resolved conflicts for merge of 27eecb70 to gingerbread

Change-Id: If064f2f4950fc1a4ff38e6927fe2120af76b26f1
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 30ee7c4..7efc6d7 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -91,16 +91,35 @@
 
 Camera::~Camera()
 {
-    disconnect();
+    // We don't need to call disconnect() here because if the CameraService
+    // thinks we are the owner of the hardware, it will hold a (strong)
+    // reference to us, and we can't possibly be here. We also don't want to
+    // call disconnect() here if we are in the same process as mediaserver,
+    // because we may be invoked by CameraService::Client::connect() and will
+    // deadlock if we call any method of ICamera here.
 }
 
-sp<Camera> Camera::connect()
+int32_t Camera::getNumberOfCameras()
+{
+    const sp<ICameraService>& cs = getCameraService();
+    if (cs == 0) return 0;
+    return cs->getNumberOfCameras();
+}
+
+status_t Camera::getCameraInfo(int cameraId,
+                               struct CameraInfo* cameraInfo) {
+    const sp<ICameraService>& cs = getCameraService();
+    if (cs == 0) return UNKNOWN_ERROR;
+    return cs->getCameraInfo(cameraId, cameraInfo);
+}
+
+sp<Camera> Camera::connect(int cameraId)
 {
     LOGV("connect");
     sp<Camera> c = new Camera();
     const sp<ICameraService>& cs = getCameraService();
     if (cs != 0) {
-        c->mCamera = cs->connect(c);
+        c->mCamera = cs->connect(c, cameraId);
     }
     if (c->mCamera != 0) {
         c->mCamera->asBinder()->linkToDeath(c);
diff --git a/camera/CameraParameters.cpp b/camera/CameraParameters.cpp
index 65fd7ac..1415493 100644
--- a/camera/CameraParameters.cpp
+++ b/camera/CameraParameters.cpp
@@ -69,8 +69,13 @@
 const char CameraParameters::KEY_ZOOM_RATIOS[] = "zoom-ratios";
 const char CameraParameters::KEY_ZOOM_SUPPORTED[] = "zoom-supported";
 const char CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED[] = "smooth-zoom-supported";
+const char CameraParameters::KEY_FOCUS_DISTANCES[] = "focus-distances";
+const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format";
+const char CameraParameters::KEY_METERING_MODE[] = "metering-mode";
+const char CameraParameters::KEY_SUPPORTED_METERING_MODES[] = "metering-mode-values";
 
 const char CameraParameters::TRUE[] = "true";
+const char CameraParameters::FOCUS_DISTANCE_INFINITY[] = "Infinity";
 
 // Values for white balance settings.
 const char CameraParameters::WHITE_BALANCE_AUTO[] = "auto";
@@ -137,6 +142,12 @@
 const char CameraParameters::FOCUS_MODE_MACRO[] = "macro";
 const char CameraParameters::FOCUS_MODE_FIXED[] = "fixed";
 const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
+const char CameraParameters::FOCUS_MODE_CONTINUOUS[] = "continuous";
+
+// Values for metering mode settings.
+const char CameraParameters::METERING_MODE_CENTER_WEIGHTED[] = "center-weighted";
+const char CameraParameters::METERING_MODE_FRAME_AVERAGE[] = "frame-average";
+const char CameraParameters::METERING_MODE_SPOT[] = "spot";
 
 CameraParameters::CameraParameters()
                 : mMap()
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 46b5478..85f1a29 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -34,12 +34,34 @@
     {
     }
 
+    // get number of cameras available
+    virtual int32_t getNumberOfCameras()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+        remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);
+        return reply.readInt32();
+    }
+
+    // get information about a camera
+    virtual status_t getCameraInfo(int cameraId,
+                                   struct CameraInfo* cameraInfo) {
+        Parcel data, reply;
+        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
+        data.writeInt32(cameraId);
+        remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);
+        cameraInfo->facing = reply.readInt32();
+        cameraInfo->orientation = reply.readInt32();
+        return reply.readInt32();
+    }
+
     // connect to camera service
-    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient)
+    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
         data.writeStrongBinder(cameraClient->asBinder());
+        data.writeInt32(cameraId);
         remote()->transact(BnCameraService::CONNECT, data, &reply);
         return interface_cast<ICamera>(reply.readStrongBinder());
     }
@@ -53,10 +75,25 @@
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
+        case GET_NUMBER_OF_CAMERAS: {
+            CHECK_INTERFACE(ICameraService, data, reply);
+            reply->writeInt32(getNumberOfCameras());
+            return NO_ERROR;
+        } break;
+        case GET_CAMERA_INFO: {
+            CHECK_INTERFACE(ICameraService, data, reply);
+            CameraInfo cameraInfo;
+            memset(&cameraInfo, 0, sizeof(cameraInfo));
+            status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
+            reply->writeInt32(cameraInfo.facing);
+            reply->writeInt32(cameraInfo.orientation);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        } break;
         case CONNECT: {
             CHECK_INTERFACE(ICameraService, data, reply);
             sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder());
-            sp<ICamera> camera = connect(cameraClient);
+            sp<ICamera> camera = connect(cameraClient, data.readInt32());
             reply->writeStrongBinder(camera->asBinder());
             return NO_ERROR;
         } break;
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index 34648b5..9a97284 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
@@ -9,11 +7,12 @@
 	SineSource.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libstagefright libmedia libutils libbinder
+	libstagefright libmedia libutils libbinder libstagefright_foundation
 
 LOCAL_C_INCLUDES:= \
 	$(JNI_H_INCLUDE) \
 	frameworks/base/media/libstagefright \
+	frameworks/base/media/libstagefright/include \
 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
 
 LOCAL_CFLAGS += -Wno-multichar
@@ -71,5 +70,3 @@
 LOCAL_MODULE:= audioloop
 
 include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 845c854..5a87f4c 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -147,7 +147,7 @@
     OMXClient client;
     CHECK_EQ(client.connect(), OK);
 
-#if 1
+#if 0
     sp<MediaSource> source = createSource(argv[1]);
 
     if (source == NULL) {
@@ -165,14 +165,15 @@
     success = success && meta->findInt32(kKeyHeight, &height);
     CHECK(success);
 #else
-    int width = 800;
+    int width = 720;
     int height = 480;
     sp<MediaSource> decoder = new DummySource(width, height);
 #endif
 
     sp<MetaData> enc_meta = new MetaData;
     // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
-    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
     enc_meta->setInt32(kKeyWidth, width);
     enc_meta->setInt32(kKeyHeight, height);
 
@@ -213,6 +214,8 @@
 
 #if 0
     CameraSource *source = CameraSource::Create();
+    source->start();
+
     printf("source = %p\n", source);
 
     for (int i = 0; i < 100; ++i) {
@@ -227,6 +230,8 @@
         buffer = NULL;
     }
 
+    source->stop();
+
     delete source;
     source = NULL;
 #endif
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index b838f32..4a1d27b 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -25,13 +25,14 @@
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include "include/ARTSPController.h"
 #include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/CachingDataSource.h>
-#include <media/stagefright/FileSource.h>
-#include <media/stagefright/HTTPDataSource.h>
+#include <media/stagefright/DataSource.h>
 #include <media/stagefright/JPEGSource.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaExtractor.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
@@ -39,6 +40,9 @@
 #include <media/stagefright/OMXCodec.h>
 #include <media/mediametadataretriever.h>
 
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MPEG4Writer.h>
+
 using namespace android;
 
 static long gNumRepetitions;
@@ -46,6 +50,8 @@
 static long gReproduceBug;  // if not -1.
 static bool gPreferSoftwareCodec;
 static bool gPlaybackAudio;
+static bool gWriteMP4;
+static String8 gWriteMP4Filename;
 
 static int64_t getNowUs() {
     struct timeval tv;
@@ -85,6 +91,7 @@
     if (gPlaybackAudio) {
         AudioPlayer *player = new AudioPlayer(NULL);
         player->setSource(rawSource);
+        rawSource.clear();
 
         player->start(true /* sourceAlreadyStarted */);
 
@@ -95,6 +102,8 @@
 
         delete player;
         player = NULL;
+
+        return;
     } else if (gReproduceBug >= 3 && gReproduceBug <= 5) {
         int64_t durationUs;
         CHECK(meta->findInt64(kKeyDuration, &durationUs));
@@ -256,6 +265,77 @@
     }
 }
 
+static void writeSourceToMP4(const sp<MediaSource> &source) {
+    sp<MPEG4Writer> writer =
+        new MPEG4Writer(gWriteMP4Filename.string());
+
+    CHECK_EQ(writer->addSource(source), OK);
+
+    sp<MetaData> params = new MetaData;
+    CHECK_EQ(writer->start(), OK);
+
+    while (!writer->reachedEOS()) {
+        usleep(100000);
+    }
+    writer->stop();
+}
+
+static void performSeekTest(const sp<MediaSource> &source) {
+    CHECK_EQ(OK, source->start());
+
+    int64_t durationUs;
+    CHECK(source->getFormat()->findInt64(kKeyDuration, &durationUs));
+
+    for (int64_t seekTimeUs = 0; seekTimeUs <= durationUs;
+            seekTimeUs += 60000ll) {
+        MediaSource::ReadOptions options;
+        options.setSeekTo(
+                seekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
+
+        MediaBuffer *buffer;
+        status_t err;
+        for (;;) {
+            err = source->read(&buffer, &options);
+
+            options.clearSeekTo();
+
+            if (err == INFO_FORMAT_CHANGED) {
+                CHECK(buffer == NULL);
+                continue;
+            }
+
+            if (err != OK) {
+                CHECK(buffer == NULL);
+                break;
+            }
+
+            if (buffer->range_length() > 0) {
+                break;
+            }
+
+            CHECK(buffer != NULL);
+
+            buffer->release();
+            buffer = NULL;
+        }
+
+        if (err == OK) {
+            int64_t timeUs;
+            CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+            printf("%lld\t%lld\t%lld\n", seekTimeUs, timeUs, seekTimeUs - timeUs);
+
+            buffer->release();
+            buffer = NULL;
+        } else {
+            printf("ERROR\n");
+            break;
+        }
+    }
+
+    CHECK_EQ(OK, source->stop());
+}
+
 static void usage(const char *me) {
     fprintf(stderr, "usage: %s\n", me);
     fprintf(stderr, "       -h(elp)\n");
@@ -268,6 +348,8 @@
     fprintf(stderr, "       -t(humbnail) extract video thumbnail or album art\n");
     fprintf(stderr, "       -s(oftware) prefer software codec\n");
     fprintf(stderr, "       -o playback audio\n");
+    fprintf(stderr, "       -w(rite) filename (write to .mp4 file)\n");
+    fprintf(stderr, "       -k seek test\n");
 }
 
 int main(int argc, char **argv) {
@@ -277,14 +359,19 @@
     bool listComponents = false;
     bool dumpProfiles = false;
     bool extractThumbnail = false;
+    bool seekTest = false;
     gNumRepetitions = 1;
     gMaxNumFrames = 0;
     gReproduceBug = -1;
     gPreferSoftwareCodec = false;
     gPlaybackAudio = false;
+    gWriteMP4 = false;
+
+    sp<ALooper> looper;
+    sp<ARTSPController> rtspController;
 
     int res;
-    while ((res = getopt(argc, argv, "han:lm:b:ptso")) >= 0) {
+    while ((res = getopt(argc, argv, "han:lm:b:ptsow:k")) >= 0) {
         switch (res) {
             case 'a':
             {
@@ -320,6 +407,13 @@
                 break;
             }
 
+            case 'w':
+            {
+                gWriteMP4 = true;
+                gWriteMP4Filename.setTo(optarg);
+                break;
+            }
+
             case 'p':
             {
                 dumpProfiles = true;
@@ -344,6 +438,12 @@
                 break;
             }
 
+            case 'k':
+            {
+                seekTest = true;
+                break;
+            }
+
             case '?':
             case 'h':
             default:
@@ -479,19 +579,10 @@
     for (int k = 0; k < argc; ++k) {
         const char *filename = argv[k];
 
-        sp<DataSource> dataSource;
-        if (!strncasecmp("http://", filename, 7)) {
-            dataSource = new HTTPDataSource(filename);
-            if (((HTTPDataSource *)dataSource.get())->connect() != OK) {
-                fprintf(stderr, "failed to connect to HTTP server.\n");
-                return -1;
-            }
-            dataSource = new CachingDataSource(dataSource, 32 * 1024, 20);
-        } else {
-            dataSource = new FileSource(filename);
-        }
+        sp<DataSource> dataSource = DataSource::CreateFromURI(filename);
 
-        if (dataSource == NULL) {
+        if ((strncasecmp(filename, "sine:", 5)
+                && strncasecmp(filename, "rtsp://", 7)) && dataSource == NULL) {
             fprintf(stderr, "Unable to create data source.\n");
             return 1;
         }
@@ -516,10 +607,28 @@
             }
             mediaSource = new SineSource(sampleRate, 1);
         } else {
-            sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
-            if (extractor == NULL) {
-                fprintf(stderr, "could not create extractor.\n");
-                return -1;
+            sp<MediaExtractor> extractor;
+
+            if (!strncasecmp("rtsp://", filename, 7)) {
+                if (looper == NULL) {
+                    looper = new ALooper;
+                    looper->start();
+                }
+
+                rtspController = new ARTSPController(looper);
+                status_t err = rtspController->connect(filename);
+                if (err != OK) {
+                    fprintf(stderr, "could not connect to rtsp server.\n");
+                    return -1;
+                }
+
+                extractor = rtspController.get();
+            } else {
+                extractor = MediaExtractor::Create(dataSource);
+                if (extractor == NULL) {
+                    fprintf(stderr, "could not create extractor.\n");
+                    return -1;
+                }
             }
 
             size_t numTracks = extractor->countTracks();
@@ -562,7 +671,20 @@
             mediaSource = extractor->getTrack(i);
         }
 
-        playSource(&client, mediaSource);
+        if (gWriteMP4) {
+            writeSourceToMP4(mediaSource);
+        } else if (seekTest) {
+            performSeekTest(mediaSource);
+        } else {
+            playSource(&client, mediaSource);
+        }
+
+        if (rtspController != NULL) {
+            rtspController->disconnect();
+            rtspController.clear();
+
+            sleep(3);
+        }
     }
 
     client.disconnect();
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 57968e3..964700b 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -92,6 +92,32 @@
     CAMERA_ERROR_SERVER_DIED = 100
 };
 
+enum {
+    CAMERA_FACING_BACK = 0,
+    CAMERA_FACING_FRONT = 1 /* The camera faces to the user */
+};
+
+struct CameraInfo {
+
+    /**
+     * The direction that the camera faces to. It should be
+     * CAMERA_FACING_BACK or CAMERA_FACING_FRONT.
+     */
+    int facing;
+
+    /**
+     * The orientation of the camera image. The value is the angle that the
+     * camera image needs to be rotated clockwise so it shows correctly on
+     * the display in its natural orientation. It should be 0, 90, 180, or 270.
+     *
+     * For example, suppose a device has a naturally tall screen, but the camera
+     * sensor is mounted in landscape. If the top side of the camera sensor is
+     * aligned with the right edge of the display in natural orientation, the
+     * value should be 90.
+     */
+    int orientation;
+};
+
 class ICameraService;
 class ICamera;
 class Surface;
@@ -112,7 +138,10 @@
 public:
             // construct a camera client from an existing remote
     static  sp<Camera>  create(const sp<ICamera>& camera);
-    static  sp<Camera>  connect();
+    static  int32_t     getNumberOfCameras();
+    static  status_t    getCameraInfo(int cameraId,
+                                      struct CameraInfo* cameraInfo);
+    static  sp<Camera>  connect(int cameraId);
                         ~Camera();
             void        init();
 
diff --git a/include/camera/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h
index d877c74..1529db7 100644
--- a/include/camera/CameraHardwareInterface.h
+++ b/include/camera/CameraHardwareInterface.h
@@ -213,8 +213,15 @@
     virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
 };
 
-/** factory function to instantiate a camera hardware object */
-extern "C" sp<CameraHardwareInterface> openCameraHardware();
+/**
+ * The functions need to be provided by the camera HAL.
+ *
+ * If getNumberOfCameras() returns N, the valid cameraId for getCameraInfo()
+ * and openCameraHardware() is 0 to N-1.
+ */
+extern "C" int HAL_getNumberOfCameras();
+extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo);
+extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId);
 
 };  // namespace android
 
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 5ea83a5..e12a694 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -65,13 +65,15 @@
     // Supported preview frame sizes in pixels.
     // Example value: "800x600,480x320". Read only.
     static const char KEY_SUPPORTED_PREVIEW_SIZES[];
-    // The image format for preview frames.
+    // The image format for preview frames. See CAMERA_MSG_PREVIEW_FRAME in
+    // frameworks/base/include/camera/Camera.h.
     // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read/write.
     static const char KEY_PREVIEW_FORMAT[];
     // Supported image formats for preview frames.
     // Example value: "yuv420sp,yuv422i-yuyv". Read only.
     static const char KEY_SUPPORTED_PREVIEW_FORMATS[];
-    // Number of preview frames per second.
+    // Number of preview frames per second. This is the target frame rate. The
+    // actual frame rate depends on the driver.
     // Example value: "15". Read/write.
     static const char KEY_PREVIEW_FRAME_RATE[];
     // Supported number of preview frames per second.
@@ -83,7 +85,8 @@
     // Supported dimensions for captured pictures in pixels.
     // Example value: "2048x1536,1024x768". Read only.
     static const char KEY_SUPPORTED_PICTURE_SIZES[];
-    // The image format for captured pictures.
+    // The image format for captured pictures. See CAMERA_MSG_COMPRESSED_IMAGE
+    // in frameworks/base/include/camera/Camera.h.
     // Example value: "jpeg" or PIXEL_FORMAT_XXX constants. Read/write.
     static const char KEY_PICTURE_FORMAT[];
     // Supported image formats for captured pictures.
@@ -119,14 +122,17 @@
     // should not set default value for this parameter.
     // Example value: "0" or "90" or "180" or "270". Write only.
     static const char KEY_ROTATION[];
-    // GPS latitude coordinate. This will be stored in JPEG EXIF header.
-    // Example value: "25.032146". Write only.
+    // GPS latitude coordinate. GPSLatitude and GPSLatitudeRef will be stored in
+    // JPEG EXIF header.
+    // Example value: "25.032146" or "-33.462809". Write only.
     static const char KEY_GPS_LATITUDE[];
-    // GPS longitude coordinate. This will be stored in JPEG EXIF header.
-    // Example value: "121.564448". Write only.
+    // GPS longitude coordinate. GPSLongitude and GPSLongitudeRef will be stored
+    // in JPEG EXIF header.
+    // Example value: "121.564448" or "-70.660286". Write only.
     static const char KEY_GPS_LONGITUDE[];
-    // GPS altitude. This will be stored in JPEG EXIF header.
-    // Example value: "21.0". Write only.
+    // GPS altitude. GPSAltitude and GPSAltitudeRef will be stored in JPEG EXIF
+    // header.
+    // Example value: "21.0" or "-5". Write only.
     static const char KEY_GPS_ALTITUDE[];
     // GPS timestamp (UTC in seconds since January 1, 1970). This should be
     // stored in JPEG EXIF header.
@@ -221,9 +227,42 @@
     // Example value: "true". Read only.
     static const char KEY_SMOOTH_ZOOM_SUPPORTED[];
 
+    // The distances (in meters) from the camera to where an object appears to
+    // be in focus. The object is sharpest at the optimal focus distance. The
+    // depth of field is the far focus distance minus near focus distance.
+    //
+    // Applications can read this parameter anytime to get the latest focus
+    // distances. If the focus mode is FOCUS_MODE_EDOF, the values may be all
+    // 0, which means focus distance is not applicable. If the focus mode is
+    // FOCUS_MODE_CONTINUOUS and autofocus has started, focus distances may
+    // change from time to time.
+    //
+    // Far focus distance > optimal focus distance > near focus distance. If
+    // the far focus distance is infinity, the value should be "Infinity" (case
+    // sensitive). The format is three float values separated by commas. The
+    // first is near focus distance. The second is optimal focus distance. The
+    // third is far focus distance.
+    // Example value: "0.95,1.9,Infinity" or "0.049,0.05,0.051". Read only.
+    static const char KEY_FOCUS_DISTANCES[];
+
+    // The image format for video frames. See CAMERA_MSG_VIDEO_FRAME in
+    // frameworks/base/include/camera/Camera.h.
+    // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read only.
+    static const char KEY_VIDEO_FRAME_FORMAT[];
+
+    // Metering mode. This affects how camera determines exposure.
+    // Example value: "spot" or METERING_MODE_XXX constants. Read/write.
+    static const char KEY_METERING_MODE[];
+    // Supported metering modes.
+    // Example value: "center-weighted,frame-average,spot". Read only.
+    static const char KEY_SUPPORTED_METERING_MODES[];
+
     // Value for KEY_ZOOM_SUPPORTED or KEY_SMOOTH_ZOOM_SUPPORTED.
     static const char TRUE[];
 
+    // Value for KEY_FOCUS_DISTANCES.
+    static const char FOCUS_DISTANCE_INFINITY[];
+
     // Values for white balance settings.
     static const char WHITE_BALANCE_AUTO[];
     static const char WHITE_BALANCE_INCANDESCENT[];
@@ -309,6 +348,21 @@
     // continuously. Applications should not call
     // CameraHardwareInterface.autoFocus in this mode.
     static const char FOCUS_MODE_EDOF[];
+    // Continuous focus mode. The camera continuously tries to focus. This is
+    // ideal for shooting video or shooting photo of moving object. Continuous
+    // focus starts when CameraHardwareInterface.autoFocus is called. Focus
+    // callback will be only called once as soon as the picture is in focus.
+    static const char FOCUS_MODE_CONTINUOUS[];
+
+    // The camera determines the exposure by giving more weight to the
+    // central part of the scene.
+    static const char METERING_MODE_CENTER_WEIGHTED[];
+    // The camera determines the exposure by averaging the entire scene,
+    // giving no weighting to any particular area.
+    static const char METERING_MODE_FRAME_AVERAGE[];
+    // The camera determines the exposure by a very small area of the scene,
+    // typically the center.
+    static const char METERING_MODE_SPOT[];
 
 private:
     DefaultKeyedVector<String8,String8>    mMap;
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index 82b1283..7d70c1e 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -30,13 +30,19 @@
 {
 public:
     enum {
-        CONNECT = IBinder::FIRST_CALL_TRANSACTION,
+        GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
+        GET_CAMERA_INFO,
+        CONNECT
     };
 
 public:
     DECLARE_META_INTERFACE(CameraService);
 
-    virtual sp<ICamera>     connect(const sp<ICameraClient>& cameraClient) = 0;
+    virtual int32_t         getNumberOfCameras() = 0;
+    virtual status_t        getCameraInfo(int cameraId,
+                                          struct CameraInfo* cameraInfo) = 0;
+    virtual sp<ICamera>     connect(const sp<ICameraClient>& cameraClient,
+                                    int cameraId) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
new file mode 100644
index 0000000..c967efb
--- /dev/null
+++ b/include/media/AudioEffect.h
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2009 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 ANDROID_AUDIOEFFECT_H
+#define ANDROID_AUDIOEFFECT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <media/EffectApi.h>
+#include <media/AudioSystem.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class effect_param_cblk_t;
+
+// ----------------------------------------------------------------------------
+
+class AudioEffect : public RefBase
+{
+public:
+
+    /*
+     *  Static methods for effect libraries management.
+     */
+
+    /*
+     *   Loads the effect library which path is given as first argument.
+     *   This must be the full path of a dynamic library (.so) implementing one or
+     *   more effect engines and exposing the effect library interface described in
+     *   EffectApi.h. The function returns a handle on the library for use by
+     *   further call to unloadEffectLibrary() to unload the library.
+     *
+     *   Parameters:
+     *          libPath:    full path of the dynamic library file in the file system.
+     *          handle:     address where to return the library handle
+     *
+     *   Returned status (from utils/Errors.h) can be:
+     *          NO_ERROR    successful operation.
+     *          PERMISSION_DENIED could not get AudioFlinger interface or
+     *                      application does not have permission to configure audio
+     *          NO_INIT     effect factory not initialized or
+     *                      library could not be loaded or
+     *                      library does not implement required functions
+     *          BAD_VALUE   invalid libPath string or handle
+     *
+     *   Returned value:
+     *          *handle updated with library handle
+     */
+    static status_t loadEffectLibrary(const char *libPath, int *handle);
+
+    /*
+     *   Unloads the effect library which handle is given as argument.
+     *
+     *   Parameters:
+     *          handle: library handle
+     *
+     *   Returned status (from utils/Errors.h) can be:
+     *          NO_ERROR    successful operation.
+     *          PERMISSION_DENIED could not get AudioFlinger interface or
+     *                      application does not have permission to configure audio
+     *          NO_INIT     effect factory not initialized
+     *          BAD_VALUE   invalid handle
+     */
+    static status_t unloadEffectLibrary(int handle);
+
+    /*
+     *  Static methods for effects enumeration.
+     */
+
+    /*
+     * Returns the number of effects available. This method together
+     * with queryEffect() is used to enumerate all effects:
+     * The enumeration sequence is:
+     *      queryNumberEffects(&num_effects);
+     *      for (i = 0; i < num_effects; i++)
+     *          queryEffect(i,...);
+     *
+     * Parameters:
+     *      numEffects:    address where the number of effects should be returned.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR   successful operation.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *      NO_INIT    effect library failed to initialize
+     *      BAD_VALUE  invalid numEffects pointer
+     *
+     * Returned value
+     *   *numEffects:     updated with number of effects available
+     */
+    static status_t queryNumberEffects(uint32_t *numEffects);
+
+    /*
+     * Returns an effect descriptor during effect
+     * enumeration.
+     *
+     * Parameters:
+     *      index:      index of the queried effect.
+     *      descriptor: address where the effect descriptor should be returned.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR        successful operation.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *      NO_INIT         effect library failed to initialize
+     *      BAD_VALUE       invalid descriptor pointer or index
+     *      INVALID_OPERATION  effect list has changed since last execution of queryNumberEffects()
+     *
+     * Returned value
+     *   *descriptor:     updated with effect descriptor
+     */
+    static status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor);
+
+
+    /*
+     * Returns the descriptor for the specified effect uuid.
+     *
+     * Parameters:
+     *      uuid:       pointer to effect uuid.
+     *      descriptor: address where the effect descriptor should be returned.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR        successful operation.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *      NO_INIT         effect library failed to initialize
+     *      BAD_VALUE       invalid uuid or descriptor pointers
+     *      NAME_NOT_FOUND  no effect with this uuid found
+     *
+     * Returned value
+     *   *descriptor updated with effect descriptor
+     */
+    static status_t getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor);
+
+
+    /*
+     * Events used by callback function (effect_callback_t).
+     */
+    enum event_type {
+        EVENT_CONTROL_STATUS_CHANGED = 0,
+        EVENT_ENABLE_STATUS_CHANGED = 1,
+        EVENT_PARAMETER_CHANGED = 2,
+        EVENT_ERROR = 3
+    };
+
+    /* Callback function notifying client application of a change in effect engine state or
+     * configuration.
+     * An effect engine can be shared by several applications but only one has the control
+     * of the engine activity and configuration at a time.
+     * The EVENT_CONTROL_STATUS_CHANGED event is received when an application loses or
+     * retrieves the control of the effect engine. Loss of control happens
+     * if another application requests the use of the engine by creating an AudioEffect for
+     * the same effect type but with a higher priority. Control is returned when the
+     * application having the control deletes its AudioEffect object.
+     * The EVENT_ENABLE_STATUS_CHANGED event is received by all applications not having the
+     * control of the effect engine when the effect is enabled or disabled.
+     * The EVENT_PARAMETER_CHANGED event is received by all applications not having the
+     * control of the effect engine when an effect parameter is changed.
+     * The EVENT_ERROR event is received when the media server process dies.
+     *
+     * Parameters:
+     *
+     * event:   type of event notified (see enum AudioEffect::event_type).
+     * user:    Pointer to context for use by the callback receiver.
+     * info:    Pointer to optional parameter according to event type:
+     *  - EVENT_CONTROL_STATUS_CHANGED:  boolean indicating if control is granted (true)
+     *  or stolen (false).
+     *  - EVENT_ENABLE_STATUS_CHANGED: boolean indicating if effect is now enabled (true)
+     *  or disabled (false).
+     *  - EVENT_PARAMETER_CHANGED: pointer to a effect_param_t structure.
+     *  - EVENT_ERROR:  status_t indicating the error (DEAD_OBJECT when media server dies).
+     */
+
+    typedef void (*effect_callback_t)(int32_t event, void* user, void *info);
+
+
+    /* Constructor.
+     * AudioEffect is the base class for creating and controlling an effect engine from
+     * the application process. Creating an AudioEffect object will create the effect engine
+     * in the AudioFlinger if no engine of the specified type exists. If one exists, this engine
+     * will be used. The application creating the AudioEffect object (or a derived class like
+     * Reverb for instance) will either receive control of the effect engine or not, depending
+     * on the priority parameter. If priority is higher than the priority used by the current
+     * effect engine owner, the control will be transfered to the new application. Otherwise
+     * control will remain to the previous application. In this case, the new application will be
+     * notified of changes in effect engine state or control ownership by the effect callback.
+     * After creating the AudioEffect, the application must call the initCheck() method and
+     * check the creation status before trying to control the effect engine (see initCheck()).
+     * If the effect is to be applied to an AudioTrack or MediaPlayer only the application
+     * must specify the audio session ID corresponding to this player.
+     */
+
+    /* Simple Constructor.
+     */
+    AudioEffect();
+
+
+    /* Constructor.
+     *
+     * Parameters:
+     *
+     * type:  type of effect created: can be null if uuid is specified. This corresponds to
+     *        the OpenSL ES interface implemented by this effect.
+     * uuid:  Uuid of effect created: can be null if type is specified. This uuid corresponds to
+     *        a particular implementation of an effect type.
+     * priority:    requested priority for effect control: the priority level corresponds to the
+     *      value of priority parameter: negative values indicate lower priorities, positive values
+     *      higher priorities, 0 being the normal priority.
+     * cbf:         optional callback function (see effect_callback_t)
+     * user:        pointer to context for use by the callback receiver.
+     * sessionID:   audio session this effect is associated to. If 0, the effect will be global to
+     *      the output mix. If not 0, the effect will be applied to all players
+     *      (AudioTrack or MediaPLayer) within the same audio session.
+     * output:  HAL audio output stream to which this effect must be attached. Leave at 0 for
+     *      automatic output selection by AudioFlinger.
+     */
+
+    AudioEffect(const effect_uuid_t *type,
+                const effect_uuid_t *uuid = NULL,
+                  int32_t priority = 0,
+                  effect_callback_t cbf = 0,
+                  void* user = 0,
+                  int sessionId = 0,
+                  audio_io_handle_t output = 0
+                  );
+
+    /* Constructor.
+     *      Same as above but with type and uuid specified by character strings
+     */
+    AudioEffect(const char *typeStr,
+                    const char *uuidStr = NULL,
+                    int32_t priority = 0,
+                    effect_callback_t cbf = 0,
+                    void* user = 0,
+                    int sessionId = 0,
+                    audio_io_handle_t output = 0
+                    );
+
+    /* Terminates the AudioEffect and unregisters it from AudioFlinger.
+     * The effect engine is also destroyed if this AudioEffect was the last controlling
+     * the engine.
+     */
+                        ~AudioEffect();
+
+    /* Initialize an uninitialized AudioEffect.
+    * Returned status (from utils/Errors.h) can be:
+    *  - NO_ERROR or ALREADY_EXISTS: successful initialization
+    *  - INVALID_OPERATION: AudioEffect is already initialized
+    *  - BAD_VALUE: invalid parameter
+    *  - NO_INIT: audio flinger or audio hardware not initialized
+    * */
+            status_t    set(const effect_uuid_t *type,
+                            const effect_uuid_t *uuid = NULL,
+                            int32_t priority = 0,
+                            effect_callback_t cbf = 0,
+                            void* user = 0,
+                            int sessionId = 0,
+                            audio_io_handle_t output = 0
+                            );
+
+    /* Result of constructing the AudioEffect. This must be checked
+     * before using any AudioEffect API.
+     * initCheck() can return:
+     *  - NO_ERROR:    the effect engine is successfully created and the application has control.
+     *  - ALREADY_EXISTS: the effect engine is successfully created but the application does not
+     *              have control.
+     *  - NO_INIT:     the effect creation failed.
+     *
+     */
+            status_t    initCheck() const;
+
+
+    /* Returns the unique effect Id for the controlled effect engine. This ID is unique
+     * system wide and is used for instance in the case of auxiliary effects to attach
+     * the effect to an AudioTrack or MediaPlayer.
+     *
+     */
+            int32_t     id() const { return mId; }
+
+    /* Returns a descriptor for the effect (see effect_descriptor_t in EffectApi.h).
+     */
+            effect_descriptor_t descriptor() const;
+
+    /* Returns effect control priority of this AudioEffect object.
+     */
+            int32_t     priority() const { return mPriority; }
+
+
+    /* Enables or disables the effect engine.
+     *
+     * Parameters:
+     *  enabled: requested enable state.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation
+     *  - INVALID_OPERATION: the application does not have control of the effect engine or the
+     *  effect is already in the requested state.
+     */
+    virtual status_t    setEnabled(bool enabled);
+            bool        getEnabled() const;
+
+    /* Sets a parameter value.
+     *
+     * Parameters:
+     *      param:  pointer to effect_param_t structure containing the parameter
+     *          and its value (See EffectApi.h).
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation.
+     *  - INVALID_OPERATION: the application does not have control of the effect engine.
+     *  - BAD_VALUE: invalid parameter identifier or value.
+     *  - DEAD_OBJECT: the effect engine has been deleted.
+     */
+     virtual status_t   setParameter(effect_param_t *param);
+
+    /* Prepare a new parameter value that will be set by next call to
+     * setParameterCommit(). This method can be used to set multiple parameters
+     * in a synchronous manner or to avoid multiple binder calls for each
+     * parameter.
+     *
+     * Parameters:
+     *      param:  pointer to effect_param_t structure containing the parameter
+     *          and its value (See EffectApi.h).
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation.
+     *  - INVALID_OPERATION: the application does not have control of the effect engine.
+     *  - NO_MEMORY: no more space available in shared memory used for deferred parameter
+     *  setting.
+     */
+     virtual status_t   setParameterDeferred(effect_param_t *param);
+
+     /* Commit all parameter values previously prepared by setParameterDeferred().
+      *
+      * Parameters:
+      *     none
+      *
+      * Returned status (from utils/Errors.h) can be:
+      *  - NO_ERROR: successful operation.
+      *  - INVALID_OPERATION: No new parameter values ready for commit.
+      *  - BAD_VALUE: invalid parameter identifier or value: there is no indication
+      *     as to which of the parameters caused this error.
+      *  - DEAD_OBJECT: the effect engine has been deleted.
+      */
+     virtual status_t   setParameterCommit();
+
+    /* Gets a parameter value.
+     *
+     * Parameters:
+     *      param:  pointer to effect_param_t structure containing the parameter
+     *          and the returned value (See EffectApi.h).
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation.
+     *  - INVALID_OPERATION: the AudioEffect was not successfully initialized.
+     *  - BAD_VALUE: invalid parameter identifier.
+     *  - DEAD_OBJECT: the effect engine has been deleted.
+     */
+     virtual status_t   getParameter(effect_param_t *param);
+
+     /* Sends a command and receives a response to/from effect engine.
+      *     See EffectApi.h for details on effect command() function, valid command codes
+      *     and formats.
+      */
+     virtual status_t command(uint32_t cmdCode,
+                              uint32_t cmdSize,
+                              void *cmdData,
+                              uint32_t *replySize,
+                              void *replyData);
+
+
+     /*
+      * Utility functions.
+      */
+
+     /* Converts the string passed as first argument to the effect_uuid_t
+      * pointed to by second argument
+      */
+     static status_t stringToGuid(const char *str, effect_uuid_t *guid);
+     /* Converts the effect_uuid_t pointed to by first argument to the
+      * string passed as second argument
+      */
+     static status_t guidToString(const effect_uuid_t *guid, char *str, size_t maxLen);
+
+protected:
+     volatile int32_t        mEnabled;           // enable state
+     int32_t                 mSessionId;         // audio session ID
+     int32_t                 mPriority;          // priority for effect control
+     status_t                mStatus;            // effect status
+     effect_callback_t       mCbf;               // callback function for status, control and
+                                                 // parameter changes notifications
+     void*                   mUserData;          // client context for callback function
+     effect_descriptor_t     mDescriptor;        // effect descriptor
+     int32_t                 mId;                // system wide unique effect engine instance ID
+
+private:
+
+     // Implements the IEffectClient interface
+    class EffectClient : public android::BnEffectClient,  public android::IBinder::DeathRecipient
+    {
+    public:
+
+        EffectClient(AudioEffect *effect) : mEffect(effect){}
+
+        // IEffectClient
+        virtual void controlStatusChanged(bool controlGranted) {
+            mEffect->controlStatusChanged(controlGranted);
+        }
+        virtual void enableStatusChanged(bool enabled) {
+            mEffect->enableStatusChanged(enabled);
+        }
+        virtual void commandExecuted(uint32_t cmdCode,
+                                     uint32_t cmdSize,
+                                     void *pCmdData,
+                                     uint32_t replySize,
+                                     void *pReplyData) {
+            mEffect->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+        }
+
+        // IBinder::DeathRecipient
+        virtual void binderDied(const wp<IBinder>& who) {mEffect->binderDied();}
+
+    private:
+        AudioEffect *mEffect;
+    };
+
+
+    friend class EffectClient;
+
+    // IEffectClient
+    void controlStatusChanged(bool controlGranted);
+    void enableStatusChanged(bool enabled);
+    void commandExecuted(uint32_t cmdCode,
+                         uint32_t cmdSize,
+                         void *pCmdData,
+                         uint32_t replySize,
+                         void *pReplyData);
+    void binderDied();
+
+
+    sp<IEffect>             mIEffect;           // IEffect binder interface
+    sp<EffectClient>        mIEffectClient;     // IEffectClient implementation
+    sp<IMemory>             mCblkMemory;        // shared memory for deferred parameter setting
+    effect_param_cblk_t*    mCblk;              // control block for deferred parameter setting
+};
+
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOEFFECT_H
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 92bc126..38e3d44 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -100,6 +100,19 @@
 
     typedef void (*callback_t)(int event, void* user, void *info);
 
+    /* Returns the minimum frame count required for the successful creation of
+     * an AudioRecord object.
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation
+     *  - NO_INIT: audio server or audio hardware not initialized
+     *  - BAD_VALUE: unsupported configuration
+     */
+
+     static status_t getMinFrameCount(int* frameCount,
+                                      uint32_t sampleRate,
+                                      int format,
+                                      int channelCount);
+
     /* Constructs an uninitialized AudioRecord. No connection with
      * AudioFlinger takes place.
      */
@@ -142,7 +155,8 @@
                                     uint32_t flags      = 0,
                                     callback_t cbf = 0,
                                     void* user = 0,
-                                    int notificationFrames = 0);
+                                    int notificationFrames = 0,
+                                    int sessionId = 0);
 
 
     /* Terminates the AudioRecord and unregisters it from AudioFlinger.
@@ -168,7 +182,8 @@
                             callback_t cbf = 0,
                             void* user = 0,
                             int notificationFrames = 0,
-                            bool threadCanCallJava = false);
+                            bool threadCanCallJava = false,
+                            int sessionId = 0);
 
 
     /* Result of constructing the AudioRecord. This must be checked
@@ -270,6 +285,16 @@
      */
             audio_io_handle_t    getInput();
 
+    /* returns the audio session ID associated to this AudioRecord.
+     *
+     * Parameters:
+     *  none.
+     *
+     * Returned value:
+     *  AudioRecord session ID.
+     */
+            int    getSessionId();
+
     /* obtains a buffer of "frameCount" frames. The buffer must be
      * filled entirely. If the track is stopped, obtainBuffer() returns
      * STOPPED instead of NO_ERROR as long as there are buffers availlable,
@@ -356,6 +381,7 @@
     uint32_t                mFlags;
     uint32_t                mChannels;
     audio_io_handle_t       mInput;
+    int                     mSessionId;
 };
 
 }; // namespace android
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index d0ccc50..9fd905f 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -168,6 +168,15 @@
         TX_DISABLE    = 0
     };
 
+    // special audio session values
+    enum audio_sessions {
+        SESSION_OUTPUT_STAGE = -1, // session for effects attached to a particular output stream
+                                   // (value must be less than 0)
+        SESSION_OUTPUT_MIX = 0,    // session for effects applied to output mix. These effects can
+                                   // be moved by audio policy manager to another output stream
+                                   // (value must be 0)
+    };
+
     /* These are static methods to control the system-wide AudioFlinger
      * only privileged processes can have access to them
      */
@@ -234,6 +243,8 @@
     static status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int stream = DEFAULT);
 
     static unsigned int  getInputFramesLost(audio_io_handle_t ioHandle);
+
+    static int newAudioSessionId();
     //
     // AudioPolicyService interface
     //
@@ -351,8 +362,12 @@
                                         uint32_t format = FORMAT_DEFAULT,
                                         uint32_t channels = CHANNEL_OUT_STEREO,
                                         output_flags flags = OUTPUT_FLAG_INDIRECT);
-    static status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
-    static status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream);
+    static status_t startOutput(audio_io_handle_t output,
+                                AudioSystem::stream_type stream,
+                                int session = 0);
+    static status_t stopOutput(audio_io_handle_t output,
+                               AudioSystem::stream_type stream,
+                               int session = 0);
     static void releaseOutput(audio_io_handle_t output);
     static audio_io_handle_t getInput(int inputSource,
                                     uint32_t samplingRate = 0,
@@ -368,6 +383,16 @@
     static status_t setStreamVolumeIndex(stream_type stream, int index);
     static status_t getStreamVolumeIndex(stream_type stream, int *index);
 
+    static uint32_t getStrategyForStream(stream_type stream);
+
+    static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
+    static status_t registerEffect(effect_descriptor_t *desc,
+                                    audio_io_handle_t output,
+                                    uint32_t strategy,
+                                    int session,
+                                    int id);
+    static status_t unregisterEffect(int id);
+
     static const sp<IAudioPolicyService>& get_audio_policy_service();
 
     // ----------------------------------------------------------------------------
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 14b30ae..4475d4a 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -102,6 +102,17 @@
 
     typedef void (*callback_t)(int event, void* user, void *info);
 
+    /* Returns the minimum frame count required for the successful creation of
+     * an AudioTrack object.
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation
+     *  - NO_INIT: audio server or audio hardware not initialized
+     */
+
+     static status_t getMinFrameCount(int* frameCount,
+                                      int streamType      =-1,
+                                      uint32_t sampleRate = 0);
+
     /* Constructs an uninitialized AudioTrack. No connection with
      * AudioFlinger takes place.
      */
@@ -138,7 +149,8 @@
                                     uint32_t flags       = 0,
                                     callback_t cbf       = 0,
                                     void* user           = 0,
-                                    int notificationFrames = 0);
+                                    int notificationFrames = 0,
+                                    int sessionId = 0);
 
     /* Creates an audio track and registers it with AudioFlinger. With this constructor,
      * The PCM data to be rendered by AudioTrack is passed in a shared memory buffer
@@ -157,7 +169,8 @@
                                     uint32_t flags      = 0,
                                     callback_t cbf      = 0,
                                     void* user          = 0,
-                                    int notificationFrames = 0);
+                                    int notificationFrames = 0,
+                                    int sessionId = 0);
 
     /* Terminates the AudioTrack and unregisters it from AudioFlinger.
      * Also destroys all resources assotiated with the AudioTrack.
@@ -182,7 +195,8 @@
                             void* user          = 0,
                             int notificationFrames = 0,
                             const sp<IMemory>& sharedBuffer = 0,
-                            bool threadCanCallJava = false);
+                            bool threadCanCallJava = false,
+                            int sessionId = 0);
 
 
     /* Result of constructing the AudioTrack. This must be checked
@@ -239,10 +253,17 @@
 
 
     /* set volume for this track, mostly used for games' sound effects
+     * left and right volumes. Levels must be <= 1.0.
      */
-            void        setVolume(float left, float right);
+            status_t    setVolume(float left, float right);
             void        getVolume(float* left, float* right);
 
+    /* set the send level for this track. An auxiliary effect should be attached
+     * to the track with attachEffect(). Level must be <= 1.0.
+     */
+            status_t    setAuxEffectSendLevel(float level);
+            void        getAuxEffectSendLevel(float* level);
+
     /* set sample rate for this track, mostly used for games' sound effects
      */
             status_t    setSampleRate(int sampleRate);
@@ -340,6 +361,31 @@
      */
             audio_io_handle_t    getOutput();
 
+    /* returns the unique ID associated to this track.
+     *
+     * Parameters:
+     *  none.
+     *
+     * Returned value:
+     *  AudioTrack ID.
+     */
+            int    getSessionId();
+
+
+    /* Attach track auxiliary output to specified effect. Used effectId = 0
+     * to detach track from effect.
+     *
+     * Parameters:
+     *
+     * effectId:  effectId obtained from AudioEffect::id().
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation
+     *  - INVALID_OPERATION: the effect is not an auxiliary effect.
+     *  - BAD_VALUE: The specified effect ID is invalid
+     */
+            status_t    attachAuxEffect(int effectId);
+
     /* obtains a buffer of "frameCount" frames. The buffer must be
      * filled entirely. If the track is stopped, obtainBuffer() returns
      * STOPPED instead of NO_ERROR as long as there are buffers availlable,
@@ -398,13 +444,15 @@
                                  int frameCount,
                                  uint32_t flags,
                                  const sp<IMemory>& sharedBuffer,
-                                 audio_io_handle_t output);
+                                 audio_io_handle_t output,
+                                 bool enforceFrameCount);
 
     sp<IAudioTrack>         mAudioTrack;
     sp<IMemory>             mCblkMemory;
     sp<AudioTrackThread>    mAudioTrackThread;
 
     float                   mVolume[2];
+    float                   mSendLevel;
     uint32_t                mFrameCount;
 
     audio_track_cblk_t*     mCblk;
@@ -420,7 +468,8 @@
 
     callback_t              mCbf;
     void*                   mUserData;
-    uint32_t                mNotificationFrames;
+    uint32_t                mNotificationFramesReq; // requested number of frames between each notification callback
+    uint32_t                mNotificationFramesAct; // actual number of frames between each notification callback
     sp<IMemory>             mSharedBuffer;
     int                     mLoopCount;
     uint32_t                mRemainingFrames;
@@ -429,6 +478,8 @@
     uint32_t                mNewPosition;
     uint32_t                mUpdatePeriod;
     uint32_t                mFlags;
+    int                     mSessionId;
+    int                     mAuxEffectId;
 };
 
 
diff --git a/include/media/EffectApi.h b/include/media/EffectApi.h
new file mode 100644
index 0000000..16fb43c
--- /dev/null
+++ b/include/media/EffectApi.h
@@ -0,0 +1,796 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTAPI_H_
+#define ANDROID_EFFECTAPI_H_
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/////////////////////////////////////////////////
+//      Effect control interface
+/////////////////////////////////////////////////
+
+// The effect control interface is exposed by each effect engine implementation. It consists of
+// a set of functions controlling the configuration, activation and process of the engine.
+// The functions are grouped in a structure of type effect_interface_s:
+//    struct effect_interface_s {
+//        effect_process_t process;
+//        effect_command_t command;
+//    };
+
+
+// effect_interface_t: Effect control interface handle.
+// The effect_interface_t serves two purposes regarding the implementation of the effect engine:
+// - 1 it is the address of a pointer to an effect_interface_s structure where the functions
+// of the effect control API for a particular effect are located.
+// - 2 it is the address of the context of a particular effect instance.
+// A typical implementation in the effect library would define a structure as follows:
+// struct effect_module_s {
+//        const struct effect_interface_s *itfe;
+//        effect_config_t config;
+//        effect_context_t context;
+// }
+// The implementation of EffectCreate() function would then allocate a structure of this
+// type and return its address as effect_interface_t
+typedef struct effect_interface_s **effect_interface_t;
+
+
+// Effect API version 1.0
+#define EFFECT_API_VERSION 0x0100 // Format 0xMMmm MM: Major version, mm: minor version
+
+// Maximum length of character strings in structures defines by this API.
+#define EFFECT_STRING_LEN_MAX 64
+
+//
+//--- Effect descriptor structure effect_descriptor_t
+//
+
+// Unique effect ID (can be generated from the following site:
+//  http://www.itu.int/ITU-T/asn1/uuid.html)
+// This format is used for both "type" and "uuid" fields of the effect descriptor structure.
+// - When used for effect type and the engine is implementing and effect corresponding to a standard
+// OpenSL ES interface, this ID must be the one defined in OpenSLES_IID.h for that interface.
+// - When used as uuid, it should be a unique UUID for this particular implementation.
+typedef struct effect_uuid_s {
+    uint32_t timeLow;
+    uint16_t timeMid;
+    uint16_t timeHiAndVersion;
+    uint16_t clockSeq;
+    uint8_t node[6];
+} effect_uuid_t;
+
+// NULL UUID definition (matches SL_IID_NULL_)
+#define EFFECT_UUID_INITIALIZER { 0xec7178ec, 0xe5e1, 0x4432, 0xa3f4, \
+                                  { 0x46, 0x57, 0xe6, 0x79, 0x52, 0x10 } }
+static const effect_uuid_t EFFECT_UUID_NULL_ = EFFECT_UUID_INITIALIZER;
+const effect_uuid_t * const EFFECT_UUID_NULL = &EFFECT_UUID_NULL_;
+const char * const EFFECT_UUID_NULL_STR = "ec7178ec-e5e1-4432-a3f4-4657e6795210";
+
+// The effect descriptor contains necessary information to facilitate the enumeration of the effect
+// engines present in a library.
+typedef struct effect_descriptor_s {
+    effect_uuid_t type;     // UUID of to the OpenSL ES interface implemented by this effect
+    effect_uuid_t uuid;     // UUID for this particular implementation
+    uint16_t apiVersion;    // Version of the effect API implemented: matches EFFECT_API_VERSION
+    uint32_t flags;         // effect engine capabilities/requirements flags (see below)
+    uint16_t cpuLoad;       // CPU load indication (see below)
+    uint16_t memoryUsage;   // Data Memory usage (see below)
+    char    name[EFFECT_STRING_LEN_MAX];   // human readable effect name
+    char    implementor[EFFECT_STRING_LEN_MAX];    // human readable effect implementor name
+} effect_descriptor_t;
+
+// CPU load and memory usage indication: each effect implementation must provide an indication of
+// its CPU and memory usage for the audio effect framework to limit the number of effects
+// instantiated at a given time on a given platform.
+// The CPU load is expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE) with 0 WS.
+// The memory usage is expressed in KB and includes only dynamically allocated memory
+
+// Definitions for flags field of effect descriptor.
+//  +---------------------------+-----------+-----------------------------------
+//  | description               | bits      | values
+//  +---------------------------+-----------+-----------------------------------
+//  | connection mode           | 0..1      | 0 insert: after track process
+//  |                           |           | 1 auxiliary: connect to track auxiliary
+//  |                           |           |  output and use send level
+//  |                           |           | 2 replace: replaces track process function;
+//  |                           |           |   must implement SRC, volume and mono to stereo.
+//  |                           |           | 3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | insertion preference      | 2..4      | 0 none
+//  |                           |           | 1 first of the chain
+//  |                           |           | 2 last of the chain
+//  |                           |           | 3 exclusive (only effect in the insert chain)
+//  |                           |           | 4..7 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Volume management         | 5..6      | 0 none
+//  |                           |           | 1 implements volume control
+//  |                           |           | 2 requires volume indication
+//  |                           |           | 3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Device indication         | 7..8      | 0 none
+//  |                           |           | 1 requires device updates
+//  |                           |           | 2..3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Sample input mode         | 9..10     | 0 direct: process() function or EFFECT_CMD_CONFIGURE
+//  |                           |           |   command must specify a buffer descriptor
+//  |                           |           | 1 provider: process() function uses the
+//  |                           |           |   bufferProvider indicated by the
+//  |                           |           |   EFFECT_CMD_CONFIGURE command to request input.
+//  |                           |           |   buffers.
+//  |                           |           | 2 both: both input modes are supported
+//  |                           |           | 3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Sample output mode        | 11..12    | 0 direct: process() function or EFFECT_CMD_CONFIGURE
+//  |                           |           |   command must specify a buffer descriptor
+//  |                           |           | 1 provider: process() function uses the
+//  |                           |           |   bufferProvider indicated by the
+//  |                           |           |   EFFECT_CMD_CONFIGURE command to request output
+//  |                           |           |   buffers.
+//  |                           |           | 2 both: both output modes are supported
+//  |                           |           | 3 reserved
+//  +---------------------------+-----------+-----------------------------------
+//  | Hardware acceleration     | 13..15    | 0 No hardware acceleration
+//  |                           |           | 1 non tunneled hw acceleration: the process() function
+//  |                           |           |   reads the samples, send them to HW accelerated
+//  |                           |           |   effect processor, reads back the processed samples
+//  |                           |           |   and returns them to the output buffer.
+//  |                           |           | 2 tunneled hw acceleration: the process() function is
+//  |                           |           |   transparent. The effect interface is only used to
+//  |                           |           |   control the effect engine. This mode is relevant for
+//  |                           |           |   global effects actually applied by the audio
+//  |                           |           |   hardware on the output stream.
+//  +---------------------------+-----------+-----------------------------------
+//  | Audio Mode indication     | 16..17    | 0 none
+//  |                           |           | 1 requires audio mode updates
+//  |                           |           | 2..3 reserved
+//  +---------------------------+-----------+-----------------------------------
+
+// Insert mode
+#define EFFECT_FLAG_TYPE_MASK           0x00000003
+#define EFFECT_FLAG_TYPE_INSERT         0x00000000
+#define EFFECT_FLAG_TYPE_AUXILIARY      0x00000001
+#define EFFECT_FLAG_TYPE_REPLACE        0x00000002
+
+// Insert preference
+#define EFFECT_FLAG_INSERT_MASK         0x0000001C
+#define EFFECT_FLAG_INSERT_ANY          0x00000000
+#define EFFECT_FLAG_INSERT_FIRST        0x00000004
+#define EFFECT_FLAG_INSERT_LAST         0x00000008
+#define EFFECT_FLAG_INSERT_EXCLUSIVE    0x0000000C
+
+
+// Volume control
+#define EFFECT_FLAG_VOLUME_MASK         0x00000060
+#define EFFECT_FLAG_VOLUME_CTRL         0x00000020
+#define EFFECT_FLAG_VOLUME_IND          0x00000040
+#define EFFECT_FLAG_VOLUME_NONE         0x00000000
+
+// Device indication
+#define EFFECT_FLAG_DEVICE_MASK         0x00000180
+#define EFFECT_FLAG_DEVICE_IND          0x00000080
+#define EFFECT_FLAG_DEVICE_NONE         0x00000000
+
+// Sample input modes
+#define EFFECT_FLAG_INPUT_MASK          0x00000600
+#define EFFECT_FLAG_INPUT_DIRECT        0x00000000
+#define EFFECT_FLAG_INPUT_PROVIDER      0x00000200
+#define EFFECT_FLAG_INPUT_BOTH          0x00000400
+
+// Sample output modes
+#define EFFECT_FLAG_OUTPUT_MASK          0x00001800
+#define EFFECT_FLAG_OUTPUT_DIRECT        0x00000000
+#define EFFECT_FLAG_OUTPUT_PROVIDER      0x00000800
+#define EFFECT_FLAG_OUTPUT_BOTH          0x00001000
+
+// Hardware acceleration mode
+#define EFFECT_FLAG_HW_ACC_MASK          0x00006000
+#define EFFECT_FLAG_HW_ACC_SIMPLE        0x00002000
+#define EFFECT_FLAG_HW_ACC_TUNNEL        0x00004000
+
+// Audio mode indication
+#define EFFECT_FLAG_AUDIO_MODE_MASK      0x00018000
+#define EFFECT_FLAG_AUDIO_MODE_IND       0x00008000
+#define EFFECT_FLAG_AUDIO_MODE_NONE      0x00000000
+
+// Forward definition of type audio_buffer_t
+typedef struct audio_buffer_s audio_buffer_t;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       process
+//
+//    Description:    Effect process function. Takes input samples as specified
+//          (count and location) in input buffer descriptor and output processed
+//          samples as specified in output buffer descriptor. If the buffer descriptor
+//          is not specified the function must use either the buffer or the
+//          buffer provider function installed by the EFFECT_CMD_CONFIGURE command.
+//          The effect framework will call the process() function after the EFFECT_CMD_ENABLE
+//          command is received and until the EFFECT_CMD_DISABLE is received. When the engine
+//          receives the EFFECT_CMD_DISABLE command it should turn off the effect gracefully
+//          and when done indicate that it is OK to stop calling the process() function by
+//          returning the -ENODATA status.
+//
+//    NOTE: the process() function implementation should be "real-time safe" that is
+//      it should not perform blocking calls: malloc/free, sleep, read/write/open/close,
+//      pthread_cond_wait/pthread_mutex_lock...
+//
+//    Input:
+//          effect_interface_t: handle to the effect interface this function
+//              is called on.
+//          inBuffer:   buffer descriptor indicating where to read samples to process.
+//              If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command.
+//
+//          inBuffer:   buffer descriptor indicating where to write processed samples.
+//              If NULL, use the configuration passed by EFFECT_CMD_CONFIGURE command.
+//
+//    Output:
+//        returned value:    0 successful operation
+//                          -ENODATA the engine has finished the disable phase and the framework
+//                                  can stop calling process()
+//                          -EINVAL invalid interface handle or
+//                                  invalid input/output buffer description
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_process_t)(effect_interface_t self,
+                                    audio_buffer_t *inBuffer,
+                                    audio_buffer_t *outBuffer);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       command
+//
+//    Description:    Send a command and receive a response to/from effect engine.
+//
+//    Input:
+//          effect_interface_t: handle to the effect interface this function
+//              is called on.
+//          cmdCode:    command code: the command can be a standardized command defined in
+//              effect_command_e (see below) or a proprietary command.
+//          cmdSize:    size of command in bytes
+//          pCmdData:   pointer to command data
+//          pReplyData: pointer to reply data
+//
+//    Input/Output:
+//          replySize: maximum size of reply data as input
+//                      actual size of reply data as output
+//
+//    Output:
+//          returned value: 0       successful operation
+//                          -EINVAL invalid interface handle or
+//                                  invalid command/reply size or format according to command code
+//              The return code should be restricted to indicate problems related to the this
+//              API specification. Status related to the execution of a particular command should be
+//              indicated as part of the reply field.
+//
+//          *pReplyData updated with command response
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_command_t)(effect_interface_t self,
+                                    uint32_t cmdCode,
+                                    uint32_t cmdSize,
+                                    void *pCmdData,
+                                    uint32_t *replySize,
+                                    void *pReplyData);
+
+
+// Effect control interface definition
+struct effect_interface_s {
+    effect_process_t process;
+    effect_command_t command;
+};
+
+
+//
+//--- Standardized command codes for command() function
+//
+enum effect_command_e {
+   EFFECT_CMD_INIT,                 // initialize effect engine
+   EFFECT_CMD_CONFIGURE,            // configure effect engine (see effect_config_t)
+   EFFECT_CMD_RESET,                // reset effect engine
+   EFFECT_CMD_ENABLE,               // enable effect process
+   EFFECT_CMD_DISABLE,              // disable effect process
+   EFFECT_CMD_SET_PARAM,            // set parameter immediately (see effect_param_t)
+   EFFECT_CMD_SET_PARAM_DEFERRED,   // set parameter deferred
+   EFFECT_CMD_SET_PARAM_COMMIT,     // commit previous set parameter deferred
+   EFFECT_CMD_GET_PARAM,            // get parameter
+   EFFECT_CMD_SET_DEVICE,           // set audio device (see audio_device_e)
+   EFFECT_CMD_SET_VOLUME,           // set volume
+   EFFECT_CMD_SET_AUDIO_MODE,       // set the audio mode (normal, ring, ...)
+   EFFECT_CMD_FIRST_PROPRIETARY = 0x10000 // first proprietary command code
+};
+
+//==================================================================================================
+// command: EFFECT_CMD_INIT
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Initialize effect engine: All configurations return to default
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_CONFIGURE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Apply new audio parameters configurations for input and output buffers
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_config_t)
+//  data: effect_config_t
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_RESET
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Reset the effect engine. Keep configuration but resets state and buffer content
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_ENABLE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Enable the process. Called by the framework before the first call to process()
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_DISABLE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Disable the process. Called by the framework after the last call to process()
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_SET_PARAM
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set a parameter and apply it immediately
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_param_t) + size of param and value
+//  data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_SET_PARAM_DEFERRED
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set a parameter but apply it only when receiving EFFECT_CMD_SET_PARAM_COMMIT command
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_param_t) + size of param and value
+//  data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_SET_PARAM_COMMIT
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Apply all previously received EFFECT_CMD_SET_PARAM_DEFERRED commands
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: 0
+//  data: N/A
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(int)
+//  data: status
+//==================================================================================================
+// command: EFFECT_CMD_GET_PARAM
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Get a parameter value
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(effect_param_t) + size of param
+//  data: effect_param_t + param
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: sizeof(effect_param_t) + size of param and value
+//  data: effect_param_t + param + value. See effect_param_t definition below for value offset
+//==================================================================================================
+// command: EFFECT_CMD_SET_DEVICE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set the rendering device the audio output path is connected to. See audio_device_e for device
+//  values.
+//  The effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to receive this
+//  command when the device changes
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(uint32_t)
+//  data: audio_device_e
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_SET_VOLUME
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set and get volume. Used by audio framework to delegate volume control to effect engine.
+//  The effect implementation must set EFFECT_FLAG_VOLUME_IND or EFFECT_FLAG_VOLUME_CTRL flag in
+//  its descriptor to receive this command before every call to process() function
+//  If EFFECT_FLAG_VOLUME_CTRL flag is set in the effect descriptor, the effect engine must return
+//  the volume that should be applied before the effect is processed. The overall volume (the volume
+//  actually applied by the effect engine multiplied by the returned value) should match the value
+//  indicated in the command.
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: n * sizeof(uint32_t)
+//  data: volume for each channel defined in effect_config_t for output buffer expressed in
+//      8.24 fixed point format
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: n * sizeof(uint32_t) / 0
+//  data: - if EFFECT_FLAG_VOLUME_CTRL is set in effect descriptor:
+//              volume for each channel defined in effect_config_t for output buffer expressed in
+//              8.24 fixed point format
+//        - if EFFECT_FLAG_VOLUME_CTRL is not set in effect descriptor:
+//              N/A
+//  It is legal to receive a null pointer as pReplyData in which case the effect framework has
+//  delegated volume control to another effect
+//==================================================================================================
+// command: EFFECT_CMD_SET_AUDIO_MODE
+//--------------------------------------------------------------------------------------------------
+// description:
+//  Set the audio mode. The effect implementation must set EFFECT_FLAG_AUDIO_MODE_IND flag in its
+//  descriptor to receive this command when the audio mode changes.
+//--------------------------------------------------------------------------------------------------
+// command format:
+//  size: sizeof(uint32_t)
+//  data: audio_mode_e
+//--------------------------------------------------------------------------------------------------
+// reply format:
+//  size: 0
+//  data: N/A
+//==================================================================================================
+// command: EFFECT_CMD_FIRST_PROPRIETARY
+//--------------------------------------------------------------------------------------------------
+// description:
+//  All proprietary effect commands must use command codes above this value. The size and format of
+//  command and response fields is free in this case
+//==================================================================================================
+
+
+// Audio buffer descriptor used by process(), bufferProvider() functions and buffer_config_t
+// structure. Multi-channel audio is always interleaved. The channel order is from LSB to MSB with
+// regard to the channel mask definition in audio_channels_e e.g :
+// Stereo: left, right
+// 5 point 1: front left, front right, front center, low frequency, back left, back right
+// The buffer size is expressed in frame count, a frame being composed of samples for all
+// channels at a given time. Frame size for unspecified format (AUDIO_FORMAT_OTHER) is 8 bit by
+// definition
+struct audio_buffer_s {
+    size_t   frameCount;        // number of frames in buffer
+    union {
+        void*       raw;        // raw pointer to start of buffer
+        int32_t*    s32;        // pointer to signed 32 bit data at start of buffer
+        int16_t*    s16;        // pointer to signed 16 bit data at start of buffer
+        uint8_t*    u8;         // pointer to unsigned 8 bit data at start of buffer
+    };
+};
+
+// The buffer_provider_s structure contains functions that can be used
+// by the effect engine process() function to query and release input
+// or output audio buffer.
+// The getBuffer() function is called to retrieve a buffer where data
+// should read from or written to by process() function.
+// The releaseBuffer() function MUST be called when the buffer retrieved
+// with getBuffer() is not needed anymore.
+// The process function should use the buffer provider mechanism to retrieve
+// input or output buffer if the inBuffer or outBuffer passed as argument is NULL
+// and the buffer configuration (buffer_config_t) given by the EFFECT_CMD_CONFIGURE
+// command did not specify an audio buffer.
+
+typedef int32_t (* buffer_function_t)(void *cookie, audio_buffer_t *buffer);
+
+typedef struct buffer_provider_s {
+    buffer_function_t getBuffer;       // retrieve next buffer
+    buffer_function_t releaseBuffer;   // release used buffer
+    void       *cookie;                // for use by client of buffer provider functions
+} buffer_provider_t;
+
+
+// The buffer_config_s structure specifies the input or output audio format
+// to be used by the effect engine. It is part of the effect_config_t
+// structure that defines both input and output buffer configurations and is
+// passed by the EFFECT_CMD_CONFIGURE command.
+typedef struct buffer_config_s {
+    audio_buffer_t  buffer;     // buffer for use by process() function if not passed explicitly
+    uint32_t   samplingRate;    // sampling rate
+    uint32_t   channels;        // channel mask (see audio_channels_e)
+    buffer_provider_t bufferProvider;   // buffer provider
+    uint8_t    format;          // Audio format  (see audio_format_e)
+    uint8_t    accessMode;      // read/write or accumulate in buffer (effect_buffer_access_e)
+    uint16_t   mask;            // indicates which of the above fields is valid
+} buffer_config_t;
+
+// Sample format
+enum audio_format_e {
+    SAMPLE_FORMAT_PCM_S15,   // PCM signed 16 bits
+    SAMPLE_FORMAT_PCM_U8,    // PCM unsigned 8 bits
+    SAMPLE_FORMAT_PCM_S7_24, // PCM signed 7.24 fixed point representation
+    SAMPLE_FORMAT_OTHER      // other format (e.g. compressed)
+};
+
+// Channel mask
+enum audio_channels_e {
+    CHANNEL_FRONT_LEFT = 0x1,                   // front left channel
+    CHANNEL_FRONT_RIGHT = 0x2,                  // front right channel
+    CHANNEL_FRONT_CENTER = 0x4,                // front center channel
+    CHANNEL_LOW_FREQUENCY = 0x8,               // low frequency channel
+    CHANNEL_BACK_LEFT = 0x10,                   // back left channel
+    CHANNEL_BACK_RIGHT = 0x20,                  // back right channel
+    CHANNEL_FRONT_LEFT_OF_CENTER = 0x40,       // front left of center channel
+    CHANNEL_FRONT_RIGHT_OF_CENTER = 0x80,      // front right of center channel
+    CHANNEL_BACK_CENTER = 0x100,                // back center channel
+    CHANNEL_MONO = CHANNEL_FRONT_LEFT,
+    CHANNEL_STEREO = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT),
+    CHANNEL_QUAD = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT),
+    CHANNEL_SURROUND = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_BACK_CENTER),
+    CHANNEL_5POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT),
+    CHANNEL_7POINT1 = (CHANNEL_FRONT_LEFT | CHANNEL_FRONT_RIGHT |
+            CHANNEL_FRONT_CENTER | CHANNEL_LOW_FREQUENCY | CHANNEL_BACK_LEFT | CHANNEL_BACK_RIGHT |
+            CHANNEL_FRONT_LEFT_OF_CENTER | CHANNEL_FRONT_RIGHT_OF_CENTER),
+};
+
+// Render device
+enum audio_device_e {
+    DEVICE_EARPIECE = 0x1,                      // earpiece
+    DEVICE_SPEAKER = 0x2,                       // speaker
+    DEVICE_WIRED_HEADSET = 0x4,                 // wired headset, with microphone
+    DEVICE_WIRED_HEADPHONE = 0x8,               // wired headphone, without microphone
+    DEVICE_BLUETOOTH_SCO = 0x10,                // generic bluetooth SCO
+    DEVICE_BLUETOOTH_SCO_HEADSET = 0x20,        // bluetooth SCO headset
+    DEVICE_BLUETOOTH_SCO_CARKIT = 0x40,         // bluetooth SCO car kit
+    DEVICE_BLUETOOTH_A2DP = 0x80,               // generic bluetooth A2DP
+    DEVICE_BLUETOOTH_A2DP_HEADPHONES = 0x100,   // bluetooth A2DP headphones
+    DEVICE_BLUETOOTH_A2DP_SPEAKER = 0x200,      // bluetooth A2DP speakers
+    DEVICE_AUX_DIGITAL = 0x400,                 // digital output
+    DEVICE_EXTERNAL_SPEAKER = 0x800             // external speaker (stereo and High quality)
+};
+
+// Audio mode
+enum audio_mode_e {
+    AUDIO_MODE_NORMAL,      // phone idle
+    AUDIO_MODE_RINGTONE,    // phone ringing
+    AUDIO_MODE_IN_CALL      // phone call connected
+};
+
+// Values for "accessMode" field of buffer_config_t:
+//   overwrite, read only, accumulate (read/modify/write)
+enum effect_buffer_access_e {
+    EFFECT_BUFFER_ACCESS_WRITE,
+    EFFECT_BUFFER_ACCESS_READ,
+    EFFECT_BUFFER_ACCESS_ACCUMULATE
+
+};
+
+// Values for bit field "mask" in buffer_config_t. If a bit is set, the corresponding field
+// in buffer_config_t must be taken into account when executing the EFFECT_CMD_CONFIGURE command
+#define EFFECT_CONFIG_BUFFER    0x0001  // buffer field must be taken into account
+#define EFFECT_CONFIG_SMP_RATE  0x0002  // samplingRate field must be taken into account
+#define EFFECT_CONFIG_CHANNELS  0x0004  // channels field must be taken into account
+#define EFFECT_CONFIG_FORMAT    0x0008  // format field must be taken into account
+#define EFFECT_CONFIG_ACC_MODE  0x0010  // accessMode field must be taken into account
+#define EFFECT_CONFIG_PROVIDER  0x0020  // bufferProvider field must be taken into account
+#define EFFECT_CONFIG_ALL (EFFECT_CONFIG_BUFFER | EFFECT_CONFIG_SMP_RATE | \
+                           EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT | \
+                           EFFECT_CONFIG_ACC_MODE | EFFECT_CONFIG_PROVIDER)
+
+
+// effect_config_s structure describes the format of the pCmdData argument of EFFECT_CMD_CONFIGURE
+// command to configure audio parameters and buffers for effect engine input and output.
+typedef struct effect_config_s {
+    buffer_config_t   inputCfg;
+    buffer_config_t   outputCfg;;
+} effect_config_t;
+
+
+// effect_param_s structure describes the format of the pCmdData argument of EFFECT_CMD_SET_PARAM
+// command and pCmdData and pReplyData of EFFECT_CMD_GET_PARAM command.
+// psize and vsize represent the actual size of parameter and value.
+//
+// NOTE: the start of value field inside the data field is always on a 32 bit boundary:
+//
+//  +-----------+
+//  | status    | sizeof(int)
+//  +-----------+
+//  | psize     | sizeof(int)
+//  +-----------+
+//  | vsize     | sizeof(int)
+//  +-----------+
+//  |           |   |           |
+//  ~ parameter ~   > psize     |
+//  |           |   |           >  ((psize - 1)/sizeof(int) + 1) * sizeof(int)
+//  +-----------+               |
+//  | padding   |               |
+//  +-----------+
+//  |           |   |
+//  ~ value     ~   > vsize
+//  |           |   |
+//  +-----------+
+
+typedef struct effect_param_s {
+    int32_t     status;     // Transaction status (unused for command, used for reply)
+    uint32_t    psize;      // Parameter size
+    uint32_t    vsize;      // Value size
+    char        data[];     // Start of Parameter + Value data
+} effect_param_t;
+
+
+/////////////////////////////////////////////////
+//      Effect library interface
+/////////////////////////////////////////////////
+
+// An effect library is required to implement and expose the following functions
+// to enable effect enumeration and instantiation. The name of these functions must be as
+// specified here as the effect framework will get the function address with dlsym():
+//
+// - effect_QueryNumberEffects_t EffectQueryNumberEffects;
+// - effect_QueryEffect_t EffectQueryEffect;
+// - effect_CreateEffect_t EffectCreate;
+// - effect_ReleaseEffect_t EffectRelease;
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectQueryNumberEffects
+//
+//    Description:    Returns the number of different effects exposed by the
+//          library. Each effect must have a unique effect uuid (see
+//          effect_descriptor_t). This function together with EffectQueryEffect()
+//          is used to enumerate all effects present in the library.
+//
+//    Input/Output:
+//          pNumEffects:    address where the number of effects should be returned.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     library failed to initialize
+//                          -EINVAL     invalid pNumEffects
+//        *pNumEffects:     updated with number of effects in library
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_QueryNumberEffects_t)(uint32_t *pNumEffects);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectQueryEffect
+//
+//    Description:    Returns the descriptor of the effect engine which index is
+//          given as first argument.
+//          See effect_descriptor_t for details on effect descriptors.
+//          This function together with EffectQueryNumberEffects() is used to enumerate all
+//          effects present in the library. The enumeration sequence is:
+//              EffectQueryNumberEffects(&num_effects);
+//              for (i = 0; i < num_effects; i++)
+//                  EffectQueryEffect(i,...);
+//
+//    Input/Output:
+//          index:          index of the effect
+//          pDescriptor:    address where to return the effect descriptor.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     library failed to initialize
+//                          -EINVAL     invalid pDescriptor or index
+//                          -ENOSYS     effect list has changed since last execution of
+//                                      EffectQueryNumberEffects()
+//                          -ENOENT     no more effect available
+//        *pDescriptor:     updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_QueryEffect_t)(uint32_t index,
+                                        effect_descriptor_t *pDescriptor);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectCreate
+//
+//    Description:    Creates an effect engine of the specified type and returns an
+//          effect control interface on this engine. The function will allocate the
+//          resources for an instance of the requested effect engine and return
+//          a handle on the effect control interface.
+//
+//    Input:
+//          uuid:    pointer to the effect uuid.
+//          sessionId:  audio session to which this effect instance will be attached. All effects
+//              created with the same session ID are connected in series and process the same signal
+//              stream. Knowing that two effects are part of the same effect chain can help the
+//              library implement some kind of optimizations.
+//          ioId:   identifies the output or input stream this effect is directed to at audio HAL.
+//              For future use especially with tunneled HW accelerated effects
+//
+//    Input/Output:
+//          pInterface:    address where to return the effect interface.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     library failed to initialize
+//                          -EINVAL     invalid pEffectUuid or pInterface
+//                          -ENOENT     no effect with this uuid found
+//        *pInterface:     updated with the effect interface handle.
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_CreateEffect_t)(effect_uuid_t *uuid,
+                                         int32_t sessionId,
+                                         int32_t ioId,
+                                         effect_interface_t *pInterface);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectRelease
+//
+//    Description:    Releases the effect engine whose handle is given as argument.
+//          All resources allocated to this particular instance of the effect are
+//          released.
+//
+//    Input:
+//          interface:    handle on the effect interface to be released.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     library failed to initialize
+//                          -EINVAL     invalid interface handle
+//
+////////////////////////////////////////////////////////////////////////////////
+typedef int32_t (*effect_ReleaseEffect_t)(effect_interface_t interface);
+
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTAPI_H_*/
diff --git a/include/media/EffectBassBoostApi.h b/include/media/EffectBassBoostApi.h
new file mode 100644
index 0000000..75f8d78
--- /dev/null
+++ b/include/media/EffectBassBoostApi.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTBASSBOOSTAPI_H_
+#define ANDROID_EFFECTBASSBOOSTAPI_H_
+
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_BASSBOOST_ = { 0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_BASSBOOST = &SL_IID_BASSBOOST_;
+#endif //OPENSL_ES_H_
+
+/* enumerated parameter settings for BassBoost effect */
+typedef enum
+{
+    BASSBOOST_PARAM_STRENGTH_SUPPORTED,
+    BASSBOOST_PARAM_STRENGTH
+} t_bassboost_params;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTBASSBOOSTAPI_H_*/
diff --git a/include/media/EffectEnvironmentalReverbApi.h b/include/media/EffectEnvironmentalReverbApi.h
new file mode 100644
index 0000000..2233e3f
--- /dev/null
+++ b/include/media/EffectEnvironmentalReverbApi.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_
+#define ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_
+
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_ENVIRONMENTALREVERB_ = { 0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, { 0x4e, 0x23, 0x4d, 0x6, 0x83, 0x9e } };
+const effect_uuid_t * const SL_IID_ENVIRONMENTALREVERB = &SL_IID_ENVIRONMENTALREVERB_;
+#endif //OPENSL_ES_H_
+
+/* enumerated parameter settings for environmental reverb effect */
+typedef enum
+{
+    // Parameters below are as defined in OpenSL ES specification for environmental reverb interface
+    REVERB_PARAM_ROOM_LEVEL,            // in millibels,    range -6000 to 0
+    REVERB_PARAM_ROOM_HF_LEVEL,         // in millibels,    range -4000 to 0
+    REVERB_PARAM_DECAY_TIME,            // in milliseconds, range 100 to 20000
+    REVERB_PARAM_DECAY_HF_RATIO,        // in permilles,    range 100 to 1000
+    REVERB_PARAM_REFLECTIONS_LEVEL,     // in millibels,    range -6000 to 0
+    REVERB_PARAM_REFLECTIONS_DELAY,     // in milliseconds, range 0 to 65
+    REVERB_PARAM_REVERB_LEVEL,          // in millibels,    range -6000 to 0
+    REVERB_PARAM_REVERB_DELAY,          // in milliseconds, range 0 to 65
+    REVERB_PARAM_DIFFUSION,             // in permilles,    range 0 to 1000
+    REVERB_PARAM_DENSITY,               // in permilles,    range 0 to 1000
+    REVERB_PARAM_PROPERTIES,
+    REVERB_PARAM_BYPASS
+} t_env_reverb_params;
+
+//t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.
+typedef struct s_reverb_settings {
+    int16_t roomLevel;
+    int16_t roomHFLevel;
+    int32_t decayTime;
+    int16_t decayHFRatio;
+    int16_t reflectionsLevel;
+    int32_t reflectionsDelay;
+    int16_t reverbLevel;
+    int32_t reverbDelay;
+    int16_t diffusion;
+    int16_t density;
+} __attribute__((packed)) t_reverb_settings;
+
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTENVIRONMENTALREVERBAPI_H_*/
diff --git a/include/media/EffectEqualizerApi.h b/include/media/EffectEqualizerApi.h
new file mode 100644
index 0000000..0492ea0
--- /dev/null
+++ b/include/media/EffectEqualizerApi.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTEQUALIZERAPI_H_
+#define ANDROID_EFFECTEQUALIZERAPI_H_
+
+#include <media/EffectApi.h>
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_EQUALIZER_ = { 0x0bed4300, 0xddd6, 0x11db, 0x8f34, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_EQUALIZER = &SL_IID_EQUALIZER_;
+#endif //OPENSL_ES_H_
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/* enumerated parameters for Equalizer effect */
+typedef enum
+{
+    EQ_PARAM_NUM_BANDS,             // Gets the number of frequency bands that the equalizer supports.
+    EQ_PARAM_LEVEL_RANGE,           // Returns the minimum and maximum band levels supported.
+    EQ_PARAM_BAND_LEVEL,            // Gets/Sets the gain set for the given equalizer band.
+    EQ_PARAM_CENTER_FREQ,           // Gets the center frequency of the given band.
+    EQ_PARAM_BAND_FREQ_RANGE,       // Gets the frequency range of the given frequency band.
+    EQ_PARAM_GET_BAND,              // Gets the band that has the most effect on the given frequency.
+    EQ_PARAM_CUR_PRESET,            // Gets/Sets the current preset.
+    EQ_PARAM_GET_NUM_OF_PRESETS,    // Gets the total number of presets the equalizer supports.
+    EQ_PARAM_GET_PRESET_NAME,       // Gets the preset name based on the index.
+    EQ_PARAM_PROPERTIES             // Gets/Sets all parameters at a time.
+} t_equalizer_params;
+
+//t_equalizer_settings groups all current equalizer setting for backup and restore.
+typedef struct s_equalizer_settings {
+    uint16_t curPreset;
+    uint16_t numBands;
+    uint16_t bandLevels[];
+} t_equalizer_settings;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTEQUALIZERAPI_H_*/
diff --git a/include/media/EffectPresetReverbApi.h b/include/media/EffectPresetReverbApi.h
new file mode 100644
index 0000000..53205bb
--- /dev/null
+++ b/include/media/EffectPresetReverbApi.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTPRESETREVERBAPI_H_
+#define ANDROID_EFFECTPRESETREVERBAPI_H_
+
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_PRESETREVERB_ = { 0x47382d60, 0xddd8, 0x11db, 0xbf3a, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_PRESETREVERB = &SL_IID_PRESETREVERB_;
+#endif //OPENSL_ES_H_
+
+/* enumerated parameter settings for preset reverb effect */
+typedef enum
+{
+    REVERB_PARAM_PRESET
+} t_preset_reverb_params;
+
+
+typedef enum
+{
+    REVERB_PRESET_NONE,
+    REVERB_PRESET_SMALLROOM,
+    REVERB_PRESET_MEDIUMROOM,
+    REVERB_PRESET_LARGEROOM,
+    REVERB_PRESET_MEDIUMHALL,
+    REVERB_PRESET_LARGEHALL,
+    REVERB_PRESET_PLATE
+} t_reverb_presets;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTPRESETREVERBAPI_H_*/
diff --git a/include/media/EffectVirtualizerApi.h b/include/media/EffectVirtualizerApi.h
new file mode 100644
index 0000000..c3d5131
--- /dev/null
+++ b/include/media/EffectVirtualizerApi.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTVIRTUALIZERAPI_H_
+#define ANDROID_EFFECTVIRTUALIZERAPI_H_
+
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_VIRTUALIZER_ = { 0x37cc2c00, 0xdddd, 0x11db, 0x8577, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_VIRTUALIZER = &SL_IID_VIRTUALIZER_;
+#endif //OPENSL_ES_H_
+
+/* enumerated parameter settings for virtualizer effect */
+typedef enum
+{
+    VIRTUALIZER_PARAM_STRENGTH_SUPPORTED,
+    VIRTUALIZER_PARAM_STRENGTH
+} t_virtualizer_params;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTVIRTUALIZERAPI_H_*/
diff --git a/include/media/EffectVisualizerApi.h b/include/media/EffectVisualizerApi.h
new file mode 100644
index 0000000..bef1a4f
--- /dev/null
+++ b/include/media/EffectVisualizerApi.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTVISUALIZERAPI_H_
+#define ANDROID_EFFECTVISUALIZERAPI_H_
+
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_VISUALIZATION_ =
+    { 0xe46b26a0, 0xdddd, 0x11db, 0x8afd, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_VISUALIZATION = &SL_IID_VISUALIZATION_;
+#endif //OPENSL_ES_H_
+
+#define VISUALIZER_CAPTURE_SIZE_MAX 1024  // maximum capture size in samples
+#define VISUALIZER_CAPTURE_SIZE_MIN 128   // minimum capture size in samples
+
+/* enumerated parameters for Visualizer effect */
+typedef enum
+{
+    VISU_PARAM_CAPTURE_SIZE,        // Sets the number PCM samples in the capture.
+} t_visualizer_params;
+
+/* commands */
+typedef enum
+{
+    VISU_CMD_CAPTURE = EFFECT_CMD_FIRST_PROPRIETARY, // Gets the latest PCM capture.
+}t_visualizer_cmds;
+
+// VISU_CMD_CAPTURE retrieves the latest PCM snapshot captured by the visualizer engine.
+// It returns the number of samples specified by VISU_PARAM_CAPTURE_SIZE
+// in 8 bit unsigned format (0 = 0x80)
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTVISUALIZERAPI_H_*/
diff --git a/include/media/EffectsFactoryApi.h b/include/media/EffectsFactoryApi.h
new file mode 100644
index 0000000..0ed1a14
--- /dev/null
+++ b/include/media/EffectsFactoryApi.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTSFACTORYAPI_H_
+#define ANDROID_EFFECTSFACTORYAPI_H_
+
+#include <errno.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <media/EffectApi.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/////////////////////////////////////////////////
+//      Effect factory interface
+/////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectQueryNumberEffects
+//
+//    Description:    Returns the number of different effects in all loaded libraries.
+//          Each effect must have a different effect uuid (see
+//          effect_descriptor_t). This function together with EffectQueryEffect()
+//          is used to enumerate all effects present in all loaded libraries.
+//          Each time EffectQueryNumberEffects() is called, the factory must
+//          reset the index of the effect descriptor returned by next call to
+//          EffectQueryEffect() to restart enumeration from the beginning.
+//
+//    Input/Output:
+//          pNumEffects:    address where the number of effects should be returned.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pNumEffects
+//        *pNumEffects:     updated with number of effects in factory
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectQueryNumberEffects(uint32_t *pNumEffects);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectQueryEffect
+//
+//    Description:    Returns a descriptor of the next available effect.
+//          See effect_descriptor_t for a details on effect descriptor.
+//          This function together with EffectQueryNumberEffects() is used to enumerate all
+//          effects present in all loaded libraries. The enumeration sequence is:
+//              EffectQueryNumberEffects(&num_effects);
+//              for (i = 0; i < num_effects; i++)
+//                  EffectQueryEffect(i,...);
+//
+//    Input/Output:
+//          pDescriptor:    address where to return the effect descriptor.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENOENT     no more effect available
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pDescriptor
+//                          -ENOSYS     effect list has changed since last execution of EffectQueryNumberEffects()
+//        *pDescriptor:     updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectCreate
+//
+//    Description:    Creates an effect engine of the specified type and returns an
+//          effect control interface on this engine. The function will allocate the
+//          resources for an instance of the requested effect engine and return
+//          a handler on the effect control interface.
+//
+//    Input:
+//          pEffectUuid:    pointer to the effect uuid.
+//          sessionId:  audio session to which this effect instance will be attached. All effects created
+//              with the same session ID are connected in series and process the same signal stream.
+//              Knowing that two effects are part of the same effect chain can help the library implement
+//              some kind of optimizations.
+//          ioId:   identifies the output or input stream this effect is directed to at audio HAL. For future
+//              use especially with tunneled HW accelerated effects
+//
+//    Input/Output:
+//          pInterface:    address where to return the effect interface.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pEffectUuid or pInterface
+//                          -ENOENT     no effect with this uuid found
+//        *pInterface:     updated with the effect interface.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectCreate(effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t ioId, effect_interface_t *pInterface);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectRelease
+//
+//    Description:    Releases the effect engine whose handler is given as argument.
+//          All resources allocated to this particular instance of the effect are
+//          released.
+//
+//    Input:
+//          interface:    handler on the effect interface to be released.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid interface handler
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectRelease(effect_interface_t interface);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectLoadLibrary
+//
+//    Description:    Loads the effect library which path is given as first argument.
+//          This must be the full path of a dynamic library (.so) implementing one or
+//          more effect engines and exposing the effect library interface described in
+//          EffectApi.h. The function returns a handle on the library for used by
+//          further call to EffectUnloadLibrary() to unload the library.
+//
+//    Input:
+//          libPath:    full path of the dynamic library file in the file system.
+//
+//          handle:     address where to return the library handle
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     effect factory not initialized or
+//                                      library could not be loaded or
+//                                      library does not implement required functions
+//                          -EINVAL     invalid libPath string or handle
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectLoadLibrary(const char *libPath, int *handle);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectUnloadLibrary
+//
+//    Description:  Unloads the effect library which handle is given as argument.
+//
+//    Input:
+//          handle: library handle
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     effect factory not initialized
+//                          -ENOENT     invalid handle
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectUnloadLibrary(int handle);
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectGetDescriptor
+//
+//    Description:    Returns the descriptor of the effect which uuid is pointed
+//          to by first argument.
+//
+//    Input:
+//          pEffectUuid:    pointer to the effect uuid.
+//
+//    Input/Output:
+//          pDescriptor:    address where to return the effect descriptor.
+//
+//    Output:
+//        returned value:    0          successful operation.
+//                          -ENODEV     factory failed to initialize
+//                          -EINVAL     invalid pEffectUuid or pDescriptor
+//                          -ENOENT     no effect with this uuid found
+//        *pDescriptor:     updated with the effect descriptor.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectGetDescriptor(effect_uuid_t *pEffectUuid, effect_descriptor_t *pDescriptor);
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//    Function:       EffectIsNullUuid
+//
+//    Description:    Helper function to compare effect uuid to EFFECT_UUID_NULL
+//
+//    Input:
+//          pEffectUuid: pointer to effect uuid to compare to EFFECT_UUID_NULL.
+//
+//    Output:
+//        returned value:    0 if uuid is different from EFFECT_UUID_NULL.
+//                           1 if uuid is equal to EFFECT_UUID_NULL.
+//
+////////////////////////////////////////////////////////////////////////////////
+int EffectIsNullUuid(effect_uuid_t *pEffectUuid);
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTSFACTORYAPI_H_*/
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index c147632..70e505e 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -27,6 +27,9 @@
 #include <media/IAudioTrack.h>
 #include <media/IAudioRecord.h>
 #include <media/IAudioFlingerClient.h>
+#include <media/EffectApi.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
 #include <utils/String8.h>
 
 namespace android {
@@ -51,6 +54,7 @@
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
                                 int output,
+                                int *sessionId,
                                 status_t *status) = 0;
 
     virtual sp<IAudioRecord> openRecord(
@@ -61,6 +65,7 @@
                                 int channelCount,
                                 int frameCount,
                                 uint32_t flags,
+                                int *sessionId,
                                 status_t *status) = 0;
 
     /* query the audio hardware state. This state never changes,
@@ -134,6 +139,30 @@
     virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output) = 0;
 
     virtual unsigned int  getInputFramesLost(int ioHandle) = 0;
+
+    virtual int newAudioSessionId() = 0;
+
+    virtual status_t loadEffectLibrary(const char *libPath, int *handle) = 0;
+
+    virtual status_t unloadEffectLibrary(int handle) = 0;
+
+    virtual status_t queryNumberEffects(uint32_t *numEffects) = 0;
+
+    virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor) = 0;
+
+    virtual status_t getEffectDescriptor(effect_uuid_t *pEffectUUID, effect_descriptor_t *pDescriptor) = 0;
+
+    virtual sp<IEffect> createEffect(pid_t pid,
+                                    effect_descriptor_t *pDesc,
+                                    const sp<IEffectClient>& client,
+                                    int32_t priority,
+                                    int output,
+                                    int sessionId,
+                                    status_t *status,
+                                    int *id,
+                                    int *enabled) = 0;
+
+    virtual status_t moveEffects(int session, int srcOutput, int dstOutput) = 0;
 };
 
 
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 4804bbd..49eee59 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -53,8 +53,12 @@
                                         uint32_t format = AudioSystem::FORMAT_DEFAULT,
                                         uint32_t channels = 0,
                                         AudioSystem::output_flags flags = AudioSystem::OUTPUT_FLAG_INDIRECT) = 0;
-    virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream) = 0;
-    virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream) = 0;
+    virtual status_t startOutput(audio_io_handle_t output,
+                                 AudioSystem::stream_type stream,
+                                 int session = 0) = 0;
+    virtual status_t stopOutput(audio_io_handle_t output,
+                                AudioSystem::stream_type stream,
+                                int session = 0) = 0;
     virtual void releaseOutput(audio_io_handle_t output) = 0;
     virtual audio_io_handle_t getInput(int inputSource,
                                     uint32_t samplingRate = 0,
@@ -69,6 +73,14 @@
                                       int indexMax) = 0;
     virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index) = 0;
     virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index) = 0;
+    virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream) = 0;
+    virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0;
+    virtual status_t registerEffect(effect_descriptor_t *desc,
+                                    audio_io_handle_t output,
+                                    uint32_t strategy,
+                                    int session,
+                                    int id) = 0;
+    virtual status_t unregisterEffect(int id) = 0;
 };
 
 
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
index de6426a..47d530b 100644
--- a/include/media/IAudioTrack.h
+++ b/include/media/IAudioTrack.h
@@ -62,6 +62,11 @@
      */
     virtual void        pause() = 0;
 
+    /* Attach track auxiliary output to specified effect. Use effectId = 0
+     * to detach track from effect.
+     */
+    virtual status_t    attachAuxEffect(int effectId) = 0;
+
     /* get this tracks control block */
     virtual sp<IMemory> getCblk() const = 0;    
 };
diff --git a/include/media/IEffect.h b/include/media/IEffect.h
new file mode 100644
index 0000000..ff04869
--- /dev/null
+++ b/include/media/IEffect.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_IEFFECT_H
+#define ANDROID_IEFFECT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+
+namespace android {
+
+class IEffect: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(Effect);
+
+    virtual status_t enable() = 0;
+
+    virtual status_t disable() = 0;
+
+    virtual status_t command(uint32_t cmdCode,
+                             uint32_t cmdSize,
+                             void *pCmdData,
+                             uint32_t *pReplySize,
+                             void *pReplyData) = 0;
+
+    virtual void disconnect() = 0;
+
+    virtual sp<IMemory> getCblk() const = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnEffect: public BnInterface<IEffect>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IEFFECT_H
diff --git a/include/media/IEffectClient.h b/include/media/IEffectClient.h
new file mode 100644
index 0000000..2f78c98
--- /dev/null
+++ b/include/media/IEffectClient.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_IEFFECTCLIENT_H
+#define ANDROID_IEFFECTCLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/IMemory.h>
+
+namespace android {
+
+class IEffectClient: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(EffectClient);
+
+    virtual void controlStatusChanged(bool controlGranted) = 0;
+    virtual void enableStatusChanged(bool enabled) = 0;
+    virtual void commandExecuted(uint32_t cmdCode,
+                                 uint32_t cmdSize,
+                                 void *pCmdData,
+                                 uint32_t replySize,
+                                 void *pReplyData) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnEffectClient: public BnInterface<IEffectClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IEFFECTCLIENT_H
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 2619691..af9a7ed 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -48,6 +48,8 @@
     virtual status_t        setVolume(float leftVolume, float rightVolume) = 0;
     virtual status_t        suspend() = 0;
     virtual status_t        resume() = 0;
+    virtual status_t        setAuxEffectSendLevel(float level) = 0;
+    virtual status_t        attachAuxEffect(int effectId) = 0;
 
     // Invoke a generic method on the player by using opaque parcels
     // for the request and reply.
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 31c0991..9416ca1 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -40,15 +40,14 @@
 
     virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid) = 0;
     virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
-    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url, const KeyedVector<String8, String8> *headers = NULL) = 0;
-    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
+    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
+            const char* url, const KeyedVector<String8, String8> *headers = NULL,
+            int audioSessionId = 0) = 0;
+    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
+            int fd, int64_t offset, int64_t length, int audioSessionId) = 0;
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
     virtual sp<IOMX>            getOMX() = 0;
-
-    // Take a peek at currently playing audio, for visualization purposes.
-    // This returns a buffer of 16 bit mono PCM data, or NULL if no visualization buffer is currently available.
-    virtual sp<IMemory>         snoop() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 73bf2ee..54adca8 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -24,7 +24,7 @@
 
 class ISurface;
 class ICamera;
-class IMediaPlayerClient;
+class IMediaRecorderClient;
 
 class IMediaRecorder: public IInterface
 {
@@ -43,7 +43,7 @@
     virtual	status_t		setVideoSize(int width, int height) = 0;
     virtual	status_t		setVideoFrameRate(int frames_per_second) = 0;
     virtual     status_t                setParameters(const String8& params) = 0;
-    virtual     status_t                setListener(const sp<IMediaPlayerClient>& listener) = 0;
+    virtual     status_t                setListener(const sp<IMediaRecorderClient>& listener) = 0;
     virtual	status_t		prepare() = 0;
     virtual	status_t		getMaxAmplitude(int* max) = 0;
     virtual	status_t		start() = 0;
diff --git a/include/media/IMediaRecorderClient.h b/include/media/IMediaRecorderClient.h
new file mode 100644
index 0000000..0058ef2
--- /dev/null
+++ b/include/media/IMediaRecorderClient.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_IMEDIARECORDERCLIENT_H
+#define ANDROID_IMEDIARECORDERCLIENT_H
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+class IMediaRecorderClient: public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(MediaRecorderClient);
+
+    virtual void notify(int msg, int ext1, int ext2) = 0;
+};
+
+// ----------------------------------------------------------------------------
+
+class BnMediaRecorderClient: public BnInterface<IMediaRecorderClient>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+}; // namespace android
+
+#endif // ANDROID_IMEDIARECORDERCLIENT_H
+
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 9e606d9..3662983 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -39,7 +39,6 @@
 enum player_type {
     PV_PLAYER = 1,
     SONIVOX_PLAYER = 2,
-    VORBIS_PLAYER = 3,
     STAGEFRIGHT_PLAYER = 4,
     // Test players are available only in the 'test' and 'eng' builds.
     // The shared library with the test player is passed passed as an
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index a4eea2a..c3cd361 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -48,8 +48,8 @@
     static MediaProfiles* getInstance();
 
     /**
-     * Returns the value for the given param name at the given quality level,
-     * or -1 if error.
+     * Returns the value for the given param name for the given camera at
+     * the given quality level, or -1 if error.
      *
      * Supported param name are:
      * duration - the recording duration.
@@ -64,7 +64,8 @@
      * aud.hz - audio sample rate
      * aud.ch - number of audio channels
      */
-    int getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const;
+    int getCamcorderProfileParamByName(const char *name, int cameraId,
+                                       camcorder_quality quality) const;
 
     /**
      * Returns the output file formats supported.
@@ -124,12 +125,7 @@
     /**
      * Returns the number of image encoding quality levels supported.
      */
-    Vector<int> getImageEncodingQualityLevels() const;
-
-    /**
-     * Returns the maximum amount of memory in bytes we can use for decoding a JPEG file.
-     */
-    int getImageDecodingMaxMemory() const;
+    Vector<int> getImageEncodingQualityLevels(int cameraId) const;
 
 private:
     MediaProfiles& operator=(const MediaProfiles&);  // Don't call me
@@ -171,7 +167,8 @@
 
     struct CamcorderProfile {
         CamcorderProfile()
-            : mFileFormat(OUTPUT_FORMAT_THREE_GPP),
+            : mCameraId(0),
+              mFileFormat(OUTPUT_FORMAT_THREE_GPP),
               mQuality(CAMCORDER_QUALITY_HIGH),
               mDuration(0),
               mVideoCodec(0),
@@ -182,6 +179,7 @@
             delete mAudioCodec;
         }
 
+        int mCameraId;
         output_format mFileFormat;
         camcorder_quality mQuality;
         int mDuration;
@@ -249,6 +247,11 @@
         int tag;
     };
 
+    struct ImageEncodingQualityLevels {
+        int mCameraId;
+        Vector<int> mLevels;
+    };
+
     // Debug
     static void logVideoCodec(const VideoCodec& codec);
     static void logAudioCodec(const AudioCodec& codec);
@@ -267,9 +270,11 @@
     static VideoDecoderCap* createVideoDecoderCap(const char **atts);
     static VideoEncoderCap* createVideoEncoderCap(const char **atts);
     static AudioEncoderCap* createAudioEncoderCap(const char **atts);
-    static CamcorderProfile* createCamcorderProfile(const char **atts);
-    static int getImageEncodingQualityLevel(const char **atts);
-    static int getImageDecodingMaxMemory(const char **atts);
+    static CamcorderProfile* createCamcorderProfile(int cameraId, const char **atts);
+    static int getCameraId(const char **atts);
+
+    ImageEncodingQualityLevels* findImageEncodingQualityLevels(int cameraId) const;
+    void addImageEncodingQualityLevel(int cameraId, const char** atts);
 
     // Customized element tag handler for parsing the xml configuration file.
     static void startElementHandler(void *userData, const char *name, const char **atts);
@@ -303,6 +308,7 @@
     static bool sIsInitialized;
     static MediaProfiles *sInstance;
     static Mutex sLock;
+    int mCurrentCameraId;
 
     Vector<CamcorderProfile*> mCamcorderProfiles;
     Vector<AudioEncoderCap*>  mAudioEncoders;
@@ -310,8 +316,7 @@
     Vector<AudioDecoderCap*>  mAudioDecoders;
     Vector<VideoDecoderCap*>  mVideoDecoders;
     Vector<output_format>     mEncoderOutputFileFormats;
-    Vector<int>               mImageEncodingQualityLevels;
-    int                       mImageDecodingMaxMemory;
+    Vector<ImageEncodingQualityLevels *>  mImageEncodingQualityLevels;
 };
 
 }; // namespace android
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 5b787a7..5e9e368 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -41,13 +41,14 @@
     virtual status_t setOutputFile(const char *path) = 0;
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length) = 0;
     virtual status_t setParameters(const String8& params) = 0;
-    virtual status_t setListener(const sp<IMediaPlayerClient>& listener) = 0;
+    virtual status_t setListener(const sp<IMediaRecorderClient>& listener) = 0;
     virtual status_t prepare() = 0;
     virtual status_t start() = 0;
     virtual status_t stop() = 0;
     virtual status_t close() = 0;
     virtual status_t reset() = 0;
     virtual status_t getMaxAmplitude(int *max) = 0;
+    virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
 
 private:
     MediaRecorderBase(const MediaRecorderBase &);
diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h
index 2a1298a..c091c39 100644
--- a/include/media/PVMediaRecorder.h
+++ b/include/media/PVMediaRecorder.h
@@ -18,7 +18,7 @@
 #ifndef ANDROID_PVMEDIARECORDER_H
 #define ANDROID_PVMEDIARECORDER_H
 
-#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorderClient.h>
 #include <media/MediaRecorderBase.h>
 
 namespace android {
@@ -45,13 +45,14 @@
     virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
-    virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
+    virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
     virtual status_t prepare();
     virtual status_t start();
     virtual status_t stop();
     virtual status_t close();
     virtual status_t reset();
     virtual status_t getMaxAmplitude(int *max);
+    virtual status_t dump(int fd, const Vector<String16>& args) const;
 
 private:
     status_t doStop();
diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h
new file mode 100644
index 0000000..5d51de8
--- /dev/null
+++ b/include/media/Visualizer.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_MEDIA_VISUALIZER_H
+#define ANDROID_MEDIA_VISUALIZER_H
+
+#include <media/AudioEffect.h>
+#include <media/EffectVisualizerApi.h>
+#include <string.h>
+
+/**
+ * The Visualizer class enables application to retrieve part of the currently playing audio for
+ * visualization purpose. It is not an audio recording interface and only returns partial and low
+ * quality audio content. However, to protect privacy of certain audio data (e.g voice mail) the use
+ * of the visualizer requires the permission android.permission.RECORD_AUDIO.
+ * The audio session ID passed to the constructor indicates which audio content should be
+ * visualized:
+ * - If the session is 0, the audio output mix is visualized
+ * - If the session is not 0, the audio from a particular MediaPlayer or AudioTrack
+ *   using this audio session is visualized
+ * Two types of representation of audio content can be captured:
+ * - Waveform data: consecutive 8-bit (unsigned) mono samples by using the getWaveForm() method
+ * - Frequency data: 8-bit magnitude FFT by using the getFft() method
+ *
+ * The length of the capture can be retrieved or specified by calling respectively
+ * getCaptureSize() and setCaptureSize() methods. Note that the size of the FFT
+ * is half of the specified capture size but both sides of the spectrum are returned yielding in a
+ * number of bytes equal to the capture size. The capture size must be a power of 2 in the range
+ * returned by getMinCaptureSize() and getMaxCaptureSize().
+ * In addition to the polling capture mode, a callback mode is also available by installing a
+ * callback function by use of the setCaptureCallBack() method. The rate at which the callback
+ * is called as well as the type of data returned is specified.
+ * Before capturing data, the Visualizer must be enabled by calling the setEnabled() method.
+ * When data capture is not needed any more, the Visualizer should be disabled.
+ */
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class Visualizer: public AudioEffect {
+public:
+
+    enum callback_flags {
+        CAPTURE_WAVEFORM = 0x00000001,  // capture callback returns a PCM wave form
+        CAPTURE_FFT = 0x00000002,       // apture callback returns a frequency representation
+        CAPTURE_CALL_JAVA = 0x00000004  // the callback thread can call java
+    };
+
+
+    /* Constructor.
+     * See AudioEffect constructor for details on parameters.
+     */
+                        Visualizer(int32_t priority = 0,
+                                   effect_callback_t cbf = 0,
+                                   void* user = 0,
+                                   int sessionId = 0);
+
+                        ~Visualizer();
+
+    virtual status_t    setEnabled(bool enabled);
+
+    // maximum capture size in samples
+    static uint32_t getMaxCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MAX; }
+    // minimum capture size in samples
+    static uint32_t getMinCaptureSize() { return VISUALIZER_CAPTURE_SIZE_MIN; }
+    // maximum capture rate in millihertz
+    static uint32_t getMaxCaptureRate() { return CAPTURE_RATE_MAX; }
+
+    // callback used to return periodic PCM or FFT captures to the application. Either one or both
+    // types of data are returned (PCM and FFT) according to flags indicated when installing the
+    // callback. When a type of data is not present, the corresponding size (waveformSize or
+    // fftSize) is 0.
+    typedef void (*capture_cbk_t)(void* user,
+                                    uint32_t waveformSize,
+                                    uint8_t *waveform,
+                                    uint32_t fftSize,
+                                    uint8_t *fft,
+                                    uint32_t samplingrate);
+
+    // install a callback to receive periodic captures. The capture rate is specified in milliHertz
+    // and the capture format is according to flags  (see callback_flags).
+    status_t setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate);
+
+    // set the capture size capture size must be a power of two in the range
+    // [VISUALIZER_CAPTURE_SIZE_MAX. VISUALIZER_CAPTURE_SIZE_MIN]
+    // must be called when the visualizer is not enabled
+    status_t setCaptureSize(uint32_t size);
+    uint32_t getCaptureSize() { return mCaptureSize; }
+
+    // returns the capture rate indicated when installing the callback
+    uint32_t getCaptureRate() { return mCaptureRate; }
+
+    // returns the sampling rate of the audio being captured
+    uint32_t getSamplingRate() { return mSampleRate; }
+
+    // return a capture in PCM 8 bit unsigned format. The size of the capture is equal to
+    // getCaptureSize()
+    status_t getWaveForm(uint8_t *waveform);
+
+    // return a capture in FFT 8 bit signed format. The size of the capture is equal to
+    // getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum
+    // are returned
+    status_t getFft(uint8_t *fft);
+
+private:
+
+    static const uint32_t CAPTURE_RATE_MAX = 20000;
+    static const uint32_t CAPTURE_RATE_DEF = 10000;
+    static const uint32_t CAPTURE_SIZE_DEF = VISUALIZER_CAPTURE_SIZE_MAX;
+
+    /* internal class to handle the callback */
+    class CaptureThread : public Thread
+    {
+    public:
+        CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava = false);
+
+    private:
+        friend class Visualizer;
+        virtual bool        threadLoop();
+        virtual status_t    readyToRun();
+        virtual void        onFirstRef();
+        Visualizer& mReceiver;
+        Mutex       mLock;
+        uint32_t mSleepTimeUs;
+    };
+
+    status_t doFft(uint8_t *fft, uint8_t *waveform);
+    void periodicCapture();
+    uint32_t initCaptureSize();
+
+    Mutex mLock;
+    uint32_t mCaptureRate;
+    uint32_t mCaptureSize;
+    uint32_t mSampleRate;
+    capture_cbk_t mCaptureCallBack;
+    void *mCaptureCbkUser;
+    sp<CaptureThread> mCaptureThread;
+    uint32_t mCaptureFlags;
+    void *mFftTable;
+};
+
+
+}; // namespace android
+
+#endif // ANDROID_MEDIA_VISUALIZER_H
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index 7fad1b7..207191d 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -93,6 +93,11 @@
     // The video is too complex for the decoder: it can't decode frames fast
     // enough. Possibly only the audio plays fine at this stage.
     MEDIA_INFO_VIDEO_TRACK_LAGGING = 700,
+    // MediaPlayer is temporarily pausing playback internally in order to
+    // buffer more data.
+    MEDIA_INFO_BUFFERING_START = 701,
+    // MediaPlayer is resuming playback after filling buffers.
+    MEDIA_INFO_BUFFERING_END = 702,
     // 8xx
     // Bad interleaving means that a media has been improperly interleaved or not
     // interleaved at all, e.g has all the video samples first then all the audio
@@ -161,12 +166,15 @@
             void            notify(int msg, int ext1, int ext2);
     static  sp<IMemory>     decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
     static  sp<IMemory>     decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
-    static  int             snoop(short *data, int len, int kind);
             status_t        invoke(const Parcel& request, Parcel *reply);
             status_t        setMetadataFilter(const Parcel& filter);
             status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
             status_t        suspend();
             status_t        resume();
+            status_t        setAudioSessionId(int sessionId);
+            int             getAudioSessionId();
+            status_t        setAuxEffectSendLevel(float level);
+            status_t        attachAuxEffect(int effectId);
 private:
             void            clear_l();
             status_t        seekTo_l(int msec);
@@ -193,6 +201,8 @@
     float                       mRightVolume;
     int                         mVideoWidth;
     int                         mVideoHeight;
+    int                         mAudioSessionId;
+    float                       mSendLevel;
 };
 
 }; // namespace android
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 9ea6c7b..b21bc4d 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -22,7 +22,7 @@
 #include <utils/threads.h>
 #include <utils/List.h>
 #include <utils/Errors.h>
-#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorderClient.h>
 #include <media/IMediaDeathNotifier.h>
 
 namespace android {
@@ -135,7 +135,10 @@
 enum media_recorder_info_type {
     MEDIA_RECORDER_INFO_UNKNOWN                   = 1,
     MEDIA_RECORDER_INFO_MAX_DURATION_REACHED      = 800,
-    MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED      = 801
+    MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED      = 801,
+    MEDIA_RECORDER_INFO_COMPLETION_STATUS         = 802,
+    MEDIA_RECORDER_INFO_PROGRESS_FRAME_STATUS     = 803,
+    MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS      = 804,
 };
 
 // ----------------------------------------------------------------------------
@@ -146,7 +149,7 @@
     virtual void notify(int msg, int ext1, int ext2) = 0;
 };
 
-class MediaRecorder : public BnMediaPlayerClient,
+class MediaRecorder : public BnMediaRecorderClient,
                       public virtual IMediaDeathNotifier
 {
 public:
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index 372909a..813dd43 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -26,6 +26,7 @@
 namespace android {
 
 struct MediaSource;
+struct MetaData;
 
 struct AMRWriter : public MediaWriter {
     AMRWriter(const char *filename);
@@ -35,25 +36,30 @@
 
     virtual status_t addSource(const sp<MediaSource> &source);
     virtual bool reachedEOS();
-    virtual status_t start();
+    virtual status_t start(MetaData *params = NULL);
     virtual void stop();
+    virtual void pause();
 
 protected:
     virtual ~AMRWriter();
 
 private:
-    Mutex mLock;
-
     FILE *mFile;
     status_t mInitCheck;
     sp<MediaSource> mSource;
     bool mStarted;
+    volatile bool mPaused;
+    volatile bool mResumed;
     volatile bool mDone;
-    bool mReachedEOS;
+    volatile bool mReachedEOS;
     pthread_t mThread;
+    int64_t mEstimatedSizeBytes;
+    int64_t mEstimatedDurationUs;
 
     static void *ThreadWrapper(void *);
     void threadFunc();
+    bool exceedsFileSizeLimit();
+    bool exceedsFileDurationLimit();
 
     AMRWriter(const AMRWriter &);
     AMRWriter &operator=(const AMRWriter &);
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index eb00140..628200d 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -39,6 +39,9 @@
     virtual status_t stop();
     virtual sp<MetaData> getFormat();
 
+    // Returns the maximum amplitude since last call.
+    int16_t getMaxAmplitude();
+
     virtual status_t read(
             MediaBuffer **buffer, const ReadOptions *options = NULL);
 
@@ -46,13 +49,24 @@
     virtual ~AudioSource();
 
 private:
-    enum { kMaxBufferSize = 8192 };
+    enum { kMaxBufferSize = 2048 };
 
     AudioRecord *mRecord;
     status_t mInitCheck;
     bool mStarted;
+
+    bool mCollectStats;
+    bool mTrackMaxAmplitude;
+    int64_t mTotalReadTimeUs;
+    int64_t mTotalReadBytes;
+    int64_t mTotalReads;
+    int64_t mStartTimeUs;
+    int16_t mMaxAmplitude;
+
     MediaBufferGroup *mGroup;
 
+    void trackMaxAmplitude(int16_t *data, int nSamples);
+
     AudioSource(const AudioSource &);
     AudioSource &operator=(const AudioSource &);
 };
diff --git a/include/media/stagefright/CachingDataSource.h b/include/media/stagefright/CachingDataSource.h
deleted file mode 100644
index 42d50e5..0000000
--- a/include/media/stagefright/CachingDataSource.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2009 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 CACHING_DATASOURCE_H_
-
-#define CACHING_DATASOURCE_H_
-
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class CachingDataSource : public DataSource {
-public:
-    CachingDataSource(
-            const sp<DataSource> &source, size_t pageSize, int numPages);
-
-    virtual status_t initCheck() const;
-
-    virtual ssize_t readAt(off_t offset, void *data, size_t size);
-
-    virtual status_t getSize(off_t *size);
-
-    virtual uint32_t flags();
-
-protected:
-    virtual ~CachingDataSource();
-
-private:
-    struct Page {
-        Page *mPrev, *mNext;
-        off_t mOffset;
-        size_t mLength;
-        void *mData;
-    };
-
-    sp<DataSource> mSource;
-    void *mData;
-    size_t mPageSize;
-    Page *mFirst, *mLast;
-
-    Page *allocate_page();
-
-    Mutex mLock;
-
-    CachingDataSource(const CachingDataSource &);
-    CachingDataSource &operator=(const CachingDataSource &);
-};
-
-}  // namespace android
-
-#endif  // CACHING_DATASOURCE_H_
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index ea435de..3192d03 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -28,18 +28,15 @@
 
 class ICamera;
 class IMemory;
-class ISurface;
 class Camera;
 
-class CameraSource : public MediaSource {
+class CameraSource : public MediaSource, public MediaBufferObserver {
 public:
     static CameraSource *Create();
-    static CameraSource *CreateFromICamera(const sp<ICamera> &icamera);
+    static CameraSource *CreateFromCamera(const sp<Camera> &camera);
 
     virtual ~CameraSource();
 
-    void setPreviewSurface(const sp<ISurface> &surface);
-
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
 
@@ -48,25 +45,39 @@
     virtual status_t read(
             MediaBuffer **buffer, const ReadOptions *options = NULL);
 
+    virtual void signalBufferReturned(MediaBuffer* buffer);
+
 private:
     friend class CameraSourceListener;
 
     sp<Camera> mCamera;
-    sp<ISurface> mPreviewSurface;
+    sp<MetaData> mMeta;
 
     Mutex mLock;
     Condition mFrameAvailableCondition;
-    List<sp<IMemory> > mFrames;
+    Condition mFrameCompleteCondition;
+    List<sp<IMemory> > mFramesReceived;
+    List<sp<IMemory> > mFramesBeingEncoded;
     List<int64_t> mFrameTimes;
 
-    int mWidth, mHeight;
+    int64_t mStartTimeUs;
     int64_t mFirstFrameTimeUs;
-    int32_t mNumFrames;
+    int64_t mLastFrameTimestampUs;
+    int32_t mNumFramesReceived;
+    int32_t mNumFramesEncoded;
+    int32_t mNumFramesDropped;
+    int32_t mNumGlitches;
+    int64_t mGlitchDurationThresholdUs;
+    bool mCollectStats;
     bool mStarted;
 
     CameraSource(const sp<Camera> &camera);
 
-    void dataCallback(int32_t msgType, const sp<IMemory> &data);
+    void dataCallbackTimestamp(
+            int64_t timestampUs, int32_t msgType, const sp<IMemory> &data);
+
+    void releaseQueuedFrames();
+    void releaseOneRecordingFrame(const sp<IMemory>& frame);
 
     CameraSource(const CameraSource &);
     CameraSource &operator=(const CameraSource &);
diff --git a/include/media/stagefright/ColorConverter.h b/include/media/stagefright/ColorConverter.h
index 1e341b9..bc3f464 100644
--- a/include/media/stagefright/ColorConverter.h
+++ b/include/media/stagefright/ColorConverter.h
@@ -58,6 +58,11 @@
             const void *srcBits, size_t srcSkip,
             void *dstBits, size_t dstSkip);
 
+    void convertYUV420SemiPlanar(
+            size_t width, size_t height,
+            const void *srcBits, size_t srcSkip,
+            void *dstBits, size_t dstSkip);
+
     ColorConverter(const ColorConverter &);
     ColorConverter &operator=(const ColorConverter &);
 };
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
deleted file mode 100644
index 0400bea..0000000
--- a/include/media/stagefright/HTTPDataSource.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2009 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 HTTP_DATASOURCE_H_
-
-#define HTTP_DATASOURCE_H_
-
-#include <media/stagefright/DataSource.h>
-#include <utils/String8.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class HTTPStream;
-
-class HTTPDataSource : public DataSource {
-public:
-    HTTPDataSource(
-            const char *host, int port, const char *path,
-            const KeyedVector<String8, String8> *headers = NULL);
-
-    HTTPDataSource(
-            const char *uri,
-            const KeyedVector<String8, String8> *headers = NULL);
-
-    status_t connect();
-    void disconnect();
-
-    virtual status_t initCheck() const;
-
-    virtual ssize_t readAt(off_t offset, void *data, size_t size);
-
-    virtual status_t getSize(off_t *size);
-
-    virtual uint32_t flags();
-
-protected:
-    virtual ~HTTPDataSource();
-
-private:
-    enum {
-        kBufferSize = 64 * 1024,
-
-        // If we encounter a socket-read error we'll try reconnecting
-        // and restarting the read for at most this many times.
-        kMaxNumRetries = 3,
-    };
-
-    enum State {
-        DISCONNECTED,
-        CONNECTING,
-        CONNECTED
-    };
-
-    State mState;
-    mutable Mutex mStateLock;
-
-    String8 mHeaders;
-
-    String8 mStartingHost;
-    String8 mStartingPath;
-    int mStartingPort;
-
-    HTTPStream *mHttp;
-
-    void *mBuffer;
-    size_t mBufferLength;
-    off_t mBufferOffset;
-
-    bool mContentLengthValid;
-    unsigned long long mContentLength;
-
-    int32_t mNumRetriesLeft;
-
-    void init(const KeyedVector<String8, String8> *headers);
-
-    ssize_t sendRangeRequest(size_t offset);
-    void initHeaders(const KeyedVector<String8, String8> *overrides);
-
-    status_t connectWithRedirectsAndRange(off_t rangeStart);
-    void applyTimeoutResponse();
-
-    HTTPDataSource(const HTTPDataSource &);
-    HTTPDataSource &operator=(const HTTPDataSource &);
-};
-
-}  // namespace android
-
-#endif  // HTTP_DATASOURCE_H_
-
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 6b93f19..d0c2dca 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -36,9 +36,10 @@
     MPEG4Writer(int fd);
 
     virtual status_t addSource(const sp<MediaSource> &source);
-    virtual status_t start();
+    virtual status_t start(MetaData *param = NULL);
     virtual bool reachedEOS();
     virtual void stop();
+    virtual void pause();
 
     void beginBox(const char *fourcc);
     void writeInt8(int8_t x);
@@ -49,6 +50,9 @@
     void writeFourcc(const char *fourcc);
     void write(const void *data, size_t size);
     void endBox();
+    uint32_t interleaveDuration() const { return mInterleaveDurationUs; }
+    status_t setInterleaveDuration(uint32_t duration);
+    int32_t getTimeScale() const { return mTimeScale; }
 
 protected:
     virtual ~MPEG4Writer();
@@ -57,16 +61,43 @@
     class Track;
 
     FILE *mFile;
+    bool mUse32BitOffset;
+    bool mPaused;
+    bool mStarted;
     off_t mOffset;
     off_t mMdatOffset;
+    uint8_t *mMoovBoxBuffer;
+    off_t mMoovBoxBufferOffset;
+    bool  mWriteMoovBoxToMemory;
+    off_t mFreeBoxOffset;
+    bool mStreamableFile;
+    off_t mEstimatedMoovBoxSize;
+    uint32_t mInterleaveDurationUs;
+    int32_t mTimeScale;
+    int64_t mStartTimestampUs;
     Mutex mLock;
 
     List<Track *> mTracks;
 
     List<off_t> mBoxes;
 
-    off_t addSample(MediaBuffer *buffer);
-    off_t addLengthPrefixedSample(MediaBuffer *buffer);
+    void setStartTimestampUs(int64_t timeUs);
+    int64_t getStartTimestampUs();  // Not const
+    status_t startTracks(MetaData *params);
+    size_t numTracks();
+    int64_t estimateMoovBoxSize(int32_t bitRate);
+
+    void lock();
+    void unlock();
+
+    // Acquire lock before calling these methods
+    off_t addSample_l(MediaBuffer *buffer);
+    off_t addLengthPrefixedSample_l(MediaBuffer *buffer);
+
+    inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream);
+    bool exceedsFileSizeLimit();
+    bool exceedsFileDurationLimit();
+    void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
 
     MPEG4Writer(const MPEG4Writer &);
     MPEG4Writer &operator=(const MPEG4Writer &);
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 207195a..9cddab2 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -22,6 +22,7 @@
 
 extern const char *MEDIA_MIMETYPE_IMAGE_JPEG;
 
+extern const char *MEDIA_MIMETYPE_VIDEO_VPX;
 extern const char *MEDIA_MIMETYPE_VIDEO_AVC;
 extern const char *MEDIA_MIMETYPE_VIDEO_MPEG4;
 extern const char *MEDIA_MIMETYPE_VIDEO_H263;
@@ -38,6 +39,8 @@
 extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
 extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
 extern const char *MEDIA_MIMETYPE_CONTAINER_OGG;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA;
+extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS;
 
 }  // namespace android
 
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index 96d57e7..dafc621 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -20,6 +20,7 @@
 
 #include <sys/types.h>
 
+#include <media/stagefright/MediaErrors.h>
 #include <utils/RefBase.h>
 
 namespace android {
@@ -61,28 +62,56 @@
     // a) not request a seek
     // b) not be late, i.e. lateness_us = 0
     struct ReadOptions {
+        enum SeekMode {
+            SEEK_PREVIOUS_SYNC,
+            SEEK_NEXT_SYNC,
+            SEEK_CLOSEST_SYNC,
+            SEEK_CLOSEST,
+        };
+
         ReadOptions();
 
         // Reset everything back to defaults.
         void reset();
 
-        void setSeekTo(int64_t time_us);
+        void setSeekTo(int64_t time_us, SeekMode mode = SEEK_CLOSEST_SYNC);
         void clearSeekTo();
-        bool getSeekTo(int64_t *time_us) const;
+        bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
+
+        // Option allows encoder to skip some frames until the specified
+        // time stamp.
+        // To prevent from being abused, when the skipFrame timestamp is
+        // found to be more than 1 second later than the current timestamp,
+        // an error will be returned from read().
+        void clearSkipFrame();
+        bool getSkipFrame(int64_t *timeUs) const;
+        void setSkipFrame(int64_t timeUs);
 
         void setLateBy(int64_t lateness_us);
         int64_t getLateBy() const;
 
     private:
         enum Options {
+            // Bit map
             kSeekTo_Option      = 1,
+            kSkipFrame_Option   = 2,
         };
 
         uint32_t mOptions;
         int64_t mSeekTimeUs;
+        SeekMode mSeekMode;
         int64_t mLatenessUs;
+
+        int64_t mSkipFrameUntilTimeUs;
     };
 
+    // Causes this source to suspend pulling data from its upstream source
+    // until a subsequent read-with-seek. Currently only supported by
+    // OMXCodec.
+    virtual status_t pause() {
+        return ERROR_UNSUPPORTED;
+    }
+
 protected:
     virtual ~MediaSource();
 
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
index b8232c6..8d3a9df 100644
--- a/include/media/stagefright/MediaWriter.h
+++ b/include/media/stagefright/MediaWriter.h
@@ -19,22 +19,41 @@
 #define MEDIA_WRITER_H_
 
 #include <utils/RefBase.h>
+#include <media/IMediaRecorderClient.h>
 
 namespace android {
 
 struct MediaSource;
+struct MetaData;
 
 struct MediaWriter : public RefBase {
-    MediaWriter() {}
+    MediaWriter()
+        : mMaxFileSizeLimitBytes(0),
+          mMaxFileDurationLimitUs(0) {
+    }
 
     virtual status_t addSource(const sp<MediaSource> &source) = 0;
     virtual bool reachedEOS() = 0;
-    virtual status_t start() = 0;
+    virtual status_t start(MetaData *params = NULL) = 0;
     virtual void stop() = 0;
+    virtual void pause() = 0;
+    virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; }
+    virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; }
+    virtual void setListener(const sp<IMediaRecorderClient>& listener) {
+        mListener = listener;
+    }
 
 protected:
     virtual ~MediaWriter() {}
+    int64_t mMaxFileSizeLimitBytes;
+    int64_t mMaxFileDurationLimitUs;
+    sp<IMediaRecorderClient> mListener;
 
+    void notify(int msg, int ext1, int ext2) {
+        if (mListener != NULL) {
+            mListener->notify(msg, ext1, ext2);
+        }
+    }
 private:
     MediaWriter(const MediaWriter &);
     MediaWriter &operator=(const MediaWriter &);
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index dc2bd50..e631c7f 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -30,10 +30,13 @@
 // The following keys map to int32_t data unless indicated otherwise.
 enum {
     kKeyMIMEType          = 'mime',  // cstring
-    kKeyWidth             = 'widt',
-    kKeyHeight            = 'heig',
-    kKeyChannelCount      = '#chn',
-    kKeySampleRate        = 'srte',
+    kKeyWidth             = 'widt',  // int32_t
+    kKeyHeight            = 'heig',  // int32_t
+    kKeyIFramesInterval   = 'ifiv',  // int32_t
+    kKeyStride            = 'strd',  // int32_t
+    kKeySliceHeight       = 'slht',  // int32_t
+    kKeyChannelCount      = '#chn',  // int32_t
+    kKeySampleRate        = 'srte',  // int32_t (also video frame rate)
     kKeyBitRate           = 'brte',  // int32_t (bps)
     kKeyESDS              = 'esds',  // raw data
     kKeyAVCC              = 'avcc',  // raw data
@@ -43,6 +46,7 @@
     kKeyIsSyncFrame       = 'sync',  // int32_t (bool)
     kKeyIsCodecConfig     = 'conf',  // int32_t (bool)
     kKeyTime              = 'time',  // int64_t (usecs)
+    kKeyTargetTime        = 'tarT',  // int64_t (usecs)
     kKeyDuration          = 'dura',  // int64_t (usecs)
     kKeyColorFormat       = 'colf',
     kKeyPlatformPrivate   = 'priv',  // pointer
@@ -65,6 +69,26 @@
     kKeyDiscNumber        = 'dnum',  // cstring
     kKeyDate              = 'date',  // cstring
     kKeyWriter            = 'writ',  // cstring
+    kKeyTimeScale         = 'tmsl',  // int32_t
+
+    // video profile and level
+    kKeyVideoProfile      = 'vprf',  // int32_t
+    kKeyVideoLevel        = 'vlev',  // int32_t
+
+    // Set this key to enable authoring files in 64-bit offset
+    kKey64BitFileOffset   = 'fobt',  // int32_t (bool)
+
+    // Identify the file output format for authoring
+    // Please see <media/mediarecorder.h> for the supported
+    // file output formats.
+    kKeyFileType          = 'ftyp',  // int32_t
+
+    // Track authoring progress status
+    // kKeyTrackTimeStatus is used to track progress in elapsed time
+    // kKeyTrackFrameStatus is used to track progress in authored frames
+    kKeyTrackFrameStatus  = 'tkfm',  // int32_t
+    kKeyTrackTimeStatus   = 'tktm',  // int64_t
+
 };
 
 enum {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 1d76a1a..6c6949b 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -27,6 +27,7 @@
 
 class MemoryDealer;
 struct OMXCodecObserver;
+struct CodecProfileLevel;
 
 struct OMXCodec : public MediaSource,
                   public MediaBufferObserver {
@@ -52,6 +53,8 @@
     virtual status_t read(
             MediaBuffer **buffer, const ReadOptions *options = NULL);
 
+    virtual status_t pause();
+
     void on_message(const omx_message &msg);
 
     // from MediaBufferObserver
@@ -98,6 +101,7 @@
         kDecoderLiesAboutNumberOfChannels     = 256,
         kInputBufferSizesAreBogus             = 512,
         kSupportsMultipleFramesPerInputBuffer = 1024,
+        kAvoidMemcopyInputRecordingFrames     = 2048,
     };
 
     struct BufferInfo {
@@ -137,12 +141,17 @@
     bool mNoMoreOutputData;
     bool mOutputPortSettingsHaveChanged;
     int64_t mSeekTimeUs;
+    ReadOptions::SeekMode mSeekMode;
+    int64_t mTargetTimeUs;
+    int64_t mSkipTimeUs;
 
     MediaBuffer *mLeftOverBuffer;
 
     Mutex mLock;
     Condition mAsyncCompletion;
 
+    bool mPaused;
+
     // A list of indices into mPortStatus[kPortIndexOutput] filled with data.
     List<size_t> mFilledBuffers;
     Condition mBufferFilled;
@@ -156,8 +165,8 @@
 
     void setComponentRole();
 
-    void setAMRFormat(bool isWAMR);
-    void setAACFormat(int32_t numChannels, int32_t sampleRate);
+    void setAMRFormat(bool isWAMR, int32_t bitRate);
+    void setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate);
 
     status_t setVideoPortFormatType(
             OMX_U32 portIndex,
@@ -165,10 +174,19 @@
             OMX_COLOR_FORMATTYPE colorFormat);
 
     void setVideoInputFormat(
-            const char *mime, OMX_U32 width, OMX_U32 height);
+            const char *mime, const sp<MetaData>& meta);
 
-    status_t setupMPEG4EncoderParameters();
-    status_t setupAVCEncoderParameters();
+    status_t setupBitRate(int32_t bitRate);
+    status_t setupErrorCorrectionParameters();
+    status_t setupH263EncoderParameters(const sp<MetaData>& meta);
+    status_t setupMPEG4EncoderParameters(const sp<MetaData>& meta);
+    status_t setupAVCEncoderParameters(const sp<MetaData>& meta);
+
+    // If profile/level is set in the meta data, its value in the meta
+    // data will be used; otherwise, the default value will be used.
+    status_t getVideoProfileLevel(const sp<MetaData>& meta,
+            const CodecProfileLevel& defaultProfileLevel,
+            CodecProfileLevel& profileLevel);
 
     status_t setVideoOutputFormat(
             const char *mime, OMX_U32 width, OMX_U32 height);
diff --git a/include/media/stagefright/foundation/AAtomizer.h b/include/media/stagefright/foundation/AAtomizer.h
new file mode 100644
index 0000000..5f3a678
--- /dev/null
+++ b/include/media/stagefright/foundation/AAtomizer.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 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 A_ATOMIZER_H_
+
+#define A_ATOMIZER_H_
+
+#include <stdint.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/List.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct AAtomizer {
+    static const char *Atomize(const char *name);
+
+private:
+    static AAtomizer gAtomizer;
+
+    Mutex mLock;
+    Vector<List<AString> > mAtoms;
+
+    AAtomizer();
+
+    const char *atomize(const char *name);
+
+    static uint32_t Hash(const char *s);
+
+    DISALLOW_EVIL_CONSTRUCTORS(AAtomizer);
+};
+
+}  // namespace android
+
+#endif  // A_ATOMIZER_H_
diff --git a/include/media/stagefright/foundation/ABase.h b/include/media/stagefright/foundation/ABase.h
new file mode 100644
index 0000000..9eceea3
--- /dev/null
+++ b/include/media/stagefright/foundation/ABase.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2010 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 A_BASE_H_
+
+#define A_BASE_H_
+
+#define DISALLOW_EVIL_CONSTRUCTORS(name) \
+    name(const name &); \
+    name &operator=(const name &)
+
+#endif  // A_BASE_H_
diff --git a/include/media/stagefright/foundation/ABuffer.h b/include/media/stagefright/foundation/ABuffer.h
new file mode 100644
index 0000000..28f0aed
--- /dev/null
+++ b/include/media/stagefright/foundation/ABuffer.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 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 A_BUFFER_H_
+
+#define A_BUFFER_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AMessage;
+
+struct ABuffer : public RefBase {
+    ABuffer(size_t capacity);
+    ABuffer(void *data, size_t capacity);
+
+    void setFarewellMessage(const sp<AMessage> msg);
+
+    uint8_t *base() { return (uint8_t *)mData; }
+    uint8_t *data() { return (uint8_t *)mData + mRangeOffset; }
+    size_t capacity() const { return mCapacity; }
+    size_t size() const { return mRangeLength; }
+    size_t offset() const { return mRangeOffset; }
+
+    void setRange(size_t offset, size_t size);
+
+    void setInt32Data(int32_t data) { mInt32Data = data; }
+    int32_t int32Data() const { return mInt32Data; }
+
+    sp<AMessage> meta();
+
+protected:
+    virtual ~ABuffer();
+
+private:
+    sp<AMessage> mFarewell;
+    sp<AMessage> mMeta;
+
+    void *mData;
+    size_t mCapacity;
+    size_t mRangeOffset;
+    size_t mRangeLength;
+
+    int32_t mInt32Data;
+
+    bool mOwnsData;
+
+    DISALLOW_EVIL_CONSTRUCTORS(ABuffer);
+};
+
+}  // namespace android
+
+#endif  // A_BUFFER_H_
diff --git a/include/media/stagefright/foundation/ADebug.h b/include/media/stagefright/foundation/ADebug.h
new file mode 100644
index 0000000..0f986a0
--- /dev/null
+++ b/include/media/stagefright/foundation/ADebug.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 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 A_DEBUG_H_
+
+#define A_DEBUG_H_
+
+#include <string.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+enum LogType {
+    VERBOSE,
+    INFO,
+    WARNING,
+    ERROR,
+    FATAL,
+};
+
+struct Logger {
+    Logger(LogType type);
+    virtual ~Logger();
+
+    template<class T> Logger &operator<<(const T &x) {
+        mMessage.append(x);
+
+        return *this;
+    }
+
+private:
+    android::AString mMessage;
+    LogType mLogType;
+
+    DISALLOW_EVIL_CONSTRUCTORS(Logger);
+};
+
+const char *LeafName(const char *s);
+
+#undef LOG
+#define LOG(type)    Logger(type) << LeafName(__FILE__) << ":" << __LINE__ << " "
+
+#define CHECK(condition)                                \
+    do {                                                \
+        if (!(condition)) {                             \
+            LOG(FATAL) << "CHECK(" #condition ") failed.";    \
+        }                                               \
+    } while (false)
+
+#define MAKE_COMPARATOR(suffix,op)                          \
+    template<class A, class B>                              \
+    AString Compare_##suffix(const A &a, const B &b) {      \
+        AString res;                                        \
+        if (!(a op b)) {                                    \
+            res.append(a);                                  \
+            res.append(" vs. ");                            \
+            res.append(b);                                  \
+        }                                                   \
+        return res;                                         \
+    }
+
+MAKE_COMPARATOR(EQ,==)
+MAKE_COMPARATOR(NE,!=)
+MAKE_COMPARATOR(LE,<=)
+MAKE_COMPARATOR(GE,>=)
+MAKE_COMPARATOR(LT,<)
+MAKE_COMPARATOR(GT,>)
+
+#define CHECK_OP(x,y,suffix,op)                                         \
+    do {                                                                \
+        AString ___res = Compare_##suffix(x, y);                        \
+        if (!___res.empty()) {                                          \
+            LOG(FATAL) << "CHECK_" #suffix "(" #x "," #y ") failed: "   \
+                       << ___res;                                       \
+        }                                                               \
+    } while (false)
+
+#define CHECK_EQ(x,y)   CHECK_OP(x,y,EQ,==)
+#define CHECK_NE(x,y)   CHECK_OP(x,y,NE,!=)
+#define CHECK_LE(x,y)   CHECK_OP(x,y,LE,<=)
+#define CHECK_LT(x,y)   CHECK_OP(x,y,LT,<)
+#define CHECK_GE(x,y)   CHECK_OP(x,y,GE,>=)
+#define CHECK_GT(x,y)   CHECK_OP(x,y,GT,>)
+
+#define TRESPASS()      LOG(FATAL) << "Should not be here."
+
+}  // namespace android
+
+#endif  // A_DEBUG_H_
+
diff --git a/include/media/stagefright/foundation/AHandler.h b/include/media/stagefright/foundation/AHandler.h
new file mode 100644
index 0000000..b008b54
--- /dev/null
+++ b/include/media/stagefright/foundation/AHandler.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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 A_HANDLER_H_
+
+#define A_HANDLER_H_
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AMessage;
+
+struct AHandler : public RefBase {
+    AHandler()
+        : mID(0) {
+    }
+
+    ALooper::handler_id id() const {
+        return mID;
+    }
+
+    sp<ALooper> looper();
+
+protected:
+    virtual void onMessageReceived(const sp<AMessage> &msg) = 0;
+
+private:
+    friend struct ALooperRoster;
+
+    ALooper::handler_id mID;
+
+    void setID(ALooper::handler_id id) {
+        mID = id;
+    }
+
+    DISALLOW_EVIL_CONSTRUCTORS(AHandler);
+};
+
+}  // namespace android
+
+#endif  // A_HANDLER_H_
diff --git a/include/media/stagefright/foundation/AHandlerReflector.h b/include/media/stagefright/foundation/AHandlerReflector.h
new file mode 100644
index 0000000..857866a
--- /dev/null
+++ b/include/media/stagefright/foundation/AHandlerReflector.h
@@ -0,0 +1,32 @@
+#ifndef A_HANDLER_REFLECTOR_H_
+
+#define A_HANDLER_REFLECTOR_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+
+namespace android {
+
+template<class T>
+struct AHandlerReflector : public AHandler {
+    AHandlerReflector(T *target)
+        : mTarget(target) {
+    }
+
+protected:
+    virtual void onMessageReceived(const sp<AMessage> &msg) {
+        sp<T> target = mTarget.promote();
+        if (target != NULL) {
+            target->onMessageReceived(msg);
+        }
+    }
+
+private:
+    wp<T> mTarget;
+
+    AHandlerReflector(const AHandlerReflector<T> &);
+    AHandlerReflector<T> &operator=(const AHandlerReflector<T> &);
+};
+
+}  // namespace android
+
+#endif  // A_HANDLER_REFLECTOR_H_
diff --git a/include/media/stagefright/foundation/ALooper.h b/include/media/stagefright/foundation/ALooper.h
new file mode 100644
index 0000000..153ead9
--- /dev/null
+++ b/include/media/stagefright/foundation/ALooper.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 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 A_LOOPER_H_
+
+#define A_LOOPER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+#include <utils/KeyedVector.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct AHandler;
+struct AMessage;
+
+struct ALooper : public RefBase {
+    typedef int32_t event_id;
+    typedef int32_t handler_id;
+
+    ALooper();
+
+    handler_id registerHandler(const sp<AHandler> &handler);
+    void unregisterHandler(handler_id handlerID);
+
+    status_t start(
+            bool runOnCallingThread = false,
+            bool canCallJava = false,
+            int32_t priority = PRIORITY_DEFAULT
+            );
+
+    status_t stop();
+
+    static int64_t GetNowUs();
+
+protected:
+    virtual ~ALooper();
+
+private:
+    friend struct ALooperRoster;
+
+    struct Event {
+        int64_t mWhenUs;
+        sp<AMessage> mMessage;
+    };
+
+    Mutex mLock;
+    Condition mQueueChangedCondition;
+
+    List<Event> mEventQueue;
+
+    struct LooperThread;
+    sp<LooperThread> mThread;
+    bool mRunningLocally;
+
+    void post(const sp<AMessage> &msg, int64_t delayUs);
+    bool loop();
+
+    DISALLOW_EVIL_CONSTRUCTORS(ALooper);
+};
+
+}  // namespace android
+
+#endif  // A_LOOPER_H_
diff --git a/include/media/stagefright/foundation/ALooperRoster.h b/include/media/stagefright/foundation/ALooperRoster.h
new file mode 100644
index 0000000..c1bd4ed
--- /dev/null
+++ b/include/media/stagefright/foundation/ALooperRoster.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 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 A_LOOPER_ROSTER_H_
+
+#define A_LOOPER_ROSTER_H_
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+struct ALooperRoster {
+    ALooperRoster();
+
+    ALooper::handler_id registerHandler(
+            const sp<ALooper> looper, const sp<AHandler> &handler);
+
+    void unregisterHandler(ALooper::handler_id handlerID);
+
+    void postMessage(const sp<AMessage> &msg, int64_t delayUs = 0);
+    void deliverMessage(const sp<AMessage> &msg);
+
+    sp<ALooper> findLooper(ALooper::handler_id handlerID);
+
+private:
+    struct HandlerInfo {
+        wp<ALooper> mLooper;
+        wp<AHandler> mHandler;
+    };
+
+    Mutex mLock;
+    KeyedVector<ALooper::handler_id, HandlerInfo> mHandlers;
+    ALooper::handler_id mNextHandlerID;
+
+    DISALLOW_EVIL_CONSTRUCTORS(ALooperRoster);
+};
+
+}  // namespace android
+
+#endif  // A_LOOPER_ROSTER_H_
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
new file mode 100644
index 0000000..c674cba
--- /dev/null
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2010 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 A_MESSAGE_H_
+
+#define A_MESSAGE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct AString;
+
+struct AMessage : public RefBase {
+    AMessage(uint32_t what = 0, ALooper::handler_id target = 0);
+
+    void setWhat(uint32_t what);
+    uint32_t what() const;
+
+    void setTarget(ALooper::handler_id target);
+    ALooper::handler_id target() const;
+
+    void setInt32(const char *name, int32_t value);
+    void setInt64(const char *name, int64_t value);
+    void setSize(const char *name, size_t value);
+    void setFloat(const char *name, float value);
+    void setDouble(const char *name, double value);
+    void setPointer(const char *name, void *value);
+    void setString(const char *name, const char *s, ssize_t len = -1);
+    void setObject(const char *name, const sp<RefBase> &obj);
+    void setMessage(const char *name, const sp<AMessage> &obj);
+
+    bool findInt32(const char *name, int32_t *value) const;
+    bool findInt64(const char *name, int64_t *value) const;
+    bool findSize(const char *name, size_t *value) const;
+    bool findFloat(const char *name, float *value) const;
+    bool findDouble(const char *name, double *value) const;
+    bool findPointer(const char *name, void **value) const;
+    bool findString(const char *name, AString *value) const;
+    bool findObject(const char *name, sp<RefBase> *obj) const;
+    bool findMessage(const char *name, sp<AMessage> *obj) const;
+
+    void post(int64_t delayUs = 0);
+
+    sp<AMessage> dup() const;
+
+    AString debugString(int32_t indent = 0) const;
+
+protected:
+    virtual ~AMessage();
+
+private:
+    enum Type {
+        kTypeInt32,
+        kTypeInt64,
+        kTypeSize,
+        kTypeFloat,
+        kTypeDouble,
+        kTypePointer,
+        kTypeString,
+        kTypeObject,
+        kTypeMessage,
+    };
+
+    uint32_t mWhat;
+    ALooper::handler_id mTarget;
+
+    struct Item {
+        union {
+            int32_t int32Value;
+            int64_t int64Value;
+            size_t sizeValue;
+            float floatValue;
+            double doubleValue;
+            void *ptrValue;
+            RefBase *refValue;
+            AString *stringValue;
+        } u;
+        const char *mName;
+        Type mType;
+    };
+
+    enum {
+        kMaxNumItems = 16
+    };
+    Item mItems[kMaxNumItems];
+    size_t mNumItems;
+
+    void clear();
+    Item *allocateItem(const char *name);
+    void freeItem(Item *item);
+    const Item *findItem(const char *name, Type type) const;
+
+    DISALLOW_EVIL_CONSTRUCTORS(AMessage);
+};
+
+}  // namespace android
+
+#endif  // A_MESSAGE_H_
diff --git a/include/media/stagefright/foundation/AString.h b/include/media/stagefright/foundation/AString.h
new file mode 100644
index 0000000..55ade64
--- /dev/null
+++ b/include/media/stagefright/foundation/AString.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2010 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 A_STRING_H_
+
+#define A_STRING_H_
+
+#include <sys/types.h>
+
+namespace android {
+
+struct AString {
+    AString();
+    AString(const char *s);
+    AString(const char *s, size_t size);
+    AString(const AString &from);
+    AString(const AString &from, size_t offset, size_t n);
+    ~AString();
+
+    AString &operator=(const AString &from);
+    void setTo(const char *s);
+    void setTo(const char *s, size_t size);
+    void setTo(const AString &from, size_t offset, size_t n);
+
+    size_t size() const;
+    const char *c_str() const;
+
+    bool empty() const;
+
+    void clear();
+    void trim();
+    void erase(size_t start, size_t n);
+
+    void append(char c) { append(&c, 1); }
+    void append(const char *s);
+    void append(const char *s, size_t size);
+    void append(const AString &from);
+    void append(const AString &from, size_t offset, size_t n);
+    void append(int x);
+    void append(unsigned x);
+    void append(long x);
+    void append(unsigned long x);
+    void append(long long x);
+    void append(unsigned long long x);
+    void append(float x);
+    void append(double x);
+    void append(void *x);
+
+    void insert(const AString &from, size_t insertionPos);
+    void insert(const char *from, size_t size, size_t insertionPos);
+
+    ssize_t find(const char *substring, size_t start = 0) const;
+
+    size_t hash() const;
+
+    bool operator==(const AString &other) const;
+    bool operator<(const AString &other) const;
+    bool operator>(const AString &other) const;
+
+    int compare(const AString &other) const;
+
+    bool startsWith(const char *prefix) const;
+
+    void tolower();
+
+private:
+    static const char *kEmptyString;
+
+    char *mData;
+    size_t mSize;
+    size_t mAllocSize;
+
+    void makeMutable();
+};
+
+AString StringPrintf(const char *format, ...);
+
+}  // namespace android
+
+#endif  // A_STRING_H_
+
diff --git a/include/media/stagefright/foundation/base64.h b/include/media/stagefright/foundation/base64.h
new file mode 100644
index 0000000..e340b89
--- /dev/null
+++ b/include/media/stagefright/foundation/base64.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 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 BASE_64_H_
+
+#define BASE_64_H_
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AString;
+
+sp<ABuffer> decodeBase64(const AString &s);
+void encodeBase64(const void *data, size_t size, AString *out);
+
+}  // namespace android
+
+#endif  // BASE_64_H_
diff --git a/include/media/stagefright/foundation/hexdump.h b/include/media/stagefright/foundation/hexdump.h
new file mode 100644
index 0000000..f6083a9
--- /dev/null
+++ b/include/media/stagefright/foundation/hexdump.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 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 HEXDUMP_H_
+
+#define HEXDUMP_H_
+
+#include <sys/types.h>
+
+namespace android {
+
+void hexdump(const void *_data, size_t size);
+
+}  // namespace android
+
+#endif  // HEXDUMP_H_
diff --git a/include/private/README b/include/private/README
new file mode 100644
index 0000000..ee41492
--- /dev/null
+++ b/include/private/README
@@ -0,0 +1,4 @@
+This folder contains private include files.
+
+These include files are part of the private implementation details of
+various framework components.  Use at your peril.
diff --git a/include/private/media/AudioEffectShared.h b/include/private/media/AudioEffectShared.h
new file mode 100644
index 0000000..a3a99a4
--- /dev/null
+++ b/include/private/media/AudioEffectShared.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTCBASESHARED_H
+#define ANDROID_EFFECTCBASESHARED_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// Size of buffer used to exchange parameters between application and mediaserver processes.
+#define EFFECT_PARAM_BUFFER_SIZE 1024
+
+
+// Shared memory area used to exchange parameters between application and mediaserver
+// process.
+struct effect_param_cblk_t
+{
+                Mutex       lock;
+    volatile    uint32_t    clientIndex;    // Current read/write index for application
+    volatile    uint32_t    serverIndex;    // Current read/write index for mediaserver
+                uint8_t*    buffer;         // start of parameter buffer
+
+                effect_param_cblk_t()
+                    : lock(Mutex::SHARED), clientIndex(0), serverIndex(0) {}
+};
+
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_EFFECTCBASESHARED_H
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 8e2db20..1510f87 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -32,6 +32,18 @@
 #define MAX_RUN_TIMEOUT_MS      1000
 #define WAIT_PERIOD_MS          10
 
+#define CBLK_UNDERRUN_MSK       0x0001
+#define CBLK_UNDERRUN_ON        0x0001  // underrun (out) or overrrun (in) indication
+#define CBLK_UNDERRUN_OFF       0x0000  // no underrun
+#define CBLK_DIRECTION_MSK      0x0002
+#define CBLK_DIRECTION_OUT      0x0002  // this cblk is for an AudioTrack
+#define CBLK_DIRECTION_IN       0x0000  // this cblk is for an AudioRecord
+#define CBLK_FORCEREADY_MSK     0x0004
+#define CBLK_FORCEREADY_ON      0x0004  // track is considered ready immediately by AudioFlinger
+#define CBLK_FORCEREADY_OFF     0x0000  // track is ready when buffer full
+#define CBLK_INVALID_MSK        0x0008
+#define CBLK_INVALID_ON         0x0008  // track buffer is invalidated by AudioFlinger: must be re-created
+#define CBLK_INVALID_OFF        0x0000
 
 struct audio_track_cblk_t
 {
@@ -44,12 +56,12 @@
     volatile    uint32_t    server;
                 uint32_t    userBase;
                 uint32_t    serverBase;
-    void*       buffers;
-    uint32_t    frameCount;
-    // Cache line boundary
-    uint32_t    loopStart;
-    uint32_t    loopEnd;
-    int         loopCount;
+                void*       buffers;
+                uint32_t    frameCount;
+                // Cache line boundary
+                uint32_t    loopStart;
+                uint32_t    loopEnd;
+                int         loopCount;
     volatile    union {
                     uint16_t    volume[2];
                     uint32_t    volumeLR;
@@ -58,15 +70,17 @@
                 // NOTE: audio_track_cblk_t::frameSize is not equal to AudioTrack::frameSize() for
                 // 8 bit PCM data: in this case,  mCblk->frameSize is based on a sample size of
                 // 16 bit because data is converted to 16 bit before being stored in buffer
-                uint32_t    frameSize;
-                uint8_t     channels;
-                uint8_t     flowControlFlag; // underrun (out) or overrrun (in) indication
-                uint8_t     out;        // out equals 1 for AudioTrack and 0 for AudioRecord
-                uint8_t     forceReady;
+
+                uint8_t     frameSize;
+                uint8_t     channelCount;
+                uint16_t    flags;
+
                 uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
                 uint16_t    waitTimeMs;      // Cumulated wait time
-                // Cache line boundary (32 bytes)
 
+                uint16_t    sendLevel;
+                uint16_t    reserved;
+                // Cache line boundary (32 bytes)
                             audio_track_cblk_t();
                 uint32_t    stepUser(uint32_t frameCount);
                 bool        stepServer(uint32_t frameCount);
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index 9b5a1e0..1eb178e 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -43,24 +43,9 @@
  * unless they are in use by the server, which is only the case for the last 
  * dequeue-able buffer. When these various conditions are not met, the caller
  * waits until the condition is met.
- *
- * 
- * CAVEATS:
- * 
- * In the current implementation there are several limitations:
- * - buffers must be locked in the same order they've been dequeued
- * - buffers must be enqueued in the same order they've been locked
- * - dequeue() is not reentrant
- * - no error checks are done on the condition above
  * 
  */
 
-// When changing these values, the COMPILE_TIME_ASSERT at the end of this
-// file need to be updated.
-const unsigned int NUM_LAYERS_MAX  = 31;
-const unsigned int NUM_BUFFER_MAX  = 4;
-const unsigned int NUM_DISPLAY_MAX = 4;
-
 // ----------------------------------------------------------------------------
 
 class Region;
@@ -69,7 +54,11 @@
 
 // ----------------------------------------------------------------------------
 
-// should be 128 bytes (32 longs)
+// 4 * (11 + 7 + (1 + 2*NUM_RECT_MAX) * NUM_BUFFER_MAX) * NUM_LAYERS_MAX
+// 4 * (11 + 7 + (1 + 2*7)*16) * 31
+// 1032 * 31
+// = ~27 KiB (31992)
+
 class SharedBufferStack
 {
     friend class SharedClient;
@@ -78,21 +67,38 @@
     friend class SharedBufferServer;
 
 public:
-    struct FlatRegion { // 12 bytes
-        static const unsigned int NUM_RECT_MAX = 1;
-        uint32_t    count;
-        uint16_t    rects[4*NUM_RECT_MAX];
-    };
-    
+    // When changing these values, the COMPILE_TIME_ASSERT at the end of this
+    // file need to be updated.
+    static const unsigned int NUM_LAYERS_MAX  = 31;
+    static const unsigned int NUM_BUFFER_MAX  = 16;
+    static const unsigned int NUM_BUFFER_MIN  = 2;
+    static const unsigned int NUM_DISPLAY_MAX = 4;
+
     struct Statistics { // 4 longs
         typedef int32_t usecs_t;
         usecs_t  totalTime;
         usecs_t  reserved[3];
     };
+
+    struct SmallRect {
+        uint16_t l, t, r, b;
+    };
+
+    struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
+        static const unsigned int NUM_RECT_MAX = 6;
+        uint32_t    count;
+        SmallRect   rects[NUM_RECT_MAX];
+    };
+    
+    struct BufferData {
+        FlatRegion dirtyRegion;
+        SmallRect  crop;
+    };
     
     SharedBufferStack();
     void init(int32_t identity);
     status_t setDirtyRegion(int buffer, const Region& reg);
+    status_t setCrop(int buffer, const Rect& reg);
     Region getDirtyRegion(int buffer) const;
 
     // these attributes are part of the conditions/updates
@@ -104,24 +110,25 @@
 
     // not part of the conditions
     volatile int32_t reallocMask;
+    volatile int8_t index[NUM_BUFFER_MAX];
 
     int32_t     identity;       // surface's identity (const)
-    int32_t     reserved32[9];
+    int32_t     token;          // surface's token (for debugging)
+    int32_t     reserved32[1];
     Statistics  stats;
-    FlatRegion  dirtyRegion[NUM_BUFFER_MAX];    // 12*4=48 bytes
+    int32_t     reserved;
+    BufferData  buffers[NUM_BUFFER_MAX];     // 960 bytes
 };
 
 // ----------------------------------------------------------------------------
 
-// 4 KB max
+// 32 KB max
 class SharedClient
 {
 public:
     SharedClient();
     ~SharedClient();
-
     status_t validate(size_t token) const;
-    uint32_t getIdentity(size_t token) const;
 
 private:
     friend class SharedBufferBase;
@@ -131,7 +138,7 @@
     // FIXME: this should be replaced by a lock-less primitive
     Mutex lock;
     Condition cv;
-    SharedBufferStack surfaces[ NUM_LAYERS_MAX ];
+    SharedBufferStack surfaces[ SharedBufferStack::NUM_LAYERS_MAX ];
 };
 
 // ============================================================================
@@ -139,18 +146,17 @@
 class SharedBufferBase
 {
 public:
-    SharedBufferBase(SharedClient* sharedClient, int surface, int num,
+    SharedBufferBase(SharedClient* sharedClient, int surface,
             int32_t identity);
     ~SharedBufferBase();
-    uint32_t getIdentity();
     status_t getStatus() const;
+    int32_t getIdentity() const;
     size_t getFrontBuffer() const;
     String8 dump(char const* prefix) const;
 
 protected:
     SharedClient* const mSharedClient;
     SharedBufferStack* const mSharedStack;
-    const int mNumBuffers;
     const int mIdentity;
 
     friend struct Update;
@@ -160,61 +166,22 @@
         SharedBufferStack& stack;
         inline ConditionBase(SharedBufferBase* sbc) 
             : stack(*sbc->mSharedStack) { }
+        virtual ~ConditionBase() { };
+        virtual bool operator()() const = 0;
+        virtual const char* name() const = 0;
     };
+    status_t waitForCondition(const ConditionBase& condition);
 
     struct UpdateBase {
         SharedBufferStack& stack;
         inline UpdateBase(SharedBufferBase* sbb) 
             : stack(*sbb->mSharedStack) { }
     };
-
-    template <typename T>
-    status_t waitForCondition(T condition);
-
     template <typename T>
     status_t updateCondition(T update);
 };
 
 template <typename T>
-status_t SharedBufferBase::waitForCondition(T condition) 
-{
-    const SharedBufferStack& stack( *mSharedStack );
-    SharedClient& client( *mSharedClient );
-    const nsecs_t TIMEOUT = s2ns(1);
-    Mutex::Autolock _l(client.lock);
-    while ((condition()==false) &&
-            (stack.identity == mIdentity) &&
-            (stack.status == NO_ERROR))
-    {
-        status_t err = client.cv.waitRelative(client.lock, TIMEOUT);
-        
-        // handle errors and timeouts
-        if (CC_UNLIKELY(err != NO_ERROR)) {
-            if (err == TIMED_OUT) {
-                if (condition()) {
-                    LOGE("waitForCondition(%s) timed out (identity=%d), "
-                        "but condition is true! We recovered but it "
-                        "shouldn't happen." , T::name(),
-                        stack.identity);
-                    break;
-                } else {
-                    LOGW("waitForCondition(%s) timed out "
-                        "(identity=%d, status=%d). "
-                        "CPU may be pegged. trying again.", T::name(),
-                        stack.identity, stack.status);
-                }
-            } else {
-                LOGE("waitForCondition(%s) error (%s) ",
-                        T::name(), strerror(-err));
-                return err;
-            }
-        }
-    }
-    return (stack.identity != mIdentity) ? status_t(BAD_INDEX) : stack.status;
-}
-
-
-template <typename T>
 status_t SharedBufferBase::updateCondition(T update) {
     SharedClient& client( *mSharedClient );
     Mutex::Autolock _l(client.lock);
@@ -238,13 +205,21 @@
     status_t queue(int buf);
     bool needNewBuffer(int buffer) const;
     status_t setDirtyRegion(int buffer, const Region& reg);
+    status_t setCrop(int buffer, const Rect& reg);
     
+
+    class SetBufferCountCallback {
+        friend class SharedBufferClient;
+        virtual status_t operator()(int bufferCount) const = 0;
+    protected:
+        virtual ~SetBufferCountCallback() { }
+    };
+    status_t setBufferCount(int bufferCount, const SetBufferCountCallback& ipc);
+
 private:
     friend struct Condition;
     friend struct DequeueCondition;
     friend struct LockCondition;
-    
-    int32_t computeTail() const;
 
     struct QueueUpdate : public UpdateBase {
         inline QueueUpdate(SharedBufferBase* sbb);
@@ -260,25 +235,34 @@
 
     struct DequeueCondition : public ConditionBase {
         inline DequeueCondition(SharedBufferClient* sbc);
-        inline bool operator()();
-        static inline const char* name() { return "DequeueCondition"; }
+        inline bool operator()() const;
+        inline const char* name() const { return "DequeueCondition"; }
     };
 
     struct LockCondition : public ConditionBase {
         int buf;
         inline LockCondition(SharedBufferClient* sbc, int buf);
-        inline bool operator()();
-        static inline const char* name() { return "LockCondition"; }
+        inline bool operator()() const;
+        inline const char* name() const { return "LockCondition"; }
     };
 
+    int32_t computeTail() const;
+
+    mutable RWLock mLock;
+    int mNumBuffers;
+
     int32_t tail;
+    int32_t undoDequeueTail;
+    int32_t queued_head;
     // statistics...
-    nsecs_t mDequeueTime[NUM_BUFFER_MAX];
+    nsecs_t mDequeueTime[SharedBufferStack::NUM_BUFFER_MAX];
 };
 
 // ----------------------------------------------------------------------------
 
-class SharedBufferServer : public SharedBufferBase
+class SharedBufferServer
+    : public SharedBufferBase,
+      public LightRefBase<SharedBufferServer>
 {
 public:
     SharedBufferServer(SharedClient* sharedClient, int surface, int num,
@@ -287,16 +271,73 @@
     ssize_t retireAndLock();
     status_t unlock(int buffer);
     void setStatus(status_t status);
-    status_t reallocate();
-    status_t assertReallocate(int buffer);
+    status_t reallocateAll();
+    status_t reallocateAllExcept(int buffer);
     int32_t getQueuedCount() const;
-    
     Region getDirtyRegion(int buffer) const;
 
+    status_t resize(int newNumBuffers);
+
     SharedBufferStack::Statistics getStats() const;
     
 
 private:
+    friend class LightRefBase<SharedBufferServer>;
+    ~SharedBufferServer();
+
+    /*
+     * BufferList is basically a fixed-capacity sorted-vector of
+     * unsigned 5-bits ints using a 32-bits int as storage.
+     * it has efficient iterators to find items in the list and not in the list.
+     */
+    class BufferList {
+        size_t mCapacity;
+        uint32_t mList;
+    public:
+        BufferList(size_t c = SharedBufferStack::NUM_BUFFER_MAX)
+            : mCapacity(c), mList(0) { }
+        status_t add(int value);
+        status_t remove(int value);
+        uint32_t getMask() const { return mList; }
+
+        class const_iterator {
+            friend class BufferList;
+            uint32_t mask, curr;
+            const_iterator(uint32_t mask) :
+                mask(mask), curr(__builtin_clz(mask)) {
+            }
+        public:
+            inline bool operator == (const const_iterator& rhs) const {
+                return mask == rhs.mask;
+            }
+            inline bool operator != (const const_iterator& rhs) const {
+                return mask != rhs.mask;
+            }
+            inline int operator *() const { return curr; }
+            inline const const_iterator& operator ++() {
+                mask &= ~(1<<(31-curr));
+                curr = __builtin_clz(mask);
+                return *this;
+            }
+        };
+
+        inline const_iterator begin() const {
+            return const_iterator(mList);
+        }
+        inline const_iterator end() const   {
+            return const_iterator(0);
+        }
+        inline const_iterator free_begin() const {
+            uint32_t mask = (1 << (32-mCapacity)) - 1;
+            return const_iterator( ~(mList | mask) );
+        }
+    };
+
+    // this protects mNumBuffers and mBufferList
+    mutable RWLock mLock;
+    int mNumBuffers;
+    BufferList mBufferList;
+
     struct UnlockUpdate : public UpdateBase {
         const int lockedBuffer;
         inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer);
@@ -314,13 +355,6 @@
         inline StatusUpdate(SharedBufferBase* sbb, status_t status);
         inline ssize_t operator()();
     };
-
-    struct ReallocateCondition : public ConditionBase {
-        int buf;
-        inline ReallocateCondition(SharedBufferBase* sbb, int buf);
-        inline bool operator()();
-        static inline const char* name() { return "ReallocateCondition"; }
-    };
 };
 
 // ===========================================================================
@@ -344,13 +378,12 @@
     uint8_t         connected;
     uint8_t         reserved[3];
     uint32_t        pad[7];
-    display_cblk_t  displays[NUM_DISPLAY_MAX];
+    display_cblk_t  displays[SharedBufferStack::NUM_DISPLAY_MAX];
 };
 
 // ---------------------------------------------------------------------------
 
-COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 4096)
-COMPILE_TIME_ASSERT(sizeof(SharedBufferStack) == 128)
+COMPILE_TIME_ASSERT(sizeof(SharedClient) <= 32768)
 COMPILE_TIME_ASSERT(sizeof(surface_flinger_cblk_t) <= 4096)
 
 // ---------------------------------------------------------------------------
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
new file mode 100644
index 0000000..20f58e5
--- /dev/null
+++ b/media/libeffects/factory/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Effect factory library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectsFactory.c
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_MODULE:= libeffects
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
new file mode 100644
index 0000000..c19a505
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (C) 2010 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_TAG "EffectsFactory"
+//#define LOG_NDEBUG 0
+
+#include "EffectsFactory.h"
+#include <string.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+
+static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
+static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
+static pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList
+static uint32_t gNumEffects;         // total number number of effects
+static list_elem_t *gCurLib;    // current library in enumeration process
+static list_elem_t *gCurEffect; // current effect in enumeration process
+static uint32_t gCurEffectIdx;       // current effect index in enumeration process
+
+const char * const gEffectLibPath = "/system/lib/soundfx"; // path to built-in effect libraries
+static int gInitDone; // true is global initialization has been preformed
+static int gNextLibId; // used by loadLibrary() to allocate unique library handles
+static int gCanQueryEffect; // indicates that call to EffectQueryEffect() is valid, i.e. that the list of effects
+                          // was not modified since last call to EffectQueryNumberEffects()
+
+/////////////////////////////////////////////////
+//      Local functions prototypes
+/////////////////////////////////////////////////
+
+static int init();
+static int loadLibrary(const char *libPath, int *handle);
+static int unloadLibrary(int handle);
+static void resetEffectEnumeration();
+static uint32_t updateNumEffects();
+static int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc);
+static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
+
+/////////////////////////////////////////////////
+//      Effect Control Interface functions
+/////////////////////////////////////////////////
+
+int Effect_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    effect_entry_t *fx = (effect_entry_t *)self;
+    pthread_mutex_lock(&gLibLock);
+    if (fx->lib == NULL) {
+        pthread_mutex_unlock(&gLibLock);
+        return -EPIPE;
+    }
+    pthread_mutex_lock(&fx->lib->lock);
+    pthread_mutex_unlock(&gLibLock);
+
+    ret = (*fx->subItfe)->process(fx->subItfe, inBuffer, outBuffer);
+    pthread_mutex_unlock(&fx->lib->lock);
+    return ret;
+}
+
+int Effect_Command(effect_interface_t self,
+                   uint32_t cmdCode,
+                   uint32_t cmdSize,
+                   void *pCmdData,
+                   uint32_t *replySize,
+                   void *pReplyData)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    effect_entry_t *fx = (effect_entry_t *)self;
+    pthread_mutex_lock(&gLibLock);
+    if (fx->lib == NULL) {
+        pthread_mutex_unlock(&gLibLock);
+        return -EPIPE;
+    }
+    pthread_mutex_lock(&fx->lib->lock);
+    pthread_mutex_unlock(&gLibLock);
+
+    ret = (*fx->subItfe)->command(fx->subItfe, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+    pthread_mutex_unlock(&fx->lib->lock);
+    return ret;
+}
+
+const struct effect_interface_s gInterface = {
+        Effect_Process,
+        Effect_Command
+};
+
+/////////////////////////////////////////////////
+//      Effect Factory Interface functions
+/////////////////////////////////////////////////
+
+int EffectQueryNumberEffects(uint32_t *pNumEffects)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pNumEffects == NULL) {
+        return -EINVAL;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+    *pNumEffects = gNumEffects;
+    gCanQueryEffect = 1;
+    pthread_mutex_unlock(&gLibLock);
+    LOGV("EffectQueryNumberEffects(): %d", *pNumEffects);
+    return ret;
+}
+
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pDescriptor == NULL ||
+        index >= gNumEffects) {
+        return -EINVAL;
+    }
+    if (gCanQueryEffect == 0) {
+        return -ENOSYS;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+    ret = -ENOENT;
+    if (index < gCurEffectIdx) {
+        resetEffectEnumeration();
+    }
+    while (gCurLib) {
+        if (gCurEffect) {
+            if (index == gCurEffectIdx) {
+                memcpy(pDescriptor, gCurEffect->object, sizeof(effect_descriptor_t));
+                ret = 0;
+                break;
+            } else {
+                gCurEffect = gCurEffect->next;
+                gCurEffectIdx++;
+            }
+        } else {
+            gCurLib = gCurLib->next;
+            gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
+        }
+    }
+
+#if (LOG_NDEBUG == 0)
+    char str[256];
+    dumpEffectDescriptor(pDescriptor, str, 256);
+    LOGV("EffectQueryEffect() desc:%s", str);
+#endif
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectGetDescriptor(effect_uuid_t *uuid, effect_descriptor_t *pDescriptor)
+{
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (pDescriptor == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+    pthread_mutex_lock(&gLibLock);
+    ret = findEffect(uuid, &l, &d);
+    if (ret == 0) {
+        memcpy(pDescriptor, d, sizeof(effect_descriptor_t));
+    }
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectCreate(effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_interface_t *pInterface)
+{
+    list_elem_t *e = gLibraryList;
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+    effect_interface_t itfe;
+    effect_entry_t *fx;
+    int found = 0;
+    int ret;
+
+    if (uuid == NULL || pInterface == NULL) {
+        return -EINVAL;
+    }
+
+    LOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+            uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
+            uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2],
+            uuid->node[3],uuid->node[4],uuid->node[5]);
+
+    ret = init();
+
+    if (ret < 0) {
+        LOGW("EffectCreate() init error: %d", ret);
+        return ret;
+    }
+
+    pthread_mutex_lock(&gLibLock);
+
+    ret = findEffect(uuid, &l, &d);
+    if (ret < 0){
+        goto exit;
+    }
+
+    // create effect in library
+    ret = l->createFx(uuid, sessionId, ioId, &itfe);
+    if (ret != 0) {
+        LOGW("EffectCreate() library %s: could not create fx %s, error %d", l->path, d->name, ret);
+        goto exit;
+    }
+
+    // add entry to effect list
+    fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
+    fx->subItfe = itfe;
+    fx->itfe = (struct effect_interface_s *)&gInterface;
+    fx->lib = l;
+
+    e = (list_elem_t *)malloc(sizeof(list_elem_t));
+    e->object = fx;
+    e->next = gEffectList;
+    gEffectList = e;
+
+    *pInterface = (effect_interface_t)fx;
+
+    LOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pInterface, itfe, l->path);
+
+exit:
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectRelease(effect_interface_t interface)
+{
+    effect_entry_t *fx;
+    list_elem_t *e1;
+    list_elem_t *e2;
+
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+
+    // remove effect from effect list
+    pthread_mutex_lock(&gLibLock);
+    e1 = gEffectList;
+    e2 = NULL;
+    while (e1) {
+        if (e1->object == interface) {
+            if (e2) {
+                e2->next = e1->next;
+            } else {
+                gEffectList = e1->next;
+            }
+            fx = (effect_entry_t *)e1->object;
+            free(e1);
+            break;
+        }
+        e2 = e1;
+        e1 = e1->next;
+    }
+    if (e1 == NULL) {
+        ret = -ENOENT;
+        goto exit;
+    }
+
+    // release effect in library
+    if (fx->lib == NULL) {
+        LOGW("EffectRelease() fx %p library already unloaded", interface);
+    } else {
+        pthread_mutex_lock(&fx->lib->lock);
+        fx->lib->releaseFx(fx->subItfe);
+        pthread_mutex_unlock(&fx->lib->lock);
+    }
+    free(fx);
+
+exit:
+    pthread_mutex_unlock(&gLibLock);
+    return ret;
+}
+
+int EffectLoadLibrary(const char *libPath, int *handle)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+    if (libPath == NULL) {
+        return -EINVAL;
+    }
+
+    ret = loadLibrary(libPath, handle);
+    updateNumEffects();
+    return ret;
+}
+
+int EffectUnloadLibrary(int handle)
+{
+    int ret = init();
+    if (ret < 0) {
+        return ret;
+    }
+
+    ret = unloadLibrary(handle);
+    updateNumEffects();
+    return ret;
+}
+
+int EffectIsNullUuid(effect_uuid_t *uuid)
+{
+    if (memcmp(uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t))) {
+        return 0;
+    }
+    return 1;
+}
+
+/////////////////////////////////////////////////
+//      Local functions
+/////////////////////////////////////////////////
+
+int init() {
+    struct dirent *ent;
+    DIR *dir = NULL;
+    char libpath[PATH_MAX];
+    int hdl;
+
+    if (gInitDone) {
+        return 0;
+    }
+
+    pthread_mutex_init(&gLibLock, NULL);
+
+    // load built-in libraries
+    dir = opendir(gEffectLibPath);
+    if (dir == NULL) {
+        return -ENODEV;
+    }
+    while ((ent = readdir(dir)) != NULL) {
+        LOGV("init() reading file %s", ent->d_name);
+        if ((strlen(ent->d_name) < 3) ||
+            strncmp(ent->d_name, "lib", 3) != 0 ||
+            strncmp(ent->d_name + strlen(ent->d_name) - 3, ".so", 3) != 0) {
+            continue;
+        }
+        strcpy(libpath, gEffectLibPath);
+        strcat(libpath, "/");
+        strcat(libpath, ent->d_name);
+        if (loadLibrary(libpath, &hdl) < 0) {
+            LOGW("init() failed to load library %s",libpath);
+        }
+    }
+    closedir(dir);
+    updateNumEffects();
+    gInitDone = 1;
+    LOGV("init() done");
+    return 0;
+}
+
+
+int loadLibrary(const char *libPath, int *handle)
+{
+    void *hdl;
+    effect_QueryNumberEffects_t queryNumFx;
+    effect_QueryEffect_t queryFx;
+    effect_CreateEffect_t createFx;
+    effect_ReleaseEffect_t releaseFx;
+    uint32_t numFx;
+    uint32_t fx;
+    int ret;
+    list_elem_t *e, *descHead = NULL;
+    lib_entry_t *l;
+
+    if (handle == NULL) {
+        return -EINVAL;
+    }
+
+    *handle = 0;
+
+    hdl = dlopen(libPath, RTLD_NOW);
+    if (hdl == 0) {
+        LOGW("could open lib %s", libPath);
+        return -ENODEV;
+    }
+
+    // Check functions availability
+    queryNumFx = (effect_QueryNumberEffects_t)dlsym(hdl, "EffectQueryNumberEffects");
+    if (queryNumFx == NULL) {
+        LOGW("could not get EffectQueryNumberEffects from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    queryFx = (effect_QueryEffect_t)dlsym(hdl, "EffectQueryEffect");
+    if (queryFx == NULL) {
+        LOGW("could not get EffectQueryEffect from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    createFx = (effect_CreateEffect_t)dlsym(hdl, "EffectCreate");
+    if (createFx == NULL) {
+        LOGW("could not get EffectCreate from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+    releaseFx = (effect_ReleaseEffect_t)dlsym(hdl, "EffectRelease");
+    if (releaseFx == NULL) {
+        LOGW("could not get EffectRelease from lib %s", libPath);
+        ret = -ENODEV;
+        goto error;
+    }
+
+    // load effect descriptors
+    ret = queryNumFx(&numFx);
+    if (ret) {
+        goto error;
+    }
+
+    for (fx = 0; fx < numFx; fx++) {
+        effect_descriptor_t *d = malloc(sizeof(effect_descriptor_t));
+        if (d == NULL) {
+            ret = -ENOMEM;
+            goto error;
+        }
+        ret = queryFx(fx, d);
+        if (ret == 0) {
+#if (LOG_NDEBUG==0)
+            char s[256];
+            dumpEffectDescriptor(d, s, 256);
+            LOGV("loadLibrary() read descriptor %p:%s",d, s);
+#endif
+            if (d->apiVersion != EFFECT_API_VERSION) {
+                LOGW("Bad API version %04x on lib %s", d->apiVersion, libPath);
+                free(d);
+                continue;
+            }
+            e = malloc(sizeof(list_elem_t));
+            if (e == NULL) {
+                free(d);
+                ret = -ENOMEM;
+                goto error;
+            }
+            e->object = d;
+            e->next = descHead;
+            descHead = e;
+        } else {
+            LOGW("Error querying effect # %d on lib %s", fx, libPath);
+        }
+    }
+
+    pthread_mutex_lock(&gLibLock);
+
+    // add entry for library in gLibraryList
+    l = malloc(sizeof(lib_entry_t));
+    l->id = ++gNextLibId;
+    l->handle = hdl;
+    strncpy(l->path, libPath, PATH_MAX);
+    l->createFx = createFx;
+    l->releaseFx = releaseFx;
+    l->effects = descHead;
+    pthread_mutex_init(&l->lock, NULL);
+
+    e = malloc(sizeof(list_elem_t));
+    e->next = gLibraryList;
+    e->object = l;
+    gLibraryList = e;
+    pthread_mutex_unlock(&gLibLock);
+    LOGV("loadLibrary() linked library %p", l);
+
+    *handle = l->id;
+
+    return 0;
+
+error:
+    LOGW("loadLibrary() error: %d on lib: %s", ret, libPath);
+    while (descHead) {
+        free(descHead->object);
+        e = descHead->next;
+        free(descHead);
+        descHead = e;;
+    }
+    dlclose(hdl);
+    return ret;
+}
+
+int unloadLibrary(int handle)
+{
+    void *hdl;
+    int ret;
+    list_elem_t *el1, *el2;
+    lib_entry_t *l;
+    effect_entry_t *fx;
+
+    pthread_mutex_lock(&gLibLock);
+    el1 = gLibraryList;
+    el2 = NULL;
+    while (el1) {
+        l = (lib_entry_t *)el1->object;
+        if (handle == l->id) {
+            if (el2) {
+                el2->next = el1->next;
+            } else {
+                gLibraryList = el1->next;
+            }
+            free(el1);
+            break;
+        }
+        el2 = el1;
+        el1 = el1->next;
+    }
+    pthread_mutex_unlock(&gLibLock);
+    if (el1 == NULL) {
+        return -ENOENT;
+    }
+
+    // clear effect descriptor list
+    el1 = l->effects;
+    while (el1) {
+        free(el1->object);
+        el2 = el1->next;
+        free(el1);
+        el1 = el2;
+    }
+
+    // disable all effects from this library
+    pthread_mutex_lock(&l->lock);
+
+    el1 = gEffectList;
+    while (el1) {
+        fx = (effect_entry_t *)el1->object;
+        if (fx->lib == l) {
+            fx->lib = NULL;
+        }
+        el1 = el1->next;
+    }
+    pthread_mutex_unlock(&l->lock);
+
+    dlclose(l->handle);
+    free(l);
+    return 0;
+}
+
+void resetEffectEnumeration()
+{
+    gCurLib = gLibraryList;
+    gCurEffect = NULL;
+    if (gCurLib) {
+        gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
+    }
+    gCurEffectIdx = 0;
+}
+
+uint32_t updateNumEffects() {
+    list_elem_t *e;
+    uint32_t cnt = 0;
+
+    resetEffectEnumeration();
+
+    e = gLibraryList;
+    while (e) {
+        lib_entry_t *l = (lib_entry_t *)e->object;
+        list_elem_t *efx = l->effects;
+        while (efx) {
+            cnt++;
+            efx = efx->next;
+        }
+        e = e->next;
+    }
+    gNumEffects = cnt;
+    gCanQueryEffect = 0;
+    return cnt;
+}
+
+int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc)
+{
+    list_elem_t *e = gLibraryList;
+    lib_entry_t *l = NULL;
+    effect_descriptor_t *d = NULL;
+    int found = 0;
+    int ret = 0;
+
+    while (e && !found) {
+        l = (lib_entry_t *)e->object;
+        list_elem_t *efx = l->effects;
+        while (efx) {
+            d = (effect_descriptor_t *)efx->object;
+            if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
+                found = 1;
+                break;
+            }
+            efx = efx->next;
+        }
+        e = e->next;
+    }
+    if (!found) {
+        LOGV("findEffect() effect not found");
+        ret = -ENOENT;
+    } else {
+        LOGV("findEffect() found effect: %s in lib %s", d->name, l->path);
+        *lib = l;
+        *desc = d;
+    }
+
+    return ret;
+}
+
+void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len) {
+    char s[256];
+
+    snprintf(str, len, "\nEffect Descriptor %p:\n", desc);
+    sprintf(s, "- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+            desc->uuid.timeLow, desc->uuid.timeMid, desc->uuid.timeHiAndVersion,
+            desc->uuid.clockSeq, desc->uuid.node[0], desc->uuid.node[1],desc->uuid.node[2],
+            desc->uuid.node[3],desc->uuid.node[4],desc->uuid.node[5]);
+    strncat(str, s, len);
+    sprintf(s, "- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+                desc->type.timeLow, desc->type.timeMid, desc->type.timeHiAndVersion,
+                desc->type.clockSeq, desc->type.node[0], desc->type.node[1],desc->type.node[2],
+                desc->type.node[3],desc->type.node[4],desc->type.node[5]);
+    strncat(str, s, len);
+    sprintf(s, "- apiVersion: %04X\n- flags: %08X\n",
+            desc->apiVersion, desc->flags);
+    strncat(str, s, len);
+    sprintf(s, "- name: %s\n", desc->name);
+    strncat(str, s, len);
+    sprintf(s, "- implementor: %s\n", desc->implementor);
+    strncat(str, s, len);
+}
+
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
new file mode 100644
index 0000000..8f543ca
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTSFACTORY_H_
+#define ANDROID_EFFECTSFACTORY_H_
+
+#include <cutils/log.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <media/EffectsFactoryApi.h>
+
+
+#if __cplusplus
+extern "C" {
+#endif
+
+typedef struct list_elem_s {
+    void *object;
+    struct list_elem_s *next;
+} list_elem_t;
+
+typedef struct lib_entry_s {
+    char path[PATH_MAX];
+    void *handle;
+    int id;
+    effect_CreateEffect_t createFx;
+    effect_ReleaseEffect_t releaseFx;
+    list_elem_t *effects; //list of effect_descriptor_t
+    pthread_mutex_t lock;
+} lib_entry_t;
+
+typedef struct effect_entry_s {
+    struct effect_interface_s *itfe;
+    effect_interface_t subItfe;
+    lib_entry_t *lib;
+} effect_entry_t;
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTSFACTORY_H_*/
diff --git a/media/libeffects/lvm/lib/Android.mk b/media/libeffects/lvm/lib/Android.mk
new file mode 100644
index 0000000..a944212
--- /dev/null
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -0,0 +1,124 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Music bundle
+
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES:= \
+    StereoWidening/src/LVCS_BypassMix.c \
+    StereoWidening/src/LVCS_Control.c \
+    StereoWidening/src/LVCS_Equaliser.c \
+    StereoWidening/src/LVCS_Init.c \
+    StereoWidening/src/LVCS_Process.c \
+    StereoWidening/src/LVCS_ReverbGenerator.c \
+    StereoWidening/src/LVCS_StereoEnhancer.c \
+    StereoWidening/src/LVCS_Tables.c \
+    Bass/src/LVDBE_Control.c \
+    Bass/src/LVDBE_Init.c \
+    Bass/src/LVDBE_Process.c \
+    Bass/src/LVDBE_Tables.c \
+    Bundle/src/LVM_API_Specials.c \
+    Bundle/src/LVM_Buffers.c \
+    Bundle/src/LVM_Init.c \
+    Bundle/src/LVM_Process.c \
+    Bundle/src/LVM_Tables.c \
+    Bundle/src/LVM_Control.c \
+    SpectrumAnalyzer/src/LVPSA_Control.c \
+    SpectrumAnalyzer/src/LVPSA_Init.c \
+    SpectrumAnalyzer/src/LVPSA_Memory.c \
+    SpectrumAnalyzer/src/LVPSA_Process.c \
+    SpectrumAnalyzer/src/LVPSA_QPD_Init.c \
+    SpectrumAnalyzer/src/LVPSA_QPD_Process.c \
+    SpectrumAnalyzer/src/LVPSA_Tables.c \
+    Eq/src/LVEQNB_CalcCoef.c \
+    Eq/src/LVEQNB_Control.c \
+    Eq/src/LVEQNB_Init.c \
+    Eq/src/LVEQNB_Process.c \
+    Eq/src/LVEQNB_Tables.c \
+    Common/src/InstAlloc.c \
+    Common/src/DC_2I_D16_TRC_WRA_01.c \
+    Common/src/DC_2I_D16_TRC_WRA_01_Init.c \
+    Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c \
+    Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c \
+    Common/src/FO_1I_D16F16C15_TRC_WRA_01.c \
+    Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c \
+    Common/src/BP_1I_D16F32C30_TRC_WRA_01.c \
+    Common/src/BP_1I_D16F16C14_TRC_WRA_01.c \
+    Common/src/BP_1I_D32F32C30_TRC_WRA_02.c \
+    Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c \
+    Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c \
+    Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c \
+    Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c \
+    Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c \
+    Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c \
+    Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c \
+    Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c \
+    Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c \
+    Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c \
+    Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c \
+    Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c \
+    Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c \
+    Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c \
+    Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c \
+    Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c \
+    Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c \
+    Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c \
+    Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c \
+    Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c \
+    Common/src/Int16LShiftToInt32_16x32.c \
+    Common/src/From2iToMono_16.c \
+    Common/src/Copy_16.c \
+    Common/src/MonoTo2I_16.c \
+    Common/src/LoadConst_16.c \
+    Common/src/dB_to_Lin32.c \
+    Common/src/Shift_Sat_v16xv16.c \
+    Common/src/Abs_32.c \
+    Common/src/Int32RShiftToInt16_Sat_32x16.c \
+    Common/src/From2iToMono_32.c \
+    Common/src/mult3s_16x16.c \
+    Common/src/NonLinComp_D16.c \
+    Common/src/DelayMix_16x16.c \
+    Common/src/MSTo2i_Sat_16x16.c \
+    Common/src/From2iToMS_16x16.c \
+    Common/src/Mac3s_Sat_16x16.c \
+    Common/src/Add2_Sat_16x16.c \
+    Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c \
+    Common/src/LVC_MixSoft_1St_D16C31_SAT.c \
+    Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c \
+    Common/src/LVC_Mixer_SetTimeConstant.c \
+    Common/src/LVC_Mixer_SetTarget.c \
+    Common/src/LVC_Mixer_GetTarget.c \
+    Common/src/LVC_Mixer_Init.c \
+    Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c \
+    Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c \
+    Common/src/LVC_Core_MixInSoft_D16C31_SAT.c \
+    Common/src/LVC_Mixer_GetCurrent.c \
+    Common/src/LVC_MixSoft_2St_D16C31_SAT.c \
+    Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c \
+    Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c \
+    Common/src/LVC_MixInSoft_D16C31_SAT.c \
+    Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c \
+    Common/src/LVM_Timer.c \
+    Common/src/LVM_Timer_Init.c
+
+LOCAL_MODULE:= libmusicbundle
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_C_INCLUDES += \
+    $(LOCAL_PATH)/Eq/lib \
+    $(LOCAL_PATH)/Eq/src \
+    $(LOCAL_PATH)/Bass/lib \
+    $(LOCAL_PATH)/Bass/src \
+    $(LOCAL_PATH)/Common/lib \
+    $(LOCAL_PATH)/Common/src \
+    $(LOCAL_PATH)/Bundle/lib \
+    $(LOCAL_PATH)/Bundle/src \
+    $(LOCAL_PATH)/SpectrumAnalyzer/lib \
+    $(LOCAL_PATH)/SpectrumAnalyzer/src \
+    $(LOCAL_PATH)/StereoWidening/src \
+    $(LOCAL_PATH)/StereoWidening/lib
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
new file mode 100755
index 0000000..48731df
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1081 $
+     $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Header file for the application layer interface of Dynamic Bass Enhancement       */
+/*  module.                                                                             */
+/*                                                                                      */
+/*  This files includes all definitions, types, structures and function                 */
+/*  prototypes required by the calling layer. All other types, structures and           */
+/*  functions are private.                                                              */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*    Note: 1                                                                           */
+/*    =======                                                                           */
+/*    The algorithm can execute either with separate input and output buffers or with   */
+/*    a common buffer, i.e. the data is processed in-place.                             */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*    Note: 2                                                                           */
+/*    =======                                                                           */
+/*    The Dynamic Bass Enhancement algorithm always processes data as stereo input. Mono*/
+/*  format data is not supported. The data is interleaved as follows:                   */
+/*                                                                                      */
+/*              Byte Offset         Stereo Input         Mono-In-Stereo Input           */
+/*              ===========         ============         ====================           */
+/*                  0               Left Sample #1          Mono Sample #1              */
+/*                  2               Right Sample #1         Mono Sample #1              */
+/*                  4               Left Sample #2          Mono Sample #2              */
+/*                  6               Right Sample #2         Mono Sample #2              */
+/*                  .                      .                     .                      */
+/*                  .                      .                     .                      */
+/*                                                                                      */
+/*  Mono format data is not supported, the calling routine must convert a Mono stream   */
+/*    in to Mono-In-Stereo format.                                                      */
+/*                                                                                      */
+/****************************************************************************************/
+
+#ifndef __LVDBE_H__
+#define __LVDBE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVM_Types.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Definitions                                                                       */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory table*/
+#define LVDBE_NR_MEMORY_REGIONS        4                            /* Number of memory regions */
+
+/* Bass Enhancement effect level */
+#define LVDBE_EFFECT_03DB            3                              /* Effect defines for backwards compatibility */
+#define LVDBE_EFFECT_06DB            6
+#define LVDBE_EFFECT_09DB            9
+#define LVDBE_EFFECT_12DB            12
+#define LVDBE_EFFECT_15DB            15
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Types                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Instance handle */
+typedef void    *LVDBE_Handle_t;
+
+
+/* Operating modes */
+typedef enum
+{
+    LVDBE_OFF      = 0,
+    LVDBE_ON       = 1,
+    LVDBE_MODE_MAX = LVM_MAXINT_32
+} LVDBE_Mode_en;
+
+
+/* High pass filter */
+typedef enum
+{
+    LVDBE_HPF_OFF = 0,
+    LVDBE_HPF_ON  = 1,
+    LVDBE_HPF_MAX = LVM_MAXINT_32
+} LVDBE_FilterSelect_en;
+
+
+/* Volume control */
+typedef enum
+{
+    LVDBE_VOLUME_OFF = 0,
+    LVDBE_VOLUME_ON  = 1,
+    LVDBE_VOLUME_MAX = LVM_MAXINT_32
+} LVDBE_Volume_en;
+
+
+/* Memory Types */
+typedef enum
+{
+    LVDBE_PERSISTENT      = 0,
+    LVDBE_PERSISTENT_DATA = 1,
+    LVDBE_PERSISTENT_COEF = 2,
+    LVDBE_SCRATCH         = 3,
+    LVDBE_MEMORY_MAX      = LVM_MAXINT_32
+
+} LVDBE_MemoryTypes_en;
+
+
+/* Function return status */
+typedef enum
+{
+    LVDBE_SUCCESS        = 0,                        /* Successful return from a routine */
+    LVDBE_ALIGNMENTERROR = 1,                        /* Memory alignment error */
+    LVDBE_NULLADDRESS    = 2,                        /* NULL allocation address */
+    LVDBE_TOOMANYSAMPLES = 3,                        /* Maximum block size exceeded */
+    LVDBE_SIZEERROR      = 4,                        /* Incorrect structure size */
+    LVDBE_STATUS_MAX     = LVM_MAXINT_32
+} LVDBE_ReturnStatus_en;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Linked enumerated type and capability definitions                                 */
+/*                                                                                      */
+/*  The capability definitions are used to define the required capabilities at          */
+/*  initialisation, these are added together to give the capability word. The           */
+/*  enumerated type is used to select the mode through a control function at run time.  */
+/*                                                                                      */
+/*  The capability definition is related to the enumerated type value by the equation:  */
+/*                                                                                      */
+/*          Capability_value = 2^Enumerated_value                                       */
+/*                                                                                      */
+/*  For example, a module could be configurd at initialisation to support two sample    */
+/*  rates only by calling the init function with the value:                             */
+/*      Capabilities.SampleRate = LVDBE_CAP_32000 + LVCS_DBE_44100;                     */
+/*                                                                                      */
+/*  and at run time it would be passed the value LVDBE_FS_32000 through the control     */
+/*  function to select operation at 32kHz                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/*
+ * Bass Enhancement centre frequency
+ */
+#define LVDBE_CAP_CENTRE_55Hz       1
+#define LVDBE_CAP_CENTRE_66Hz       2
+#define LVDBE_CAP_CENTRE_78Hz       4
+#define LVDBE_CAP_CENTRE_90Hz       8
+
+typedef enum
+{
+    LVDBE_CENTRE_55HZ = 0,
+    LVDBE_CENTRE_66HZ = 1,
+    LVDBE_CENTRE_78HZ = 2,
+    LVDBE_CENTRE_90HZ = 3,
+    LVDBE_CENTRE_MAX  = LVM_MAXINT_32
+} LVDBE_CentreFreq_en;
+
+
+/*
+ * Supported sample rates in samples per second
+ */
+#define LVDBE_CAP_FS_8000                1
+#define LVDBE_CAP_FS_11025               2
+#define LVDBE_CAP_FS_12000               4
+#define LVDBE_CAP_FS_16000               8
+#define LVDBE_CAP_FS_22050               16
+#define LVDBE_CAP_FS_24000               32
+#define LVDBE_CAP_FS_32000               64
+#define LVDBE_CAP_FS_44100               128
+#define LVDBE_CAP_FS_48000               256
+
+typedef enum
+{
+    LVDBE_FS_8000  = 0,
+    LVDBE_FS_11025 = 1,
+    LVDBE_FS_12000 = 2,
+    LVDBE_FS_16000 = 3,
+    LVDBE_FS_22050 = 4,
+    LVDBE_FS_24000 = 5,
+    LVDBE_FS_32000 = 6,
+    LVDBE_FS_44100 = 7,
+    LVDBE_FS_48000 = 8,
+    LVDBE_FS_MAX   = LVM_MAXINT_32
+} LVDBE_Fs_en;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Structures                                                                        */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory region definition */
+typedef struct
+{
+    LVM_UINT32                Size;                        /* Region size in bytes */
+    LVM_UINT16                Alignment;                  /* Region alignment in bytes */
+    LVDBE_MemoryTypes_en      Type;                       /* Region type */
+    void                      *pBaseAddress;              /* Pointer to the region base address */
+} LVDBE_MemoryRegion_t;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+    LVDBE_MemoryRegion_t    Region[LVDBE_NR_MEMORY_REGIONS];  /* One definition for each region */
+} LVDBE_MemTab_t;
+
+
+/* Parameter structure */
+typedef struct
+{
+    LVDBE_Mode_en           OperatingMode;
+    LVDBE_Fs_en             SampleRate;
+    LVM_INT16               EffectLevel;
+    LVDBE_CentreFreq_en     CentreFrequency;
+    LVDBE_FilterSelect_en   HPFSelect;
+    LVDBE_Volume_en         VolumeControl;
+    LVM_INT16               VolumedB;
+    LVM_INT16               HeadroomdB;
+
+} LVDBE_Params_t;
+
+
+/* Capability structure */
+typedef struct
+{
+      LVM_UINT16              SampleRate;               /* Sampling rate capabilities */
+      LVM_UINT16              CentreFrequency;          /* Centre frequency capabilities */
+      LVM_UINT16              MaxBlockSize;             /* Maximum block size in sample pairs */
+} LVDBE_Capabilities_t;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Function Prototypes                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVDBE_Memory                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    This function is used for memory allocation and free. It can be called in         */
+/*    two ways:                                                                         */
+/*                                                                                      */
+/*        hInstance = NULL                Returns the memory requirements               */
+/*        hInstance = Instance handle        Returns the memory requirements and        */
+/*                                        allocated base addresses for the instance     */
+/*                                                                                      */
+/*    When this function is called for memory allocation (hInstance=NULL) the memory    */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*    When the function is called for free (hInstance = Instance Handle) the memory     */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance Handle                                            */
+/*  pMemoryTable             Pointer to an empty memory definition table                */
+/*    pCapabilities            Pointer to the default capabilites                       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS            Succeeded                                                  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*    1.    This function may be interrupted by the LVDBE_Process function              */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t           hInstance,
+                                   LVDBE_MemTab_t           *pMemoryTable,
+                                   LVDBE_Capabilities_t     *pCapabilities);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVDBE_Init                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Create and initialisation function for the Bass Enhancement module                */
+/*                                                                                      */
+/*    This function can be used to create an algorithm instance by calling with         */
+/*    hInstance set to NULL. In this case the algorithm returns the new instance        */
+/*    handle.                                                                           */
+/*                                                                                      */
+/*    This function can be used to force a full re-initialisation of the algorithm      */
+/*    by calling with hInstance = Instance Handle. In this case the memory table        */
+/*    should be correct for the instance, this can be ensured by calling the function   */
+/*    LVDBE_Memory before calling this function.                                        */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                  Instance handle                                          */
+/*  pMemoryTable             Pointer to the memory definition table                     */
+/*  pCapabilities            Pointer to the initialisation capabilities                 */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS                Initialisation succeeded                               */
+/*  LVDBE_ALIGNMENTERROR        Instance or scratch memory on incorrect alignment       */
+/*    LVDBE_NULLADDRESS            One or more memory has a NULL pointer                */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.     The instance handle is the pointer to the base address of the first memory   */
+/*        region.                                                                       */
+/*    2.    This function must not be interrupted by the LVDBE_Process function         */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t             *phInstance,
+                                   LVDBE_MemTab_t           *pMemoryTable,
+                                   LVDBE_Capabilities_t     *pCapabilities);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  LVDBE_GetParameters                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Request the Bass Enhancement parameters. The current parameter set is returned    */
+/*    via the parameter pointer.                                                        */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                   Instance handle                                         */
+/*  pParams                  Pointer to an empty parameter structure                    */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS             Always succeeds                                           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.    This function may be interrupted by the LVDBE_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t        hInstance,
+                                            LVDBE_Params_t      *pParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  LVDBE_GetCapabilities                                     */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Request the Dynamic Bass Enhancement capabilities. The initial capabilities are   */
+/*  returned via the pointer.                                                           */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                   Instance handle                                         */
+/*  pCapabilities              Pointer to an empty capabilitiy structure                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_Success             Always succeeds                                           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.    This function may be interrupted by the LVDBE_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t            hInstance,
+                                              LVDBE_Capabilities_t    *pCapabilities);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVDBE_Control                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the Bass Enhancement parameters. Changing the parameters while the  */
+/*  module is processing signals may have the following side effects:                   */
+/*                                                                                      */
+/*  General parameters:                                                                 */
+/*  ===================                                                                 */
+/*  OperatingMode:      Changing the mode of operation may cause a change in volume     */
+/*                      level.                                                          */
+/*                                                                                      */
+/*  SampleRate:         Changing the sample rate may cause pops and clicks.             */
+/*                                                                                      */
+/*  EffectLevel:        Changing the effect level setting will have no side effects     */
+/*                                                                                      */
+/*  CentreFrequency:    Changing the centre frequency may cause pops and clicks         */
+/*                                                                                      */
+/*  HPFSelect:          Selecting/de-selecting the high pass filter may cause pops and  */
+/*                      clicks                                                          */
+/*                                                                                      */
+/*  VolumedB            Changing the volume setting will have no side effects           */
+/*                                                                                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pParams                 Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS           Always succeeds                                             */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function must not be interrupted by the LVDBE_Process function             */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t      hInstance,
+                                      LVDBE_Params_t    *pParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVDBE_Process                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the Bass Enhancement module.                                   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance handle                                            */
+/*  pInData                  Pointer to the input data                                  */
+/*  pOutData                 Pointer to the output data                                 */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS             Succeeded                                                 */
+/*    LVDBE_TOOMANYSAMPLES    NumSamples was larger than the maximum block size         */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t          hInstance,
+                                       const LVM_INT16      *pInData,
+                                       LVM_INT16            *pOutData,
+                                       LVM_UINT16           NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVDBE_H__ */
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
new file mode 100755
index 0000000..94a7869
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 __LVDBE_COEFFS_H__
+#define __LVDBE_COEFFS_H__
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* General                                                                          */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVDBE_SCALESHIFT                                    10         /* As a power of 2 */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* High Pass Filter coefficients                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+ /* Coefficients for centre frequency 55Hz */
+#define HPF_Fs8000_Fc55_A0                         1029556328         /* Floating point value 0.958849 */
+#define HPF_Fs8000_Fc55_A1                        -2059112655         /* Floating point value -1.917698 */
+#define HPF_Fs8000_Fc55_A2                         1029556328         /* Floating point value 0.958849 */
+#define HPF_Fs8000_Fc55_B1                        -2081986375         /* Floating point value -1.939001 */
+#define HPF_Fs8000_Fc55_B2                         1010183914         /* Floating point value 0.940807 */
+#define HPF_Fs11025_Fc55_A0                        1038210831         /* Floating point value 0.966909 */
+#define HPF_Fs11025_Fc55_A1                       -2076421662         /* Floating point value -1.933818 */
+#define HPF_Fs11025_Fc55_A2                        1038210831         /* Floating point value 0.966909 */
+#define HPF_Fs11025_Fc55_B1                       -2099950710         /* Floating point value -1.955732 */
+#define HPF_Fs11025_Fc55_B2                        1027238450         /* Floating point value 0.956690 */
+#define HPF_Fs12000_Fc55_A0                        1040079943         /* Floating point value 0.968650 */
+#define HPF_Fs12000_Fc55_A1                       -2080159885         /* Floating point value -1.937300 */
+#define HPF_Fs12000_Fc55_A2                        1040079943         /* Floating point value 0.968650 */
+#define HPF_Fs12000_Fc55_B1                       -2103811702         /* Floating point value -1.959327 */
+#define HPF_Fs12000_Fc55_B2                        1030940477         /* Floating point value 0.960138 */
+#define HPF_Fs16000_Fc55_A0                        1045381988         /* Floating point value 0.973588 */
+#define HPF_Fs16000_Fc55_A1                       -2090763976         /* Floating point value -1.947176 */
+#define HPF_Fs16000_Fc55_A2                        1045381988         /* Floating point value 0.973588 */
+#define HPF_Fs16000_Fc55_B1                       -2114727793         /* Floating point value -1.969494 */
+#define HPF_Fs16000_Fc55_B2                        1041478147         /* Floating point value 0.969952 */
+#define HPF_Fs22050_Fc55_A0                        1049766523         /* Floating point value 0.977671 */
+#define HPF_Fs22050_Fc55_A1                       -2099533046         /* Floating point value -1.955343 */
+#define HPF_Fs22050_Fc55_A2                        1049766523         /* Floating point value 0.977671 */
+#define HPF_Fs22050_Fc55_B1                       -2123714381         /* Floating point value -1.977863 */
+#define HPF_Fs22050_Fc55_B2                        1050232780         /* Floating point value 0.978105 */
+#define HPF_Fs24000_Fc55_A0                        1050711051         /* Floating point value 0.978551 */
+#define HPF_Fs24000_Fc55_A1                       -2101422103         /* Floating point value -1.957102 */
+#define HPF_Fs24000_Fc55_A2                        1050711051         /* Floating point value 0.978551 */
+#define HPF_Fs24000_Fc55_B1                       -2125645498         /* Floating point value -1.979662 */
+#define HPF_Fs24000_Fc55_B2                        1052123526         /* Floating point value 0.979866 */
+#define HPF_Fs32000_Fc55_A0                        1053385759         /* Floating point value 0.981042 */
+#define HPF_Fs32000_Fc55_A1                       -2106771519         /* Floating point value -1.962084 */
+#define HPF_Fs32000_Fc55_A2                        1053385759         /* Floating point value 0.981042 */
+#define HPF_Fs32000_Fc55_B1                       -2131104794         /* Floating point value -1.984746 */
+#define HPF_Fs32000_Fc55_B2                        1057486949         /* Floating point value 0.984861 */
+#define HPF_Fs44100_Fc55_A0                        1055592498         /* Floating point value 0.983097 */
+#define HPF_Fs44100_Fc55_A1                       -2111184995         /* Floating point value -1.966194 */
+#define HPF_Fs44100_Fc55_A2                        1055592498         /* Floating point value 0.983097 */
+#define HPF_Fs44100_Fc55_B1                       -2135598658         /* Floating point value -1.988931 */
+#define HPF_Fs44100_Fc55_B2                        1061922249         /* Floating point value 0.988992 */
+#define HPF_Fs48000_Fc55_A0                        1056067276         /* Floating point value 0.983539 */
+#define HPF_Fs48000_Fc55_A1                       -2112134551         /* Floating point value -1.967079 */
+#define HPF_Fs48000_Fc55_A2                        1056067276         /* Floating point value 0.983539 */
+#define HPF_Fs48000_Fc55_B1                       -2136564296         /* Floating point value -1.989831 */
+#define HPF_Fs48000_Fc55_B2                        1062877714         /* Floating point value 0.989882 */
+
+ /* Coefficients for centre frequency 66Hz */
+#define HPF_Fs8000_Fc66_A0                         1023293271         /* Floating point value 0.953016 */
+#define HPF_Fs8000_Fc66_A1                        -2046586542         /* Floating point value -1.906032 */
+#define HPF_Fs8000_Fc66_A2                         1023293271         /* Floating point value 0.953016 */
+#define HPF_Fs8000_Fc66_B1                        -2068896860         /* Floating point value -1.926810 */
+#define HPF_Fs8000_Fc66_B2                          997931110         /* Floating point value 0.929396 */
+#define HPF_Fs11025_Fc66_A0                        1033624228         /* Floating point value 0.962638 */
+#define HPF_Fs11025_Fc66_A1                       -2067248455         /* Floating point value -1.925275 */
+#define HPF_Fs11025_Fc66_A2                        1033624228         /* Floating point value 0.962638 */
+#define HPF_Fs11025_Fc66_B1                       -2090448000         /* Floating point value -1.946881 */
+#define HPF_Fs11025_Fc66_B2                        1018182305         /* Floating point value 0.948256 */
+#define HPF_Fs12000_Fc66_A0                        1035857662         /* Floating point value 0.964718 */
+#define HPF_Fs12000_Fc66_A1                       -2071715325         /* Floating point value -1.929435 */
+#define HPF_Fs12000_Fc66_A2                        1035857662         /* Floating point value 0.964718 */
+#define HPF_Fs12000_Fc66_B1                       -2095080333         /* Floating point value -1.951196 */
+#define HPF_Fs12000_Fc66_B2                        1022587158         /* Floating point value 0.952359 */
+#define HPF_Fs16000_Fc66_A0                        1042197528         /* Floating point value 0.970622 */
+#define HPF_Fs16000_Fc66_A1                       -2084395056         /* Floating point value -1.941244 */
+#define HPF_Fs16000_Fc66_A2                        1042197528         /* Floating point value 0.970622 */
+#define HPF_Fs16000_Fc66_B1                       -2108177912         /* Floating point value -1.963394 */
+#define HPF_Fs16000_Fc66_B2                        1035142690         /* Floating point value 0.964052 */
+#define HPF_Fs22050_Fc66_A0                        1047445145         /* Floating point value 0.975509 */
+#define HPF_Fs22050_Fc66_A1                       -2094890289         /* Floating point value -1.951019 */
+#define HPF_Fs22050_Fc66_A2                        1047445145         /* Floating point value 0.975509 */
+#define HPF_Fs22050_Fc66_B1                       -2118961025         /* Floating point value -1.973436 */
+#define HPF_Fs22050_Fc66_B2                        1045593102         /* Floating point value 0.973784 */
+#define HPF_Fs24000_Fc66_A0                        1048576175         /* Floating point value 0.976563 */
+#define HPF_Fs24000_Fc66_A1                       -2097152349         /* Floating point value -1.953125 */
+#define HPF_Fs24000_Fc66_A2                        1048576175         /* Floating point value 0.976563 */
+#define HPF_Fs24000_Fc66_B1                       -2121278255         /* Floating point value -1.975594 */
+#define HPF_Fs24000_Fc66_B2                        1047852379         /* Floating point value 0.975889 */
+#define HPF_Fs32000_Fc66_A0                        1051780119         /* Floating point value 0.979547 */
+#define HPF_Fs32000_Fc66_A1                       -2103560237         /* Floating point value -1.959093 */
+#define HPF_Fs32000_Fc66_A2                        1051780119         /* Floating point value 0.979547 */
+#define HPF_Fs32000_Fc66_B1                       -2127829187         /* Floating point value -1.981695 */
+#define HPF_Fs32000_Fc66_B2                        1054265623         /* Floating point value 0.981861 */
+#define HPF_Fs44100_Fc66_A0                        1054424722         /* Floating point value 0.982010 */
+#define HPF_Fs44100_Fc66_A1                       -2108849444         /* Floating point value -1.964019 */
+#define HPF_Fs44100_Fc66_A2                        1054424722         /* Floating point value 0.982010 */
+#define HPF_Fs44100_Fc66_B1                       -2133221723         /* Floating point value -1.986718 */
+#define HPF_Fs44100_Fc66_B2                        1059573993         /* Floating point value 0.986805 */
+#define HPF_Fs48000_Fc66_A0                        1054993851         /* Floating point value 0.982540 */
+#define HPF_Fs48000_Fc66_A1                       -2109987702         /* Floating point value -1.965079 */
+#define HPF_Fs48000_Fc66_A2                        1054993851         /* Floating point value 0.982540 */
+#define HPF_Fs48000_Fc66_B1                       -2134380475         /* Floating point value -1.987797 */
+#define HPF_Fs48000_Fc66_B2                        1060718118         /* Floating point value 0.987871 */
+
+ /* Coefficients for centre frequency 78Hz */
+#define HPF_Fs8000_Fc78_A0                         1016504203         /* Floating point value 0.946693 */
+#define HPF_Fs8000_Fc78_A1                        -2033008405         /* Floating point value -1.893387 */
+#define HPF_Fs8000_Fc78_A2                         1016504203         /* Floating point value 0.946693 */
+#define HPF_Fs8000_Fc78_B1                        -2054623390         /* Floating point value -1.913517 */
+#define HPF_Fs8000_Fc78_B2                          984733853         /* Floating point value 0.917105 */
+#define HPF_Fs11025_Fc78_A0                        1028643741         /* Floating point value 0.957999 */
+#define HPF_Fs11025_Fc78_A1                       -2057287482         /* Floating point value -1.915998 */
+#define HPF_Fs11025_Fc78_A2                        1028643741         /* Floating point value 0.957999 */
+#define HPF_Fs11025_Fc78_B1                       -2080083769         /* Floating point value -1.937229 */
+#define HPF_Fs11025_Fc78_B2                        1008393904         /* Floating point value 0.939140 */
+#define HPF_Fs12000_Fc78_A0                        1031271067         /* Floating point value 0.960446 */
+#define HPF_Fs12000_Fc78_A1                       -2062542133         /* Floating point value -1.920892 */
+#define HPF_Fs12000_Fc78_A2                        1031271067         /* Floating point value 0.960446 */
+#define HPF_Fs12000_Fc78_B1                       -2085557048         /* Floating point value -1.942326 */
+#define HPF_Fs12000_Fc78_B2                        1013551620         /* Floating point value 0.943944 */
+#define HPF_Fs16000_Fc78_A0                        1038734628         /* Floating point value 0.967397 */
+#define HPF_Fs16000_Fc78_A1                       -2077469256         /* Floating point value -1.934794 */
+#define HPF_Fs16000_Fc78_A2                        1038734628         /* Floating point value 0.967397 */
+#define HPF_Fs16000_Fc78_B1                       -2101033380         /* Floating point value -1.956740 */
+#define HPF_Fs16000_Fc78_B2                        1028275228         /* Floating point value 0.957656 */
+#define HPF_Fs22050_Fc78_A0                        1044918584         /* Floating point value 0.973156 */
+#define HPF_Fs22050_Fc78_A1                       -2089837169         /* Floating point value -1.946313 */
+#define HPF_Fs22050_Fc78_A2                        1044918584         /* Floating point value 0.973156 */
+#define HPF_Fs22050_Fc78_B1                       -2113775854         /* Floating point value -1.968607 */
+#define HPF_Fs22050_Fc78_B2                        1040555007         /* Floating point value 0.969092 */
+#define HPF_Fs24000_Fc78_A0                        1046252164         /* Floating point value 0.974398 */
+#define HPF_Fs24000_Fc78_A1                       -2092504328         /* Floating point value -1.948797 */
+#define HPF_Fs24000_Fc78_A2                        1046252164         /* Floating point value 0.974398 */
+#define HPF_Fs24000_Fc78_B1                       -2116514229         /* Floating point value -1.971157 */
+#define HPF_Fs24000_Fc78_B2                        1043212719         /* Floating point value 0.971568 */
+#define HPF_Fs32000_Fc78_A0                        1050031301         /* Floating point value 0.977918 */
+#define HPF_Fs32000_Fc78_A1                       -2100062603         /* Floating point value -1.955836 */
+#define HPF_Fs32000_Fc78_A2                        1050031301         /* Floating point value 0.977918 */
+#define HPF_Fs32000_Fc78_B1                       -2124255900         /* Floating point value -1.978367 */
+#define HPF_Fs32000_Fc78_B2                        1050762639         /* Floating point value 0.978599 */
+#define HPF_Fs44100_Fc78_A0                        1053152258         /* Floating point value 0.980824 */
+#define HPF_Fs44100_Fc78_A1                       -2106304516         /* Floating point value -1.961649 */
+#define HPF_Fs44100_Fc78_A2                        1053152258         /* Floating point value 0.980824 */
+#define HPF_Fs44100_Fc78_B1                       -2130628742         /* Floating point value -1.984303 */
+#define HPF_Fs44100_Fc78_B2                        1057018180         /* Floating point value 0.984425 */
+#define HPF_Fs48000_Fc78_A0                        1053824087         /* Floating point value 0.981450 */
+#define HPF_Fs48000_Fc78_A1                       -2107648173         /* Floating point value -1.962900 */
+#define HPF_Fs48000_Fc78_A2                        1053824087         /* Floating point value 0.981450 */
+#define HPF_Fs48000_Fc78_B1                       -2131998154         /* Floating point value -1.985578 */
+#define HPF_Fs48000_Fc78_B2                        1058367200         /* Floating point value 0.985681 */
+
+ /* Coefficients for centre frequency 90Hz */
+#define HPF_Fs8000_Fc90_A0                         1009760053         /* Floating point value 0.940412 */
+#define HPF_Fs8000_Fc90_A1                        -2019520105         /* Floating point value -1.880825 */
+#define HPF_Fs8000_Fc90_A2                         1009760053         /* Floating point value 0.940412 */
+#define HPF_Fs8000_Fc90_B1                        -2040357139         /* Floating point value -1.900231 */
+#define HPF_Fs8000_Fc90_B2                          971711129         /* Floating point value 0.904977 */
+#define HPF_Fs11025_Fc90_A0                        1023687217         /* Floating point value 0.953383 */
+#define HPF_Fs11025_Fc90_A1                       -2047374434         /* Floating point value -1.906766 */
+#define HPF_Fs11025_Fc90_A2                        1023687217         /* Floating point value 0.953383 */
+#define HPF_Fs11025_Fc90_B1                       -2069722397         /* Floating point value -1.927579 */
+#define HPF_Fs11025_Fc90_B2                         998699604         /* Floating point value 0.930111 */
+#define HPF_Fs12000_Fc90_A0                        1026704754         /* Floating point value 0.956193 */
+#define HPF_Fs12000_Fc90_A1                       -2053409508         /* Floating point value -1.912387 */
+#define HPF_Fs12000_Fc90_A2                        1026704754         /* Floating point value 0.956193 */
+#define HPF_Fs12000_Fc90_B1                       -2076035996         /* Floating point value -1.933459 */
+#define HPF_Fs12000_Fc90_B2                        1004595918         /* Floating point value 0.935603 */
+#define HPF_Fs16000_Fc90_A0                        1035283225         /* Floating point value 0.964183 */
+#define HPF_Fs16000_Fc90_A1                       -2070566451         /* Floating point value -1.928365 */
+#define HPF_Fs16000_Fc90_A2                        1035283225         /* Floating point value 0.964183 */
+#define HPF_Fs16000_Fc90_B1                       -2093889811         /* Floating point value -1.950087 */
+#define HPF_Fs16000_Fc90_B2                        1021453326         /* Floating point value 0.951303 */
+#define HPF_Fs22050_Fc90_A0                        1042398116         /* Floating point value 0.970809 */
+#define HPF_Fs22050_Fc90_A1                       -2084796232         /* Floating point value -1.941618 */
+#define HPF_Fs22050_Fc90_A2                        1042398116         /* Floating point value 0.970809 */
+#define HPF_Fs22050_Fc90_B1                       -2108591057         /* Floating point value -1.963778 */
+#define HPF_Fs22050_Fc90_B2                        1035541188         /* Floating point value 0.964423 */
+#define HPF_Fs24000_Fc90_A0                        1043933302         /* Floating point value 0.972239 */
+#define HPF_Fs24000_Fc90_A1                       -2087866604         /* Floating point value -1.944477 */
+#define HPF_Fs24000_Fc90_A2                        1043933302         /* Floating point value 0.972239 */
+#define HPF_Fs24000_Fc90_B1                       -2111750495         /* Floating point value -1.966721 */
+#define HPF_Fs24000_Fc90_B2                        1038593601         /* Floating point value 0.967266 */
+#define HPF_Fs32000_Fc90_A0                        1048285391         /* Floating point value 0.976292 */
+#define HPF_Fs32000_Fc90_A1                       -2096570783         /* Floating point value -1.952584 */
+#define HPF_Fs32000_Fc90_A2                        1048285391         /* Floating point value 0.976292 */
+#define HPF_Fs32000_Fc90_B1                       -2120682737         /* Floating point value -1.975040 */
+#define HPF_Fs32000_Fc90_B2                        1047271295         /* Floating point value 0.975347 */
+#define HPF_Fs44100_Fc90_A0                        1051881330         /* Floating point value 0.979641 */
+#define HPF_Fs44100_Fc90_A1                       -2103762660         /* Floating point value -1.959282 */
+#define HPF_Fs44100_Fc90_A2                        1051881330         /* Floating point value 0.979641 */
+#define HPF_Fs44100_Fc90_B1                       -2128035809         /* Floating point value -1.981888 */
+#define HPF_Fs44100_Fc90_B2                        1054468533         /* Floating point value 0.982050 */
+#define HPF_Fs48000_Fc90_A0                        1052655619         /* Floating point value 0.980362 */
+#define HPF_Fs48000_Fc90_A1                       -2105311238         /* Floating point value -1.960724 */
+#define HPF_Fs48000_Fc90_A2                        1052655619         /* Floating point value 0.980362 */
+#define HPF_Fs48000_Fc90_B1                       -2129615871         /* Floating point value -1.983359 */
+#define HPF_Fs48000_Fc90_B2                        1056021492         /* Floating point value 0.983497 */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* Band Pass Filter coefficients                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+ /* Coefficients for centre frequency 55Hz */
+#define BPF_Fs8000_Fc55_A0                            9875247         /* Floating point value 0.009197 */
+#define BPF_Fs8000_Fc55_A1                                  0         /* Floating point value 0.000000 */
+#define BPF_Fs8000_Fc55_A2                           -9875247         /* Floating point value -0.009197 */
+#define BPF_Fs8000_Fc55_B1                        -2125519830         /* Floating point value -1.979545 */
+#define BPF_Fs8000_Fc55_B2                         1053762629         /* Floating point value 0.981393 */
+#define BPF_Fs11025_Fc55_A0                           7183952         /* Floating point value 0.006691 */
+#define BPF_Fs11025_Fc55_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs11025_Fc55_A2                          -7183952         /* Floating point value -0.006691 */
+#define BPF_Fs11025_Fc55_B1                       -2131901658         /* Floating point value -1.985488 */
+#define BPF_Fs11025_Fc55_B2                        1059207548         /* Floating point value 0.986464 */
+#define BPF_Fs12000_Fc55_A0                           6603871         /* Floating point value 0.006150 */
+#define BPF_Fs12000_Fc55_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs12000_Fc55_A2                          -6603871         /* Floating point value -0.006150 */
+#define BPF_Fs12000_Fc55_B1                       -2133238092         /* Floating point value -1.986733 */
+#define BPF_Fs12000_Fc55_B2                        1060381143         /* Floating point value 0.987557 */
+#define BPF_Fs16000_Fc55_A0                           4960591         /* Floating point value 0.004620 */
+#define BPF_Fs16000_Fc55_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs16000_Fc55_A2                          -4960591         /* Floating point value -0.004620 */
+#define BPF_Fs16000_Fc55_B1                       -2136949052         /* Floating point value -1.990189 */
+#define BPF_Fs16000_Fc55_B2                        1063705760         /* Floating point value 0.990653 */
+#define BPF_Fs22050_Fc55_A0                           3604131         /* Floating point value 0.003357 */
+#define BPF_Fs22050_Fc55_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs22050_Fc55_A2                          -3604131         /* Floating point value -0.003357 */
+#define BPF_Fs22050_Fc55_B1                       -2139929085         /* Floating point value -1.992964 */
+#define BPF_Fs22050_Fc55_B2                        1066450095         /* Floating point value 0.993209 */
+#define BPF_Fs24000_Fc55_A0                           3312207         /* Floating point value 0.003085 */
+#define BPF_Fs24000_Fc55_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs24000_Fc55_A2                          -3312207         /* Floating point value -0.003085 */
+#define BPF_Fs24000_Fc55_B1                       -2140560606         /* Floating point value -1.993552 */
+#define BPF_Fs24000_Fc55_B2                        1067040703         /* Floating point value 0.993759 */
+#define BPF_Fs32000_Fc55_A0                           2486091         /* Floating point value 0.002315 */
+#define BPF_Fs32000_Fc55_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs32000_Fc55_A2                          -2486091         /* Floating point value -0.002315 */
+#define BPF_Fs32000_Fc55_B1                       -2142328962         /* Floating point value -1.995199 */
+#define BPF_Fs32000_Fc55_B2                        1068712067         /* Floating point value 0.995316 */
+#define BPF_Fs44100_Fc55_A0                           1805125         /* Floating point value 0.001681 */
+#define BPF_Fs44100_Fc55_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs44100_Fc55_A2                          -1805125         /* Floating point value -0.001681 */
+#define BPF_Fs44100_Fc55_B1                       -2143765772         /* Floating point value -1.996537 */
+#define BPF_Fs44100_Fc55_B2                        1070089770         /* Floating point value 0.996599 */
+#define BPF_Fs48000_Fc55_A0                           1658687         /* Floating point value 0.001545 */
+#define BPF_Fs48000_Fc55_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs48000_Fc55_A2                          -1658687         /* Floating point value -0.001545 */
+#define BPF_Fs48000_Fc55_B1                       -2144072292         /* Floating point value -1.996823 */
+#define BPF_Fs48000_Fc55_B2                        1070386036         /* Floating point value 0.996875 */
+
+ /* Coefficients for centre frequency 66Hz */
+#define BPF_Fs8000_Fc66_A0                           13580189         /* Floating point value 0.012648 */
+#define BPF_Fs8000_Fc66_A1                                  0         /* Floating point value 0.000000 */
+#define BPF_Fs8000_Fc66_A2                          -13580189         /* Floating point value -0.012648 */
+#define BPF_Fs8000_Fc66_B1                        -2117161175         /* Floating point value -1.971760 */
+#define BPF_Fs8000_Fc66_B2                         1046266945         /* Floating point value 0.974412 */
+#define BPF_Fs11025_Fc66_A0                           9888559         /* Floating point value 0.009209 */
+#define BPF_Fs11025_Fc66_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs11025_Fc66_A2                          -9888559         /* Floating point value -0.009209 */
+#define BPF_Fs11025_Fc66_B1                       -2125972738         /* Floating point value -1.979966 */
+#define BPF_Fs11025_Fc66_B2                        1053735698         /* Floating point value 0.981368 */
+#define BPF_Fs12000_Fc66_A0                           9091954         /* Floating point value 0.008468 */
+#define BPF_Fs12000_Fc66_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs12000_Fc66_A2                          -9091954         /* Floating point value -0.008468 */
+#define BPF_Fs12000_Fc66_B1                       -2127818004         /* Floating point value -1.981685 */
+#define BPF_Fs12000_Fc66_B2                        1055347356         /* Floating point value 0.982869 */
+#define BPF_Fs16000_Fc66_A0                           6833525         /* Floating point value 0.006364 */
+#define BPF_Fs16000_Fc66_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs16000_Fc66_A2                          -6833525         /* Floating point value -0.006364 */
+#define BPF_Fs16000_Fc66_B1                       -2132941739         /* Floating point value -1.986457 */
+#define BPF_Fs16000_Fc66_B2                        1059916517         /* Floating point value 0.987124 */
+#define BPF_Fs22050_Fc66_A0                           4967309         /* Floating point value 0.004626 */
+#define BPF_Fs22050_Fc66_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs22050_Fc66_A2                          -4967309         /* Floating point value -0.004626 */
+#define BPF_Fs22050_Fc66_B1                       -2137056003         /* Floating point value -1.990288 */
+#define BPF_Fs22050_Fc66_B2                        1063692170         /* Floating point value 0.990641 */
+#define BPF_Fs24000_Fc66_A0                           4565445         /* Floating point value 0.004252 */
+#define BPF_Fs24000_Fc66_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs24000_Fc66_A2                          -4565445         /* Floating point value -0.004252 */
+#define BPF_Fs24000_Fc66_B1                       -2137927842         /* Floating point value -1.991100 */
+#define BPF_Fs24000_Fc66_B2                        1064505202         /* Floating point value 0.991398 */
+#define BPF_Fs32000_Fc66_A0                           3427761         /* Floating point value 0.003192 */
+#define BPF_Fs32000_Fc66_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs32000_Fc66_A2                          -3427761         /* Floating point value -0.003192 */
+#define BPF_Fs32000_Fc66_B1                       -2140369007         /* Floating point value -1.993374 */
+#define BPF_Fs32000_Fc66_B2                        1066806920         /* Floating point value 0.993541 */
+#define BPF_Fs44100_Fc66_A0                           2489466         /* Floating point value 0.002318 */
+#define BPF_Fs44100_Fc66_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs44100_Fc66_A2                          -2489466         /* Floating point value -0.002318 */
+#define BPF_Fs44100_Fc66_B1                       -2142352342         /* Floating point value -1.995221 */
+#define BPF_Fs44100_Fc66_B2                        1068705240         /* Floating point value 0.995309 */
+#define BPF_Fs48000_Fc66_A0                           2287632         /* Floating point value 0.002131 */
+#define BPF_Fs48000_Fc66_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs48000_Fc66_A2                          -2287632         /* Floating point value -0.002131 */
+#define BPF_Fs48000_Fc66_B1                       -2142775436         /* Floating point value -1.995615 */
+#define BPF_Fs48000_Fc66_B2                        1069113581         /* Floating point value 0.995690 */
+
+ /* Coefficients for centre frequency 78Hz */
+#define BPF_Fs8000_Fc78_A0                           19941180         /* Floating point value 0.018572 */
+#define BPF_Fs8000_Fc78_A1                                  0         /* Floating point value 0.000000 */
+#define BPF_Fs8000_Fc78_A2                          -19941180         /* Floating point value -0.018572 */
+#define BPF_Fs8000_Fc78_B1                        -2103186749         /* Floating point value -1.958745 */
+#define BPF_Fs8000_Fc78_B2                         1033397648         /* Floating point value 0.962427 */
+#define BPF_Fs11025_Fc78_A0                          14543934         /* Floating point value 0.013545 */
+#define BPF_Fs11025_Fc78_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs11025_Fc78_A2                         -14543934         /* Floating point value -0.013545 */
+#define BPF_Fs11025_Fc78_B1                       -2115966638         /* Floating point value -1.970647 */
+#define BPF_Fs11025_Fc78_B2                        1044317135         /* Floating point value 0.972596 */
+#define BPF_Fs12000_Fc78_A0                          13376999         /* Floating point value 0.012458 */
+#define BPF_Fs12000_Fc78_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs12000_Fc78_A2                         -13376999         /* Floating point value -0.012458 */
+#define BPF_Fs12000_Fc78_B1                       -2118651708         /* Floating point value -1.973148 */
+#define BPF_Fs12000_Fc78_B2                        1046678029         /* Floating point value 0.974795 */
+#define BPF_Fs16000_Fc78_A0                          10064222         /* Floating point value 0.009373 */
+#define BPF_Fs16000_Fc78_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs16000_Fc78_A2                         -10064222         /* Floating point value -0.009373 */
+#define BPF_Fs16000_Fc78_B1                       -2126124342         /* Floating point value -1.980108 */
+#define BPF_Fs16000_Fc78_B2                        1053380304         /* Floating point value 0.981037 */
+#define BPF_Fs22050_Fc78_A0                           7321780         /* Floating point value 0.006819 */
+#define BPF_Fs22050_Fc78_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs22050_Fc78_A2                          -7321780         /* Floating point value -0.006819 */
+#define BPF_Fs22050_Fc78_B1                       -2132143771         /* Floating point value -1.985714 */
+#define BPF_Fs22050_Fc78_B2                        1058928700         /* Floating point value 0.986204 */
+#define BPF_Fs24000_Fc78_A0                           6730640         /* Floating point value 0.006268 */
+#define BPF_Fs24000_Fc78_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs24000_Fc78_A2                          -6730640         /* Floating point value -0.006268 */
+#define BPF_Fs24000_Fc78_B1                       -2133421607         /* Floating point value -1.986904 */
+#define BPF_Fs24000_Fc78_B2                        1060124669         /* Floating point value 0.987318 */
+#define BPF_Fs32000_Fc78_A0                           5055965         /* Floating point value 0.004709 */
+#define BPF_Fs32000_Fc78_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs32000_Fc78_A2                          -5055965         /* Floating point value -0.004709 */
+#define BPF_Fs32000_Fc78_B1                       -2137003977         /* Floating point value -1.990240 */
+#define BPF_Fs32000_Fc78_B2                        1063512802         /* Floating point value 0.990473 */
+#define BPF_Fs44100_Fc78_A0                           3673516         /* Floating point value 0.003421 */
+#define BPF_Fs44100_Fc78_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs44100_Fc78_A2                          -3673516         /* Floating point value -0.003421 */
+#define BPF_Fs44100_Fc78_B1                       -2139919394         /* Floating point value -1.992955 */
+#define BPF_Fs44100_Fc78_B2                        1066309718         /* Floating point value 0.993078 */
+#define BPF_Fs48000_Fc78_A0                           3375990         /* Floating point value 0.003144 */
+#define BPF_Fs48000_Fc78_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs48000_Fc78_A2                          -3375990         /* Floating point value -0.003144 */
+#define BPF_Fs48000_Fc78_B1                       -2140541906         /* Floating point value -1.993535 */
+#define BPF_Fs48000_Fc78_B2                        1066911660         /* Floating point value 0.993639 */
+
+ /* Coefficients for centre frequency 90Hz */
+#define BPF_Fs8000_Fc90_A0                           24438548         /* Floating point value 0.022760 */
+#define BPF_Fs8000_Fc90_A1                                  0         /* Floating point value 0.000000 */
+#define BPF_Fs8000_Fc90_A2                          -24438548         /* Floating point value -0.022760 */
+#define BPF_Fs8000_Fc90_B1                        -2092801347         /* Floating point value -1.949073 */
+#define BPF_Fs8000_Fc90_B2                         1024298757         /* Floating point value 0.953953 */
+#define BPF_Fs11025_Fc90_A0                          17844385         /* Floating point value 0.016619 */
+#define BPF_Fs11025_Fc90_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs11025_Fc90_A2                         -17844385         /* Floating point value -0.016619 */
+#define BPF_Fs11025_Fc90_B1                       -2108604921         /* Floating point value -1.963791 */
+#define BPF_Fs11025_Fc90_B2                        1037639797         /* Floating point value 0.966377 */
+#define BPF_Fs12000_Fc90_A0                          16416707         /* Floating point value 0.015289 */
+#define BPF_Fs12000_Fc90_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs12000_Fc90_A2                         -16416707         /* Floating point value -0.015289 */
+#define BPF_Fs12000_Fc90_B1                       -2111922936         /* Floating point value -1.966882 */
+#define BPF_Fs12000_Fc90_B2                        1040528216         /* Floating point value 0.969067 */
+#define BPF_Fs16000_Fc90_A0                          12359883         /* Floating point value 0.011511 */
+#define BPF_Fs16000_Fc90_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs16000_Fc90_A2                         -12359883         /* Floating point value -0.011511 */
+#define BPF_Fs16000_Fc90_B1                       -2121152162         /* Floating point value -1.975477 */
+#define BPF_Fs16000_Fc90_B2                        1048735817         /* Floating point value 0.976711 */
+#define BPF_Fs22050_Fc90_A0                           8997173         /* Floating point value 0.008379 */
+#define BPF_Fs22050_Fc90_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs22050_Fc90_A2                          -8997173         /* Floating point value -0.008379 */
+#define BPF_Fs22050_Fc90_B1                       -2128580762         /* Floating point value -1.982395 */
+#define BPF_Fs22050_Fc90_B2                        1055539113         /* Floating point value 0.983047 */
+#define BPF_Fs24000_Fc90_A0                           8271818         /* Floating point value 0.007704 */
+#define BPF_Fs24000_Fc90_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs24000_Fc90_A2                          -8271818         /* Floating point value -0.007704 */
+#define BPF_Fs24000_Fc90_B1                       -2130157013         /* Floating point value -1.983863 */
+#define BPF_Fs24000_Fc90_B2                        1057006621         /* Floating point value 0.984414 */
+#define BPF_Fs32000_Fc90_A0                           6215918         /* Floating point value 0.005789 */
+#define BPF_Fs32000_Fc90_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs32000_Fc90_A2                          -6215918         /* Floating point value -0.005789 */
+#define BPF_Fs32000_Fc90_B1                       -2134574521         /* Floating point value -1.987977 */
+#define BPF_Fs32000_Fc90_B2                        1061166033         /* Floating point value 0.988288 */
+#define BPF_Fs44100_Fc90_A0                           4517651         /* Floating point value 0.004207 */
+#define BPF_Fs44100_Fc90_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs44100_Fc90_A2                          -4517651         /* Floating point value -0.004207 */
+#define BPF_Fs44100_Fc90_B1                       -2138167926         /* Floating point value -1.991324 */
+#define BPF_Fs44100_Fc90_B2                        1064601898         /* Floating point value 0.991488 */
+#define BPF_Fs48000_Fc90_A0                           4152024         /* Floating point value 0.003867 */
+#define BPF_Fs48000_Fc90_A1                                 0         /* Floating point value 0.000000 */
+#define BPF_Fs48000_Fc90_A2                          -4152024         /* Floating point value -0.003867 */
+#define BPF_Fs48000_Fc90_B1                       -2138935002         /* Floating point value -1.992038 */
+#define BPF_Fs48000_Fc90_B2                        1065341620         /* Floating point value 0.992177 */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* Automatic Gain Control time constants and gain settings                          */
+/*                                                                                  */
+/************************************************************************************/
+
+/* AGC Time constants */
+#define AGC_ATTACK_Fs8000                               27571         /* Floating point value 0.841395 */
+#define AGC_ATTACK_Fs11025                              28909         /* Floating point value 0.882223 */
+#define AGC_ATTACK_Fs12000                              29205         /* Floating point value 0.891251 */
+#define AGC_ATTACK_Fs16000                              30057         /* Floating point value 0.917276 */
+#define AGC_ATTACK_Fs22050                              30778         /* Floating point value 0.939267 */
+#define AGC_ATTACK_Fs24000                              30935         /* Floating point value 0.944061 */
+#define AGC_ATTACK_Fs32000                              31383         /* Floating point value 0.957745 */
+#define AGC_ATTACK_Fs44100                              31757         /* Floating point value 0.969158 */
+#define AGC_ATTACK_Fs48000                              31838         /* Floating point value 0.971628 */
+#define DECAY_SHIFT                                        10         /* As a power of 2 */
+#define AGC_DECAY_Fs8000                                   44         /* Floating point value 0.000042 */
+#define AGC_DECAY_Fs11025                                  32         /* Floating point value 0.000030 */
+#define AGC_DECAY_Fs12000                                  29         /* Floating point value 0.000028 */
+#define AGC_DECAY_Fs16000                                  22         /* Floating point value 0.000021 */
+#define AGC_DECAY_Fs22050                                  16         /* Floating point value 0.000015 */
+#define AGC_DECAY_Fs24000                                  15         /* Floating point value 0.000014 */
+#define AGC_DECAY_Fs32000                                  11         /* Floating point value 0.000010 */
+#define AGC_DECAY_Fs44100                                   8         /* Floating point value 0.000008 */
+#define AGC_DECAY_Fs48000                                   7         /* Floating point value 0.000007 */
+
+/* AGC Gain settings */
+#define AGC_GAIN_SCALE                                        31         /* As a power of 2 */
+#define AGC_GAIN_SHIFT                                         4         /* As a power of 2 */
+#define AGC_TARGETLEVEL                              33170337         /* Floating point value -0.100000dB */
+#define AGC_HPFGAIN_0dB                             110739704         /* Floating point value 0.412538 */
+#define AGC_GAIN_0dB                                        0         /* Floating point value 0.000000 */
+#define AGC_HPFGAIN_1dB                             157006071         /* Floating point value 0.584893 */
+#define AGC_GAIN_1dB                                 32754079         /* Floating point value 0.122018 */
+#define AGC_HPFGAIN_2dB                             208917788         /* Floating point value 0.778279 */
+#define AGC_GAIN_2dB                                 69504761         /* Floating point value 0.258925 */
+#define AGC_HPFGAIN_3dB                             267163693         /* Floating point value 0.995262 */
+#define AGC_GAIN_3dB                                110739704         /* Floating point value 0.412538 */
+#define AGC_HPFGAIN_4dB                             332516674         /* Floating point value 1.238721 */
+#define AGC_GAIN_4dB                                157006071         /* Floating point value 0.584893 */
+#define AGC_HPFGAIN_5dB                             405843924         /* Floating point value 1.511886 */
+#define AGC_GAIN_5dB                                208917788         /* Floating point value 0.778279 */
+#define AGC_HPFGAIN_6dB                             488118451         /* Floating point value 1.818383 */
+#define AGC_GAIN_6dB                                267163693         /* Floating point value 0.995262 */
+#define AGC_HPFGAIN_7dB                             580431990         /* Floating point value 2.162278 */
+#define AGC_GAIN_7dB                                332516674         /* Floating point value 1.238721 */
+#define AGC_HPFGAIN_8dB                             684009483         /* Floating point value 2.548134 */
+#define AGC_GAIN_8dB                                405843924         /* Floating point value 1.511886 */
+#define AGC_HPFGAIN_9dB                             800225343         /* Floating point value 2.981072 */
+#define AGC_GAIN_9dB                                488118451         /* Floating point value 1.818383 */
+#define AGC_HPFGAIN_10dB                            930621681         /* Floating point value 3.466836 */
+#define AGC_GAIN_10dB                               580431990         /* Floating point value 2.162278 */
+#define AGC_HPFGAIN_11dB                           1076928780         /* Floating point value 4.011872 */
+#define AGC_GAIN_11dB                               684009483         /* Floating point value 2.548134 */
+#define AGC_HPFGAIN_12dB                           1241088045         /* Floating point value 4.623413 */
+#define AGC_GAIN_12dB                               800225343         /* Floating point value 2.981072 */
+#define AGC_HPFGAIN_13dB                           1425277769         /* Floating point value 5.309573 */
+#define AGC_GAIN_13dB                               930621681         /* Floating point value 3.466836 */
+#define AGC_HPFGAIN_14dB                           1631942039         /* Floating point value 6.079458 */
+#define AGC_GAIN_14dB                              1076928780         /* Floating point value 4.011872 */
+#define AGC_HPFGAIN_15dB                           1863823163         /* Floating point value 6.943282 */
+#define AGC_GAIN_15dB                              1241088045         /* Floating point value 4.623413 */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* Volume control                                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Volume control gain */
+#define VOLUME_MAX                                          0         /* In dBs */
+#define VOLUME_SHIFT                                        0         /* In dBs */
+
+/* Volume control time constants */
+#define VOL_TC_SHIFT                                       21         /* As a power of 2 */
+#define VOL_TC_Fs8000                                   25889         /* Floating point value 0.024690 */
+#define VOL_TC_Fs11025                                  18850         /* Floating point value 0.017977 */
+#define VOL_TC_Fs12000                                  17331         /* Floating point value 0.016529 */
+#define VOL_TC_Fs16000                                  13026         /* Floating point value 0.012422 */
+#define VOL_TC_Fs22050                                   9468         /* Floating point value 0.009029 */
+#define VOL_TC_Fs24000                                   8702         /* Floating point value 0.008299 */
+#define VOL_TC_Fs32000                                   6533         /* Floating point value 0.006231 */
+#define VOL_TC_Fs44100                                   4745         /* Floating point value 0.004525 */
+#define VOL_TC_Fs48000                                   4360         /* Floating point value 0.004158 */
+#define MIX_TC_Fs8000                                   29365         /* Floating point value 0.896151 */
+#define MIX_TC_Fs11025                                  30230         /* Floating point value 0.922548 */
+#define MIX_TC_Fs12000                                  30422         /* Floating point value 0.928415 */
+#define MIX_TC_Fs16000                                  30978         /* Floating point value 0.945387 */
+#define MIX_TC_Fs22050                                  31451         /* Floating point value 0.959804 */
+#define MIX_TC_Fs24000                                  31554         /* Floating point value 0.962956 */
+#define MIX_TC_Fs32000                                  31850         /* Floating point value 0.971973 */
+#define MIX_TC_Fs44100                                  32097         /* Floating point value 0.979515 */
+#define MIX_TC_Fs48000                                  32150         /* Floating point value 0.981150 */
+
+
+#endif
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
new file mode 100755
index 0000000..8cf84b7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1315 $
+     $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+#include "VectorArithmetic.h"
+#include "LVDBE_Coeffs.h"
+#include "LVDBE_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  LVDBE_GetParameters                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Request the Dynamic Bass Enhancement parameters. The current parameter set is     */
+/*  returned via the parameter pointer.                                                 */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                   Instance handle                                         */
+/*  pParams                  Pointer to an empty parameter structure                    */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS            Always succeeds                                            */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.    This function may be interrupted by the LVDBE_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t        hInstance,
+                                            LVDBE_Params_t        *pParams)
+{
+
+    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
+
+    *pParams = pInstance->Params;
+
+    return(LVDBE_SUCCESS);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                  LVDBE_GetCapabilities                                 */
+/*                                                                                  */
+/* DESCRIPTION: Dynamic Bass Enhnacement capabilities. The current capabilities are */
+/* returned via the pointer.                                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance                   Instance handle                                     */
+/*  pCapabilities              Pointer to an empty capability structure             */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVDBE_Success             Always succeeds                                       */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.    This function may be interrupted by the LVDBE_Process function            */
+/*                                                                                  */
+/************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t            hInstance,
+                                              LVDBE_Capabilities_t    *pCapabilities)
+{
+
+    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
+
+    *pCapabilities = pInstance->Capabilities;
+
+    return(LVDBE_SUCCESS);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVDBE_SetFilters                                            */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the filter coefficients and clears the data history                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVDBE_SetFilters(LVDBE_Instance_t     *pInstance,
+                         LVDBE_Params_t       *pParams)
+{
+
+    /*
+     * Calculate the table offsets
+     */
+    LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));
+
+
+    /*
+     * Setup the high pass filter
+     */
+    LoadConst_16(0,                                                 /* Clear the history, value 0 */
+                 (void *)&pInstance->pData->HPFTaps,                /* Destination Cast to void: \
+                                                                     no dereferencing in function*/
+                 sizeof(pInstance->pData->HPFTaps)/sizeof(LVM_INT16));   /* Number of words */
+    BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,      /* Initialise the filter */
+                                    &pInstance->pData->HPFTaps,
+                                    (BQ_C32_Coefs_t *)&LVDBE_HPF_Table[Offset]);
+
+
+    /*
+     * Setup the band pass filter
+     */
+    LoadConst_16(0,                                                 /* Clear the history, value 0 */
+                 (void *)&pInstance->pData->BPFTaps,                /* Destination Cast to void:\
+                                                                     no dereferencing in function*/
+                 sizeof(pInstance->pData->BPFTaps)/sizeof(LVM_INT16));   /* Number of words */
+    BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,      /* Initialise the filter */
+                                    &pInstance->pData->BPFTaps,
+                                    (BP_C32_Coefs_t *)&LVDBE_BPF_Table[Offset]);
+
+}
+
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVDBE_SetAGC                                                */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the AGC gain level and attack and decay times constants.                   */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVDBE_SetAGC(LVDBE_Instance_t     *pInstance,
+                     LVDBE_Params_t       *pParams)
+{
+
+    /*
+     * Get the attack and decay time constants
+     */
+    pInstance->pData->AGCInstance.AGC_Attack = LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate];  /* Attack multiplier */
+    pInstance->pData->AGCInstance.AGC_Decay  = LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate];   /* Decay multipler */
+
+
+    /*
+     * Get the boost gain
+     */
+    if (pParams->HPFSelect == LVDBE_HPF_ON)
+    {
+        pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel];  /* High pass filter on */
+    }
+    else
+    {
+        pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel];     /* High pass filter off */
+    }
+    pInstance->pData->AGCInstance.AGC_GainShift = AGC_GAIN_SHIFT;
+    pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
+
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVDBE_SetVolume                                             */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Converts the input volume demand from dBs to linear.                            */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1. The volume should have the following settings:                               */
+/*                                                                                  */
+/*          DBE         Vol Control           Volume setting                        */
+/*          ===         ===========         ===================                     */
+/*          Off             Off                 HeadroomdB                          */
+/*          Off             On              VolumedB+HeadroomdB                     */
+/*          On              Off                 HeadroomdB                          */
+/*          On              On              VolumedB+HeadroomdB                     */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVDBE_SetVolume(LVDBE_Instance_t     *pInstance,
+                        LVDBE_Params_t       *pParams)
+{
+
+    LVM_UINT16      dBShifts;                                   /* 6dB shifts */
+    LVM_UINT16      dBOffset;                                   /* Table offset */
+    LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
+
+    /*
+     * Apply the volume if enabled
+     */
+    if (pParams->VolumeControl == LVDBE_VOLUME_ON)
+    {
+        /*
+         * Limit the gain to the maximum allowed
+         */
+        if  (pParams->VolumedB > VOLUME_MAX)
+        {
+            Volume = VOLUME_MAX;
+        }
+        else
+        {
+            Volume = pParams->VolumedB;
+        }
+    }
+
+
+    /*
+     * Calculate the required gain and shifts
+     */
+    dBOffset = (LVM_UINT16)(6 + Volume % 6);                    /* Get the dBs 0-5 */
+    dBShifts = (LVM_UINT16)(Volume / -6);                       /* Get the 6dB shifts */
+
+
+    /*
+     * When DBE is enabled use AGC volume
+     */
+    pInstance->pData->AGCInstance.Target = ((LVM_INT32)LVDBE_VolumeTable[dBOffset] << 16);
+    pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target >> dBShifts;
+
+    pInstance->pData->AGCInstance.VolumeTC    = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate];   /* Volume update time constant */
+    pInstance->pData->AGCInstance.VolumeShift = VOLUME_SHIFT+1;
+
+    /*
+     * When DBE is disabled use the bypass volume control
+     */
+    if(dBShifts > 0)
+    {
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(((LVM_INT32)LVDBE_VolumeTable[dBOffset]) >> dBShifts));
+    }
+    else
+    {
+        LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(LVM_INT32)LVDBE_VolumeTable[dBOffset]);
+    }
+
+    pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
+    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
+                                LVDBE_MIXER_TC,
+                                (LVM_Fs_en)pInstance->Params.SampleRate,
+                                2);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVDBE_Control                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the Bass Enhancement parameters. Changing the parameters while the  */
+/*  module is processing signals may have the following side effects:                   */
+/*                                                                                      */
+/*  General parameters:                                                                 */
+/*  ===================                                                                 */
+/*  OperatingMode:      Changing the mode of operation may cause a change in volume     */
+/*                      level or cause pops and clicks.                                 */
+/*                                                                                      */
+/*  SampleRate:         Changing the sample rate may cause pops and clicks.             */
+/*                                                                                      */
+/*  EffectLevel:        Changing the effect level may cause pops and clicks             */
+/*                                                                                      */
+/*  CentreFrequency:    Changing the centre frequency may cause pops and clicks         */
+/*                                                                                      */
+/*  HPFSelect:          Selecting/de-selecting the high pass filter may cause pops and  */
+/*                      clicks                                                          */
+/*                                                                                      */
+/*  VolumedB            Changing the volume setting will have no side effects           */
+/*                                                                                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pParams                 Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS           Always succeeds                                             */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function must not be interrupted by the LVDBE_Process function             */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t         hInstance,
+                                      LVDBE_Params_t         *pParams)
+{
+
+    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
+
+
+    /*
+     * Update the filters
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.CentreFrequency != pParams->CentreFrequency))
+    {
+        LVDBE_SetFilters(pInstance,                     /* Instance pointer */
+                         pParams);                      /* New parameters */
+    }
+
+
+    /*
+     * Update the AGC is the effect level has changed
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.EffectLevel != pParams->EffectLevel) ||
+        (pInstance->Params.HPFSelect != pParams->HPFSelect))
+    {
+        LVDBE_SetAGC(pInstance,                         /* Instance pointer */
+                     pParams);                          /* New parameters */
+    }
+
+
+    /*
+     * Update the Volume if the volume demand has changed
+     */
+    if ((pInstance->Params.VolumedB != pParams->VolumedB) ||
+        (pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.HeadroomdB != pParams->HeadroomdB) ||
+        (pInstance->Params.VolumeControl != pParams->VolumeControl))
+    {
+        LVDBE_SetVolume(pInstance,                      /* Instance pointer */
+                       pParams);                        /* New parameters */
+    }
+
+    if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
+    {
+        LVDBE_Params_t  Params  = *pParams;             /* make local copy of params */
+        Params.EffectLevel      = 0;                    /* zero effect level before switching off module*/
+        pInstance->bTransitionOnToOff  = LVM_TRUE;             /* Set the CallBack */
+        LVDBE_SetAGC(pInstance,                         /* Instance pointer */
+                     &Params);                          /* New parameters */
+    }
+    if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
+    {
+        pInstance->bTransitionOnToOff  = LVM_FALSE;     /* Set the CallBack */
+        LVDBE_SetAGC(pInstance,                         /* Instance pointer */
+                     pParams);                          /* New parameters */
+    }
+
+    /*
+     * Update the instance parameters
+     */
+    pInstance->Params = *pParams;
+
+
+    return(LVDBE_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
new file mode 100755
index 0000000..75869c7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1081 $
+     $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVDBE_Memory                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    This function is used for memory allocation and free. It can be called in         */
+/*    two ways:                                                                         */
+/*                                                                                      */
+/*        hInstance = NULL                Returns the memory requirements               */
+/*        hInstance = Instance handle        Returns the memory requirements and        */
+/*                                        allocated base addresses for the instance     */
+/*                                                                                      */
+/*    When this function is called for memory allocation (hInstance=NULL) the memory    */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*    When the function is called for free (hInstance = Instance Handle) the memory     */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance Handle                                            */
+/*  pMemoryTable             Pointer to an empty memory definition table                */
+/*    pCapabilities           Pointer to the instance capabilities                      */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS            Succeeded                                                  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*    1.    This function may be interrupted by the LVDBE_Process function              */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t            hInstance,
+                                   LVDBE_MemTab_t            *pMemoryTable,
+                                   LVDBE_Capabilities_t      *pCapabilities)
+{
+
+    LVM_UINT32          ScratchSize;
+    LVDBE_Instance_t    *pInstance = (LVDBE_Instance_t *)hInstance;
+
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+        /*
+         * Instance memory
+         */
+        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Size         = sizeof(LVDBE_Instance_t);
+        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Alignment    = LVDBE_INSTANCE_ALIGN;
+        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Type         = LVDBE_PERSISTENT;
+        pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+        /*
+         * Data memory
+         */
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size         = sizeof(LVDBE_Data_t);
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Alignment    = LVDBE_PERSISTENT_DATA_ALIGN;
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Type         = LVDBE_PERSISTENT_DATA;
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Coef memory
+         */
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size         = sizeof(LVDBE_Coef_t);
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment    = LVDBE_PERSISTENT_COEF_ALIGN;
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type         = LVDBE_PERSISTENT_COEF;
+        pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Scratch memory
+         */
+        ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
+        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Size         = ScratchSize;
+        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Alignment    = LVDBE_SCRATCH_ALIGN;
+        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Type         = LVDBE_SCRATCH;
+        pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
+    }
+    else
+    {
+        /* Read back memory allocation table */
+        *pMemoryTable = pInstance->MemoryTable;
+    }
+
+    return(LVDBE_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVDBE_Init                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Create and initialisation function for the Dynamic Bass Enhancement module        */
+/*                                                                                      */
+/*    This function can be used to create an algorithm instance by calling with         */
+/*    hInstance set to NULL. In this case the algorithm returns the new instance        */
+/*    handle.                                                                           */
+/*                                                                                      */
+/*    This function can be used to force a full re-initialisation of the algorithm      */
+/*    by calling with hInstance = Instance Handle. In this case the memory table        */
+/*    should be correct for the instance, this can be ensured by calling the function   */
+/*    DBE_Memory before calling this function.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                  Instance handle                                          */
+/*  pMemoryTable             Pointer to the memory definition table                     */
+/*  pCapabilities              Pointer to the instance capabilities                     */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVDBE_SUCCESS            Initialisation succeeded                                   */
+/*  LVDBE_ALIGNMENTERROR    Instance or scratch memory on incorrect alignment           */
+/*    LVDBE_NULLADDRESS        Instance or scratch memory has a NULL pointer            */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.     The instance handle is the pointer to the base address of the first memory   */
+/*        region.                                                                       */
+/*    2.    This function must not be interrupted by the LVDBE_Process function         */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t         *phInstance,
+                                   LVDBE_MemTab_t       *pMemoryTable,
+                                   LVDBE_Capabilities_t *pCapabilities)
+{
+
+    LVDBE_Instance_t      *pInstance;
+    LVMixer3_1St_st       *pMixer_Instance;
+    LVM_INT16             i;
+    LVM_INT32             MixGain;
+
+
+    /*
+     * Set the instance handle if not already initialised
+     */
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = (LVDBE_Handle_t)pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress;
+    }
+    pInstance =(LVDBE_Instance_t  *)*phInstance;
+
+
+    /*
+     * Check the memory table for NULL pointers and incorrectly aligned data
+     */
+    for (i=0; i<LVDBE_NR_MEMORY_REGIONS; i++)
+    {
+        if (pMemoryTable->Region[i].Size!=0)
+        {
+            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+            {
+                return(LVDBE_NULLADDRESS);
+            }
+            if (((LVM_UINT32)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
+                return(LVDBE_ALIGNMENTERROR);
+            }
+        }
+    }
+
+
+    /*
+     * Save the memory table in the instance structure
+     */
+    pInstance->Capabilities = *pCapabilities;
+
+
+    /*
+     * Save the memory table in the instance structure
+     */
+    pInstance->MemoryTable = *pMemoryTable;
+
+
+    /*
+     * Set the default instance parameters
+     */
+    pInstance->Params.CentreFrequency   =    LVDBE_CENTRE_55HZ;
+    pInstance->Params.EffectLevel       =    0;
+    pInstance->Params.HeadroomdB        =    0;
+    pInstance->Params.HPFSelect         =    LVDBE_HPF_OFF;
+    pInstance->Params.OperatingMode     =    LVDBE_OFF;
+    pInstance->Params.SampleRate        =    LVDBE_FS_8000;
+    pInstance->Params.VolumeControl     =    LVDBE_VOLUME_OFF;
+    pInstance->Params.VolumedB          =    0;
+
+
+    /*
+     * Set pointer to data and coef memory
+     */
+    pInstance->pData = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress;
+    pInstance->pCoef = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress;
+
+
+    /*
+     * Initialise the filters
+     */
+    LVDBE_SetFilters(pInstance,                                 /* Set the filter taps and coefficients */
+                     &pInstance->Params);
+
+
+    /*
+     * Initialise the AGC
+     */
+    LVDBE_SetAGC(pInstance,                                     /* Set the AGC gain */
+                 &pInstance->Params);
+    pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain;   /* Default to the bass boost setting */
+
+
+    /*
+     * Initialise the volume
+     */
+    LVDBE_SetVolume(pInstance,                                         /* Set the Volume */
+                    &pInstance->Params);
+
+    pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target;  /* Initialise as the target */
+
+    pMixer_Instance = &pInstance->pData->BypassVolume;
+    MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
+    LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],MixGain,MixGain);
+
+    /* Configure the mixer process path */
+    pMixer_Instance->MixerStream[0].CallbackParam = 0;
+    pMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
+    pMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
+    pMixer_Instance->MixerStream[0].CallbackSet = 0;
+
+    /*
+     * Initialise the clicks minimisation variable
+     */
+    pInstance->bTransitionOnToOff   =   LVM_FALSE;
+
+    return(LVDBE_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
new file mode 100755
index 0000000..3e09cf4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1081 $
+     $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Header file for the private layer interface of Dynamic Bass Enhancement module    */
+/*                                                                                      */
+/*  This files includes all definitions, types, structures and function                 */
+/*  prototypes required by the execution layer.                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+#ifndef __LVDBE_PRIVATE_H__
+#define __LVDBE_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVDBE.h"                                /* Calling or Application layer definitions */
+#include "BIQUAD.h"
+#include "LVC_Mixer.h"
+#include "AGC.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Defines                                                                           */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* General */
+#define    LVDBE_INVALID            0xFFFF        /* Invalid init parameter */
+
+/* Memory */
+#define LVDBE_MEMREGION_INSTANCE         0       /* Offset to the instance memory region */
+#define LVDBE_MEMREGION_PERSISTENT_DATA  1       /* Offset to persistent data memory region */
+#define LVDBE_MEMREGION_PERSISTENT_COEF  2       /* Offset to persistent coefficient region */
+#define LVDBE_MEMREGION_SCRATCH          3       /* Offset to data scratch memory region */
+
+#define LVDBE_INSTANCE_ALIGN             4       /* 32-bit alignment for structures */
+#define LVDBE_PERSISTENT_DATA_ALIGN      4       /* 32-bit alignment for data */
+#define LVDBE_PERSISTENT_COEF_ALIGN      4       /* 32-bit alignment for coef */
+#define LVDBE_SCRATCH_ALIGN              4       /* 32-bit alignment for long data */
+
+#define LVDBE_SCRATCHBUFFERS_INPLACE     4       /* Number of buffers required for inplace processing */
+
+#define LVDBE_MIXER_TC                   5       /* Mixer time  */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Structures                                                                        */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Data structure */
+typedef struct
+{
+    /* AGC parameters */
+    AGC_MIX_VOL_2St1Mon_D32_t   AGCInstance;        /* AGC instance parameters */
+
+    /* Process variables */
+    Biquad_2I_Order2_Taps_t     HPFTaps;            /* High pass filter taps */
+    Biquad_1I_Order2_Taps_t     BPFTaps;            /* Band pass filter taps */
+    LVMixer3_1St_st             BypassVolume;       /* Bypass volume scaler */
+
+} LVDBE_Data_t;
+
+/* Coefs structure */
+typedef struct
+{
+    /* Process variables */
+    Biquad_Instance_t           HPFInstance;        /* High pass filter instance */
+    Biquad_Instance_t           BPFInstance;        /* Band pass filter instance */
+
+} LVDBE_Coef_t;
+
+/* Instance structure */
+typedef struct
+{
+    /* Public parameters */
+    LVDBE_MemTab_t                MemoryTable;        /* Instance memory allocation table */
+    LVDBE_Params_t                Params;             /* Instance parameters */
+    LVDBE_Capabilities_t        Capabilities;         /* Instance capabilities */
+
+    /* Data and coefficient pointers */
+    LVDBE_Data_t                *pData;                /* Instance data */
+    LVDBE_Coef_t                *pCoef;                /* Instance coefficients */
+
+    LVM_INT32                   bTransitionOnToOff;
+
+} LVDBE_Instance_t;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* Function prototypes                                                                  */
+/*                                                                                      */
+/****************************************************************************************/
+
+void    LVDBE_SetAGC(LVDBE_Instance_t       *pInstance,
+                     LVDBE_Params_t         *pParams);
+
+
+void    LVDBE_SetVolume(LVDBE_Instance_t    *pInstance,
+                        LVDBE_Params_t      *pParams);
+
+
+void    LVDBE_SetFilters(LVDBE_Instance_t   *pInstance,
+                         LVDBE_Params_t     *pParams);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif      /* __LVDBE_PRIVATE_H__ */
+
+
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
new file mode 100755
index 0000000..35eec07
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1081 $
+     $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+#include "VectorArithmetic.h"
+#include "AGC.h"
+#include "LVDBE_Coeffs.h"               /* Filter coefficients */
+
+
+/********************************************************************************************/
+/*                                                                                          */
+/* FUNCTION:                 LVDBE_Process                                                  */
+/*                                                                                          */
+/* DESCRIPTION:                                                                             */
+/*  Process function for the Bass Enhancement module.                                       */
+/*                                                                                          */
+/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono            */
+/*  format is not supported, the calling routine must convert the mono stream to            */
+/*  mono-in-stereo.                                                                         */
+/*                                                        ___________                       */
+/*       ________                                        |           |    ________          */
+/*      |        |    _____   |------------------------->|           |   |        |         */
+/*      | 16-bit |   |     |  |    ________              |           |   | 32-bit |         */
+/* -+-->|   to   |-->| HPF |--|   |        |    _____    | AGC Mixer |-->|   to   |--|      */
+/*  |   | 32-bit |   |_____|  |   | Stereo |   |     |   |           |   | 16-bit |  |      */
+/*  |   |________|            |-->|   to   |-->| BPF |-->|           |   |________|  0      */
+/*  |                             |  Mono  |   |_____|   |___________|                \-->  */
+/*  |                             |________|                                                */
+/*  |                                                     _________                  0      */
+/*  |                                                    |         |                 |      */
+/*  |----------------------------------------------------| Volume  |-----------------|      */
+/*                                                       | Control |                        */
+/*                                                       |_________|                        */
+/*                                                                                          */
+/* PARAMETERS:                                                                              */
+/*  hInstance                 Instance handle                                               */
+/*  pInData                  Pointer to the input data                                      */
+/*  pOutData                 Pointer to the output data                                     */
+/*  NumSamples                 Number of samples in the input buffer                        */
+/*                                                                                          */
+/* RETURNS:                                                                                 */
+/*  LVDBE_SUCCESS            Succeeded                                                      */
+/*    LVDBE_TOOMANYSAMPLES    NumSamples was larger than the maximum block size             */
+/*                                                                                          */
+/* NOTES:                                                                                   */
+/*  1. The input and output data must be 32-bit format. The input is scaled by a shift      */
+/*     when converting from 16-bit format, this scaling allows for internal headroom in the */
+/*     bass enhancement algorithm.                                                          */
+/*  2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with   */
+/*     the headroom loss. This headroom loss is compensated in the volume control so the    */
+/*     overall end to end gain is odB.                                                      */
+/*                                                                                          */
+/********************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t            hInstance,
+                                       const LVM_INT16         *pInData,
+                                       LVM_INT16               *pOutData,
+                                       LVM_UINT16                   NumSamples)
+{
+
+    LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
+    LVM_INT32           *pScratch  = (LVM_INT32 *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
+    LVM_INT32           *pMono     = (LVM_INT32 *)pOutData;
+    LVM_INT16           *pInput    = (LVM_INT16 *)pInData;
+
+
+    /*
+     * Check the number of samples is not too large
+     */
+    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+    {
+        return(LVDBE_TOOMANYSAMPLES);
+    }
+
+    /*
+     * Check if the algorithm is enabled
+     */
+    if ((pInstance->Params.OperatingMode != LVDBE_OFF) ||
+        (pInstance->bTransitionOnToOff == LVM_TRUE))
+    {
+
+        /*
+         * Convert 16-bit samples to 32-bit and scale
+         * (For a 16-bit implementation apply headroom loss here)
+         */
+        Int16LShiftToInt32_16x32(pInput,                               /* Source 16-bit data      */
+                                 pScratch,                             /* Destination 32-bit data */
+                                 (LVM_INT16)(2*NumSamples),            /* Left and right          */
+                                 LVDBE_SCALESHIFT);                    /* Shift scale             */
+
+
+        /*
+         * Apply the high pass filter if selected
+         */
+        if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
+        {
+              BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,    /* Filter instance         */
+                                       (LVM_INT32 *)pScratch,               /* Source                  */
+                                       (LVM_INT32 *)pScratch,               /* Destination             */
+                                       (LVM_INT16)NumSamples);              /* Number of samples       */
+        }
+
+
+        /*
+         * Create the mono stream
+         */
+        From2iToMono_32(pScratch,                                      /* Stereo source           */
+                        pMono,                                         /* Mono destination        */
+                        (LVM_INT16)NumSamples);                        /* Number of samples       */
+
+
+        /*
+         * Apply the band pass filter
+         */
+          BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance,     /* Filter instance         */
+                                   (LVM_INT32 *)pMono,                 /* Source                  */
+                                   (LVM_INT32 *)pMono,                 /* Destination             */
+                                   (LVM_INT16)NumSamples);             /* Number of samples       */
+
+
+        /*
+         * Apply the AGC and mix
+         */
+        AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance,    /* Instance pointer        */
+                                    pScratch,                          /* Stereo source           */
+                                    pMono,                             /* Mono band pass source   */
+                                    pScratch,                          /* Stereo destination      */
+                                    NumSamples);                       /* Number of samples       */
+
+        if(pInstance->bTransitionOnToOff == LVM_TRUE)
+        {
+            if ((pInstance->pData->AGCInstance.AGC_Gain == pInstance->pData->AGCInstance.AGC_Target)&&
+                (pInstance->pData->AGCInstance.AGC_Gain == 0))
+            {
+                    pInstance->bTransitionOnToOff = LVM_FALSE;
+            }
+        }
+
+
+
+        /*
+         * Convert 32-bit samples to 16-bit and saturate
+         * (Not required for 16-bit implemenations)
+         */
+        Int32RShiftToInt16_Sat_32x16(pScratch,                         /* Source 32-bit data      */
+                                     pOutData,                         /* Destination 16-bit data */
+                                     (LVM_INT16)(2*NumSamples),        /* Left and right          */
+                                     LVDBE_SCALESHIFT);                /* Shift scale             */
+
+    }
+    else
+    {
+
+        /*
+         * The algorithm is disabled but volume management is required to compensate for
+         * headroom and volume (if enabled)
+         */
+        LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
+                                  pInData,
+                               pOutData,
+                               (LVM_INT16)(2*NumSamples));           /* Left and right           */
+
+    }
+
+    return(LVDBE_SUCCESS);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
new file mode 100755
index 0000000..da8ca5a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1009 $
+     $Date: 2010-06-28 14:14:15 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Coeffs.h"               /* Filter coefficients */
+#include "BIQUAD.h"
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Coefficients constant table                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * High Pass Filter Coefficient table
+ */
+const BQ_C32_Coefs_t LVDBE_HPF_Table[] = {
+    /* Coefficients for 55Hz centre frequency */
+    {HPF_Fs8000_Fc55_A2,                /* 8kS/s coefficients */
+     HPF_Fs8000_Fc55_A1,
+     HPF_Fs8000_Fc55_A0,
+     -HPF_Fs8000_Fc55_B2,
+     -HPF_Fs8000_Fc55_B1},
+    {HPF_Fs11025_Fc55_A2,                /* 11kS/s coefficients */
+     HPF_Fs11025_Fc55_A1,
+     HPF_Fs11025_Fc55_A0,
+     -HPF_Fs11025_Fc55_B2,
+     -HPF_Fs11025_Fc55_B1},
+    {HPF_Fs12000_Fc55_A2,                /* 12kS/s coefficients */
+     HPF_Fs12000_Fc55_A1,
+     HPF_Fs12000_Fc55_A0,
+     -HPF_Fs12000_Fc55_B2,
+     -HPF_Fs12000_Fc55_B1},
+    {HPF_Fs16000_Fc55_A2,                /* 16kS/s coefficients */
+     HPF_Fs16000_Fc55_A1,
+     HPF_Fs16000_Fc55_A0,
+     -HPF_Fs16000_Fc55_B2,
+     -HPF_Fs16000_Fc55_B1},
+    {HPF_Fs22050_Fc55_A2,                /* 22kS/s coefficients */
+     HPF_Fs22050_Fc55_A1,
+     HPF_Fs22050_Fc55_A0,
+     -HPF_Fs22050_Fc55_B2,
+     -HPF_Fs22050_Fc55_B1},
+    {HPF_Fs24000_Fc55_A2,                /* 24kS/s coefficients */
+     HPF_Fs24000_Fc55_A1,
+     HPF_Fs24000_Fc55_A0,
+     -HPF_Fs24000_Fc55_B2,
+     -HPF_Fs24000_Fc55_B1},
+    {HPF_Fs32000_Fc55_A2,                /* 32kS/s coefficients */
+     HPF_Fs32000_Fc55_A1,
+     HPF_Fs32000_Fc55_A0,
+     -HPF_Fs32000_Fc55_B2,
+     -HPF_Fs32000_Fc55_B1},
+    {HPF_Fs44100_Fc55_A2,                /* 44kS/s coefficients */
+     HPF_Fs44100_Fc55_A1,
+     HPF_Fs44100_Fc55_A0,
+     -HPF_Fs44100_Fc55_B2,
+     -HPF_Fs44100_Fc55_B1},
+    {HPF_Fs48000_Fc55_A2,                /* 48kS/s coefficients */
+     HPF_Fs48000_Fc55_A1,
+     HPF_Fs48000_Fc55_A0,
+     -HPF_Fs48000_Fc55_B2,
+     -HPF_Fs48000_Fc55_B1},
+
+    /* Coefficients for 66Hz centre frequency */
+    {HPF_Fs8000_Fc66_A2,                /* 8kS/s coefficients */
+     HPF_Fs8000_Fc66_A1,
+     HPF_Fs8000_Fc66_A0,
+     -HPF_Fs8000_Fc66_B2,
+     -HPF_Fs8000_Fc66_B1},
+    {HPF_Fs11025_Fc66_A2,                /* 11kS/s coefficients */
+     HPF_Fs11025_Fc66_A1,
+     HPF_Fs11025_Fc66_A0,
+     -HPF_Fs11025_Fc66_B2,
+     -HPF_Fs11025_Fc66_B1},
+    {HPF_Fs12000_Fc66_A2,                /* 12kS/s coefficients */
+     HPF_Fs12000_Fc66_A1,
+     HPF_Fs12000_Fc66_A0,
+     -HPF_Fs12000_Fc66_B2,
+     -HPF_Fs12000_Fc66_B1},
+    {HPF_Fs16000_Fc66_A2,                /* 16kS/s coefficients */
+     HPF_Fs16000_Fc66_A1,
+     HPF_Fs16000_Fc66_A0,
+     -HPF_Fs16000_Fc66_B2,
+     -HPF_Fs16000_Fc66_B1},
+    {HPF_Fs22050_Fc66_A2,                /* 22kS/s coefficients */
+     HPF_Fs22050_Fc66_A1,
+     HPF_Fs22050_Fc66_A0,
+     -HPF_Fs22050_Fc66_B2,
+     -HPF_Fs22050_Fc66_B1},
+    {HPF_Fs24000_Fc66_A2,                /* 24kS/s coefficients */
+     HPF_Fs24000_Fc66_A1,
+     HPF_Fs24000_Fc66_A0,
+     -HPF_Fs24000_Fc66_B2,
+     -HPF_Fs24000_Fc66_B1},
+    {HPF_Fs32000_Fc66_A2,                /* 32kS/s coefficients */
+     HPF_Fs32000_Fc66_A1,
+     HPF_Fs32000_Fc66_A0,
+     -HPF_Fs32000_Fc66_B2,
+     -HPF_Fs32000_Fc66_B1},
+    {HPF_Fs44100_Fc66_A2,                /* 44kS/s coefficients */
+     HPF_Fs44100_Fc66_A1,
+     HPF_Fs44100_Fc66_A0,
+     -HPF_Fs44100_Fc66_B2,
+     -HPF_Fs44100_Fc66_B1},
+    {HPF_Fs48000_Fc66_A2,                /* 48kS/s coefficients */
+     HPF_Fs48000_Fc66_A1,
+     HPF_Fs48000_Fc66_A0,
+     -HPF_Fs48000_Fc66_B2,
+     -HPF_Fs48000_Fc66_B1},
+
+    /* Coefficients for 78Hz centre frequency */
+    {HPF_Fs8000_Fc78_A2,                /* 8kS/s coefficients */
+     HPF_Fs8000_Fc78_A1,
+     HPF_Fs8000_Fc78_A0,
+     -HPF_Fs8000_Fc78_B2,
+     -HPF_Fs8000_Fc78_B1},
+    {HPF_Fs11025_Fc78_A2,                /* 11kS/s coefficients */
+     HPF_Fs11025_Fc78_A1,
+     HPF_Fs11025_Fc78_A0,
+     -HPF_Fs11025_Fc78_B2,
+     -HPF_Fs11025_Fc78_B1},
+    {HPF_Fs12000_Fc78_A2,                /* 12kS/s coefficients */
+     HPF_Fs12000_Fc78_A1,
+     HPF_Fs12000_Fc78_A0,
+     -HPF_Fs12000_Fc78_B2,
+     -HPF_Fs12000_Fc78_B1},
+    {HPF_Fs16000_Fc78_A2,                /* 16kS/s coefficients */
+     HPF_Fs16000_Fc78_A1,
+     HPF_Fs16000_Fc78_A0,
+     -HPF_Fs16000_Fc78_B2,
+     -HPF_Fs16000_Fc78_B1},
+    {HPF_Fs22050_Fc78_A2,                /* 22kS/s coefficients */
+     HPF_Fs22050_Fc78_A1,
+     HPF_Fs22050_Fc78_A0,
+     -HPF_Fs22050_Fc78_B2,
+     -HPF_Fs22050_Fc78_B1},
+    {HPF_Fs24000_Fc78_A2,                /* 24kS/s coefficients */
+     HPF_Fs24000_Fc78_A1,
+     HPF_Fs24000_Fc78_A0,
+     -HPF_Fs24000_Fc78_B2,
+     -HPF_Fs24000_Fc78_B1},
+    {HPF_Fs32000_Fc78_A2,                /* 32kS/s coefficients */
+     HPF_Fs32000_Fc78_A1,
+     HPF_Fs32000_Fc78_A0,
+     -HPF_Fs32000_Fc78_B2,
+     -HPF_Fs32000_Fc78_B1},
+    {HPF_Fs44100_Fc78_A2,                /* 44kS/s coefficients */
+     HPF_Fs44100_Fc78_A1,
+     HPF_Fs44100_Fc78_A0,
+     -HPF_Fs44100_Fc78_B2,
+     -HPF_Fs44100_Fc78_B1},
+    {HPF_Fs48000_Fc78_A2,                /* 48kS/s coefficients */
+     HPF_Fs48000_Fc78_A1,
+     HPF_Fs48000_Fc78_A0,
+     -HPF_Fs48000_Fc78_B2,
+     -HPF_Fs48000_Fc78_B1},
+
+    /* Coefficients for 90Hz centre frequency */
+    {HPF_Fs8000_Fc90_A2,                /* 8kS/s coefficients */
+     HPF_Fs8000_Fc90_A1,
+     HPF_Fs8000_Fc90_A0,
+     -HPF_Fs8000_Fc90_B2,
+     -HPF_Fs8000_Fc90_B1},
+    {HPF_Fs11025_Fc90_A2,                /* 11kS/s coefficients */
+     HPF_Fs11025_Fc90_A1,
+     HPF_Fs11025_Fc90_A0,
+     -HPF_Fs11025_Fc90_B2,
+     -HPF_Fs11025_Fc90_B1},
+    {HPF_Fs12000_Fc90_A2,                /* 12kS/s coefficients */
+     HPF_Fs12000_Fc90_A1,
+     HPF_Fs12000_Fc90_A0,
+     -HPF_Fs12000_Fc90_B2,
+     -HPF_Fs12000_Fc90_B1},
+    {HPF_Fs16000_Fc90_A2,                /* 16kS/s coefficients */
+     HPF_Fs16000_Fc90_A1,
+     HPF_Fs16000_Fc90_A0,
+     -HPF_Fs16000_Fc90_B2,
+     -HPF_Fs16000_Fc90_B1},
+    {HPF_Fs22050_Fc90_A2,                /* 22kS/s coefficients */
+     HPF_Fs22050_Fc90_A1,
+     HPF_Fs22050_Fc90_A0,
+     -HPF_Fs22050_Fc90_B2,
+     -HPF_Fs22050_Fc90_B1},
+    {HPF_Fs24000_Fc90_A2,                /* 24kS/s coefficients */
+     HPF_Fs24000_Fc90_A1,
+     HPF_Fs24000_Fc90_A0,
+     -HPF_Fs24000_Fc90_B2,
+     -HPF_Fs24000_Fc90_B1},
+    {HPF_Fs32000_Fc90_A2,                /* 32kS/s coefficients */
+     HPF_Fs32000_Fc90_A1,
+     HPF_Fs32000_Fc90_A0,
+     -HPF_Fs32000_Fc90_B2,
+     -HPF_Fs32000_Fc90_B1},
+    {HPF_Fs44100_Fc90_A2,                /* 44kS/s coefficients */
+     HPF_Fs44100_Fc90_A1,
+     HPF_Fs44100_Fc90_A0,
+     -HPF_Fs44100_Fc90_B2,
+     -HPF_Fs44100_Fc90_B1},
+    {HPF_Fs48000_Fc90_A2,                /* 48kS/s coefficients */
+     HPF_Fs48000_Fc90_A1,
+     HPF_Fs48000_Fc90_A0,
+     -HPF_Fs48000_Fc90_B2,
+     -HPF_Fs48000_Fc90_B1}};
+
+/*
+ * Band Pass Filter coefficient table
+ */
+const BP_C32_Coefs_t LVDBE_BPF_Table[] = {
+    /* Coefficients for 55Hz centre frequency */
+    {BPF_Fs8000_Fc55_A0,                /* 8kS/s coefficients */
+     -BPF_Fs8000_Fc55_B2,
+     -BPF_Fs8000_Fc55_B1},
+    {BPF_Fs11025_Fc55_A0,                /* 11kS/s coefficients */
+     -BPF_Fs11025_Fc55_B2,
+     -BPF_Fs11025_Fc55_B1},
+    {BPF_Fs12000_Fc55_A0,                /* 12kS/s coefficients */
+     -BPF_Fs12000_Fc55_B2,
+     -BPF_Fs12000_Fc55_B1},
+    {BPF_Fs16000_Fc55_A0,                /* 16kS/s coefficients */
+     -BPF_Fs16000_Fc55_B2,
+     -BPF_Fs16000_Fc55_B1},
+    {BPF_Fs22050_Fc55_A0,                /* 22kS/s coefficients */
+     -BPF_Fs22050_Fc55_B2,
+     -BPF_Fs22050_Fc55_B1},
+    {BPF_Fs24000_Fc55_A0,                /* 24kS/s coefficients */
+     -BPF_Fs24000_Fc55_B2,
+     -BPF_Fs24000_Fc55_B1},
+    {BPF_Fs32000_Fc55_A0,                /* 32kS/s coefficients */
+     -BPF_Fs32000_Fc55_B2,
+     -BPF_Fs32000_Fc55_B1},
+    {BPF_Fs44100_Fc55_A0,                /* 44kS/s coefficients */
+     -BPF_Fs44100_Fc55_B2,
+     -BPF_Fs44100_Fc55_B1},
+    {BPF_Fs48000_Fc55_A0,                /* 48kS/s coefficients */
+     -BPF_Fs48000_Fc55_B2,
+     -BPF_Fs48000_Fc55_B1},
+
+    /* Coefficients for 66Hz centre frequency */
+    {BPF_Fs8000_Fc66_A0,                /* 8kS/s coefficients */
+     -BPF_Fs8000_Fc66_B2,
+     -BPF_Fs8000_Fc66_B1},
+    {BPF_Fs11025_Fc66_A0,                /* 11kS/s coefficients */
+     -BPF_Fs11025_Fc66_B2,
+     -BPF_Fs11025_Fc66_B1},
+    {BPF_Fs12000_Fc66_A0,                /* 12kS/s coefficients */
+     -BPF_Fs12000_Fc66_B2,
+     -BPF_Fs12000_Fc66_B1},
+    {BPF_Fs16000_Fc66_A0,                /* 16kS/s coefficients */
+     -BPF_Fs16000_Fc66_B2,
+     -BPF_Fs16000_Fc66_B1},
+    {BPF_Fs22050_Fc66_A0,                /* 22kS/s coefficients */
+     -BPF_Fs22050_Fc66_B2,
+     -BPF_Fs22050_Fc66_B1},
+    {BPF_Fs24000_Fc66_A0,                /* 24kS/s coefficients */
+     -BPF_Fs24000_Fc66_B2,
+     -BPF_Fs24000_Fc66_B1},
+    {BPF_Fs32000_Fc66_A0,                /* 32kS/s coefficients */
+     -BPF_Fs32000_Fc66_B2,
+     -BPF_Fs32000_Fc66_B1},
+    {BPF_Fs44100_Fc66_A0,                /* 44kS/s coefficients */
+     -BPF_Fs44100_Fc66_B2,
+     -BPF_Fs44100_Fc66_B1},
+    {BPF_Fs48000_Fc66_A0,                /* 48kS/s coefficients */
+     -BPF_Fs48000_Fc66_B2,
+     -BPF_Fs48000_Fc66_B1},
+
+    /* Coefficients for 78Hz centre frequency */
+    {BPF_Fs8000_Fc78_A0,                /* 8kS/s coefficients */
+     -BPF_Fs8000_Fc78_B2,
+     -BPF_Fs8000_Fc78_B1},
+    {BPF_Fs11025_Fc78_A0,                /* 11kS/s coefficients */
+     -BPF_Fs11025_Fc78_B2,
+     -BPF_Fs11025_Fc78_B1},
+    {BPF_Fs12000_Fc78_A0,                /* 12kS/s coefficients */
+     -BPF_Fs12000_Fc78_B2,
+     -BPF_Fs12000_Fc78_B1},
+    {BPF_Fs16000_Fc78_A0,                /* 16kS/s coefficients */
+     -BPF_Fs16000_Fc78_B2,
+     -BPF_Fs16000_Fc78_B1},
+    {BPF_Fs22050_Fc78_A0,                /* 22kS/s coefficients */
+     -BPF_Fs22050_Fc78_B2,
+     -BPF_Fs22050_Fc78_B1},
+    {BPF_Fs24000_Fc78_A0,                /* 24kS/s coefficients */
+     -BPF_Fs24000_Fc78_B2,
+     -BPF_Fs24000_Fc78_B1},
+    {BPF_Fs32000_Fc78_A0,                /* 32kS/s coefficients */
+     -BPF_Fs32000_Fc78_B2,
+     -BPF_Fs32000_Fc78_B1},
+    {BPF_Fs44100_Fc78_A0,                /* 44kS/s coefficients */
+     -BPF_Fs44100_Fc78_B2,
+     -BPF_Fs44100_Fc78_B1},
+    {BPF_Fs48000_Fc78_A0,                /* 48kS/s coefficients */
+     -BPF_Fs48000_Fc78_B2,
+     -BPF_Fs48000_Fc78_B1},
+
+    /* Coefficients for 90Hz centre frequency */
+    {BPF_Fs8000_Fc90_A0,                /* 8kS/s coefficients */
+     -BPF_Fs8000_Fc90_B2,
+     -BPF_Fs8000_Fc90_B1},
+    {BPF_Fs11025_Fc90_A0,                /* 11kS/s coefficients */
+     -BPF_Fs11025_Fc90_B2,
+     -BPF_Fs11025_Fc90_B1},
+    {BPF_Fs12000_Fc90_A0,                /* 12kS/s coefficients */
+     -BPF_Fs12000_Fc90_B2,
+     -BPF_Fs12000_Fc90_B1},
+    {BPF_Fs16000_Fc90_A0,                /* 16kS/s coefficients */
+     -BPF_Fs16000_Fc90_B2,
+     -BPF_Fs16000_Fc90_B1},
+    {BPF_Fs22050_Fc90_A0,                /* 22kS/s coefficients */
+     -BPF_Fs22050_Fc90_B2,
+     -BPF_Fs22050_Fc90_B1},
+    {BPF_Fs24000_Fc90_A0,                /* 24kS/s coefficients */
+     -BPF_Fs24000_Fc90_B2,
+     -BPF_Fs24000_Fc90_B1},
+    {BPF_Fs32000_Fc90_A0,                /* 32kS/s coefficients */
+     -BPF_Fs32000_Fc90_B2,
+     -BPF_Fs32000_Fc90_B1},
+    {BPF_Fs44100_Fc90_A0,                /* 44kS/s coefficients */
+     -BPF_Fs44100_Fc90_B2,
+     -BPF_Fs44100_Fc90_B1},
+    {BPF_Fs48000_Fc90_A0,                /* 48kS/s coefficients */
+     -BPF_Fs48000_Fc90_B2,
+     -BPF_Fs48000_Fc90_B1}};
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    AGC constant tables                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Attack time (signal too large) */
+const LVM_INT16 LVDBE_AGC_ATTACK_Table[] = {
+    AGC_ATTACK_Fs8000,
+    AGC_ATTACK_Fs11025,
+    AGC_ATTACK_Fs12000,
+    AGC_ATTACK_Fs16000,
+    AGC_ATTACK_Fs22050,
+    AGC_ATTACK_Fs24000,
+    AGC_ATTACK_Fs32000,
+    AGC_ATTACK_Fs44100,
+    AGC_ATTACK_Fs48000};
+
+/* Decay time (signal too small) */
+const LVM_INT16 LVDBE_AGC_DECAY_Table[] = {
+    AGC_DECAY_Fs8000,
+    AGC_DECAY_Fs11025,
+    AGC_DECAY_Fs12000,
+    AGC_DECAY_Fs16000,
+    AGC_DECAY_Fs22050,
+    AGC_DECAY_Fs24000,
+    AGC_DECAY_Fs32000,
+    AGC_DECAY_Fs44100,
+    AGC_DECAY_Fs48000};
+
+/* Gain for use without the high pass filter */
+const LVM_INT32 LVDBE_AGC_GAIN_Table[] = {
+    AGC_GAIN_0dB,
+    AGC_GAIN_1dB,
+    AGC_GAIN_2dB,
+    AGC_GAIN_3dB,
+    AGC_GAIN_4dB,
+    AGC_GAIN_5dB,
+    AGC_GAIN_6dB,
+    AGC_GAIN_7dB,
+    AGC_GAIN_8dB,
+    AGC_GAIN_9dB,
+    AGC_GAIN_10dB,
+    AGC_GAIN_11dB,
+    AGC_GAIN_12dB,
+    AGC_GAIN_13dB,
+    AGC_GAIN_14dB,
+    AGC_GAIN_15dB};
+
+/* Gain for use with the high pass filter */
+const LVM_INT32 LVDBE_AGC_HPFGAIN_Table[] = {
+    AGC_HPFGAIN_0dB,
+    AGC_HPFGAIN_1dB,
+    AGC_HPFGAIN_2dB,
+    AGC_HPFGAIN_3dB,
+    AGC_HPFGAIN_4dB,
+    AGC_HPFGAIN_5dB,
+    AGC_HPFGAIN_6dB,
+    AGC_HPFGAIN_7dB,
+    AGC_HPFGAIN_8dB,
+    AGC_HPFGAIN_9dB,
+    AGC_HPFGAIN_10dB,
+    AGC_HPFGAIN_11dB,
+    AGC_HPFGAIN_12dB,
+    AGC_HPFGAIN_13dB,
+    AGC_HPFGAIN_14dB,
+    AGC_HPFGAIN_15dB};
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Volume control gain and time constant tables                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+const LVM_INT16 LVDBE_VolumeTable[] = {
+    0x4000,             /* -6dB */
+    0x47FB,             /* -5dB */
+    0x50C3,             /* -4dB */
+    0x5A9E,             /* -3dB */
+    0x65AD,             /* -2dB */
+    0x7215,             /* -1dB */
+    0x7FFF};            /*  0dB */
+
+const LVM_INT16 LVDBE_VolumeTCTable[] = {
+    VOL_TC_Fs8000,
+    VOL_TC_Fs11025,
+    VOL_TC_Fs12000,
+    VOL_TC_Fs16000,
+    VOL_TC_Fs22050,
+    VOL_TC_Fs24000,
+    VOL_TC_Fs32000,
+    VOL_TC_Fs44100,
+    VOL_TC_Fs48000};
+
+const LVM_INT16 LVDBE_MixerTCTable[] = {
+    MIX_TC_Fs8000,
+    MIX_TC_Fs11025,
+    MIX_TC_Fs12000,
+    MIX_TC_Fs16000,
+    MIX_TC_Fs22050,
+    MIX_TC_Fs24000,
+    MIX_TC_Fs32000,
+    MIX_TC_Fs44100,
+    MIX_TC_Fs48000};
+
+
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
new file mode 100755
index 0000000..4cb6d21
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1009 $
+     $Date: 2010-06-28 14:14:15 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+#ifndef __LVBDE_TABLES_H__
+#define __LVBDE_TABLES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "BIQUAD.h"
+#include "LVM_Types.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Coefficients constant table                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * High Pass Filter Coefficient table
+ */
+extern const BQ_C32_Coefs_t LVDBE_HPF_Table[];
+
+/*
+ * Band Pass Filter coefficient table
+ */
+extern const BP_C32_Coefs_t LVDBE_BPF_Table[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*    AGC constant tables                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Attack time (signal too large) */
+extern const LVM_INT16 LVDBE_AGC_ATTACK_Table[];
+
+/* Decay time (signal too small) */
+extern const LVM_INT16 LVDBE_AGC_DECAY_Table[];
+
+/* Gain for use without the high pass filter */
+extern const LVM_INT32 LVDBE_AGC_GAIN_Table[];
+
+/* Gain for use with the high pass filter */
+extern const LVM_INT32 LVDBE_AGC_HPFGAIN_Table[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Volume control gain and time constant tables                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+extern const LVM_INT16 LVDBE_VolumeTable[];
+
+extern const LVM_INT16 LVDBE_VolumeTCTable[];
+
+extern const LVM_INT16 LVDBE_MixerTCTable[];
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVBDE_TABLES_H__ */
diff --git a/media/libeffects/lvm/lib/Bundle/lib/LVM.h b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
new file mode 100755
index 0000000..d472182
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*****************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1002 $
+     $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Header file for the application layer interface of Concert Sound, Bass Enhancement, */
+/*  Equalizer, Power Spectrum Analyzer, Trebble Enhancement and volume management       */
+/*  bundle.                                                                             */
+/*                                                                                      */
+/*  This files includes all definitions, types, structures and function                 */
+/*  prototypes required by the calling layer. All other types, structures and           */
+/*  functions are private.                                                              */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*  Note: 1                                                                             */
+/*  =======                                                                             */
+/*  The algorithm can execute either with separate input and output buffers or with     */
+/*  a common buffer, i.e. the data is processed in-place.                               */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*  Note: 2                                                                             */
+/*  =======                                                                             */
+/*  Three data formats are support Stereo,Mono-In-Stereo and Mono. The data is          */
+/*  interleaved as follows:                                                             */
+/*                                                                                      */
+/*  Byte Offset         Stereo Input         Mono-In-Stereo Input       Mono Input      */
+/*  ===========         ============         ====================     ==============    */
+/*      0               Left Sample #1          Mono Sample #1        Mono Sample #1    */
+/*      2               Right Sample #1         Mono Sample #1        Mono Sample #2    */
+/*      4               Left Sample #2          Mono Sample #2        Mono Sample #3    */
+/*      6               Right Sample #2         Mono Sample #2        Mono Sample #4    */
+/*      .                      .                     .                     .            */
+/*      .                      .                     .                     .            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#ifndef __LVM_H__
+#define __LVM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVM_Types.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Definitions                                                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory table*/
+#define LVM_NR_MEMORY_REGIONS                 4     /* Number of memory regions */
+
+/* Concert Sound effect level presets */
+#define LVM_CS_EFFECT_NONE                    0     /* 0% effect, minimum value */
+#define LVM_CS_EFFECT_LOW                 16384     /* 50% effect */
+#define LVM_CS_EFFECT_MED                 24576     /* 75% effect */
+#define LVM_CS_EFFECT_HIGH                32767     /* 100% effect, maximum value */
+
+/* Treble enhancement */
+#define LVM_TE_LOW_MIPS                   32767
+
+/* Bass enhancement effect level presets */
+#define LVM_BE_0DB                            0     /* 0dB boost, no effect */
+#define LVM_BE_3DB                            3     /* +3dB boost */
+#define LVM_BE_6DB                            6     /* +6dB boost */
+#define LVM_BE_9DB                            9     /* +9dB boost */
+#define LVM_BE_12DB                          12     /* +12dB boost */
+#define LVM_BE_15DB                          15     /* +15dB boost */
+
+/* N-Band Equalizer */
+#define LVM_EQ_NBANDS                         5    /* Number of bands for equalizer */
+
+/* Headroom management */
+#define LVM_HEADROOM_MAX_NBANDS               5
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Types                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Instance handle */
+typedef void *LVM_Handle_t;
+
+
+/* Status return values */
+typedef enum
+{
+    LVM_SUCCESS            = 0,                     /* Successful return from a routine */
+    LVM_ALIGNMENTERROR     = 1,                     /* Memory alignment error */
+    LVM_NULLADDRESS        = 2,                     /* NULL allocation address */
+    LVM_OUTOFRANGE         = 3,                     /* Out of range control parameter */
+    LVM_INVALIDNUMSAMPLES  = 4,                     /* Invalid number of samples */
+    LVM_WRONGAUDIOTIME     = 5,                     /* Wrong time value for audio time*/
+    LVM_ALGORITHMDISABLED  = 6,                     /* Algorithm is disabled*/
+    LVM_ALGORITHMPSA       = 7,                     /* Algorithm PSA returns an error */
+    LVM_RETURNSTATUS_DUMMY = LVM_MAXENUM
+} LVM_ReturnStatus_en;
+
+
+/* Buffer Management mode */
+typedef enum
+{
+    LVM_MANAGED_BUFFERS   = 0,
+    LVM_UNMANAGED_BUFFERS = 1,
+    LVM_BUFFERS_DUMMY     = LVM_MAXENUM
+} LVM_BufferMode_en;
+
+/* Output device type */
+typedef enum
+{
+    LVM_HEADPHONES             = 0,
+    LVM_EX_HEADPHONES          = 1,
+    LVM_SPEAKERTYPE_MAX        = LVM_MAXENUM
+} LVM_OutputDeviceType_en;
+
+/* Virtualizer mode selection*/
+typedef enum
+{
+    LVM_CONCERTSOUND       = 0,
+    LVM_VIRTUALIZERTYPE_DUMMY   = LVM_MAXENUM
+} LVM_VirtualizerType_en;
+
+/* N-Band Equaliser operating mode */
+typedef enum
+{
+    LVM_EQNB_OFF   = 0,
+    LVM_EQNB_ON    = 1,
+    LVM_EQNB_DUMMY = LVM_MAXENUM
+} LVM_EQNB_Mode_en;
+
+/* Bass Enhancement operating mode */
+typedef enum
+{
+    LVM_BE_OFF   = 0,
+    LVM_BE_ON    = 1,
+    LVM_BE_DUMMY = LVM_MAXENUM
+} LVM_BE_Mode_en;
+
+/* Bass Enhancement centre frequency selection control */
+typedef enum
+{
+    LVM_BE_CENTRE_55Hz  = 0,
+    LVM_BE_CENTRE_66Hz  = 1,
+    LVM_BE_CENTRE_78Hz  = 2,
+    LVM_BE_CENTRE_90Hz  = 3,
+    LVM_BE_CENTRE_DUMMY = LVM_MAXENUM
+} LVM_BE_CentreFreq_en;
+
+/* Bass Enhancement HPF selection control */
+typedef enum
+{
+    LVM_BE_HPF_OFF   = 0,
+    LVM_BE_HPF_ON    = 1,
+    LVM_BE_HPF_DUMMY = LVM_MAXENUM
+} LVM_BE_FilterSelect_en;
+
+/* Volume Control operating mode */
+typedef enum
+{
+    LVM_VC_OFF   = 0,
+    LVM_VC_ON    = 1,
+    LVM_VC_DUMMY = LVM_MAXENUM
+} LVM_VC_Mode_en;
+
+/* Treble Enhancement operating mode */
+typedef enum
+{
+    LVM_TE_OFF   = 0,
+    LVM_TE_ON    = 1,
+    LVM_TE_DUMMY = LVM_MAXENUM
+} LVM_TE_Mode_en;
+
+/* Headroom management operating mode */
+typedef enum
+{
+    LVM_HEADROOM_OFF   = 0,
+    LVM_HEADROOM_ON    = 1,
+    LVM_Headroom_DUMMY = LVM_MAXENUM
+} LVM_Headroom_Mode_en;
+
+typedef enum
+{
+    LVM_PSA_SPEED_SLOW,                                  /* Peak decaying at slow speed */
+    LVM_PSA_SPEED_MEDIUM,                                /* Peak decaying at medium speed */
+    LVM_PSA_SPEED_FAST,                                  /* Peak decaying at fast speed */
+    LVM_PSA_SPEED_DUMMY = LVM_MAXENUM
+} LVM_PSA_DecaySpeed_en;
+
+typedef enum
+{
+    LVM_PSA_OFF   = 0,
+    LVM_PSA_ON    = 1,
+    LVM_PSA_DUMMY = LVM_MAXENUM
+} LVM_PSA_Mode_en;
+
+/* Version information */
+typedef struct
+{
+    LVM_CHAR                    *pVersionNumber;        /* Pointer to the version number in the format X.YY.ZZ */
+    LVM_CHAR                    *pPlatform;             /* Pointer to the library platform type */
+} LVM_VersionInfo_st;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Structures                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+    LVM_MemoryRegion_st         Region[LVM_NR_MEMORY_REGIONS];  /* One definition for each region */
+} LVM_MemTab_t;
+
+/* N-Band equaliser band definition */
+typedef struct
+{
+    LVM_INT16                   Gain;                   /* Band gain in dB */
+    LVM_UINT16                  Frequency;              /* Band centre frequency in Hz */
+    LVM_UINT16                  QFactor;                /* Band quality factor (x100) */
+} LVM_EQNB_BandDef_t;
+
+
+/* Headroom band definition */
+typedef struct
+{
+    LVM_UINT16                  Limit_Low;              /* Low frequency limit of the band in Hertz */
+    LVM_UINT16                  Limit_High;             /* High frequency limit of the band in Hertz */
+    LVM_INT16                   Headroom_Offset;        /* Headroom = biggest band gain - Headroom_Offset */
+} LVM_HeadroomBandDef_t;
+
+
+/* Control Parameter structure */
+typedef struct
+{
+    /* General parameters */
+    LVM_Mode_en                 OperatingMode;          /* Bundle operating mode On/Bypass */
+    LVM_Fs_en                   SampleRate;             /* Sample rate */
+    LVM_Format_en               SourceFormat;           /* Input data format */
+    LVM_OutputDeviceType_en     SpeakerType;            /* Output device type */
+
+    /* Concert Sound Virtualizer parameters*/
+    LVM_Mode_en                 VirtualizerOperatingMode; /* Virtualizer operating mode On/Off */
+    LVM_VirtualizerType_en      VirtualizerType;          /* Virtualizer type: ConcertSound */
+    LVM_UINT16                  VirtualizerReverbLevel;   /* Virtualizer reverb level in % */
+    LVM_INT16                   CS_EffectLevel;           /* Concert Sound effect level */
+
+    /* N-Band Equaliser parameters */
+    LVM_EQNB_Mode_en            EQNB_OperatingMode;     /* N-Band Equaliser operating mode */
+    LVM_UINT16                  EQNB_NBands;            /* Number of bands */
+    LVM_EQNB_BandDef_t          *pEQNB_BandDefinition;  /* Pointer to equaliser definitions */
+
+    /* Bass Enhancement parameters */
+    LVM_BE_Mode_en              BE_OperatingMode;       /* Bass Enhancement operating mode */
+    LVM_INT16                   BE_EffectLevel;         /* Bass Enhancement effect level */
+    LVM_BE_CentreFreq_en        BE_CentreFreq;          /* Bass Enhancement centre frequency */
+    LVM_BE_FilterSelect_en      BE_HPF;                 /* Bass Enhancement high pass filter selector */
+
+    /* Volume Control parameters */
+    LVM_INT16                   VC_EffectLevel;         /* Volume Control setting in dBs */
+    LVM_INT16                   VC_Balance;             /* Left Right Balance control in dB (-96 to 96 dB), -ve values reduce
+                                                           Right channel while +ve value reduces Left channel*/
+
+    /* Treble Enhancement parameters */
+    LVM_TE_Mode_en              TE_OperatingMode;       /* Treble Enhancement On/Off */
+    LVM_INT16                   TE_EffectLevel;         /* Treble Enhancement gain dBs */
+
+    /* Spectrum Analyzer parameters Control */
+    LVM_PSA_Mode_en             PSA_Enable;
+    LVM_PSA_DecaySpeed_en       PSA_PeakDecayRate;      /* Peak value decay rate*/
+
+} LVM_ControlParams_t;
+
+
+/* Instance Parameter structure */
+typedef struct
+{
+    /* General */
+    LVM_BufferMode_en           BufferMode;             /* Buffer management mode */
+    LVM_UINT16                  MaxBlockSize;           /* Maximum processing block size */
+
+    /* N-Band Equaliser */
+    LVM_UINT16                  EQNB_NumBands;          /* Maximum number of equaliser bands */
+
+    /* PSA */
+    LVM_PSA_Mode_en             PSA_Included;            /* Controls the instance memory allocation for PSA: ON/OFF */
+} LVM_InstParams_t;
+
+/* Headroom management parameter structure */
+typedef struct
+{
+    LVM_Headroom_Mode_en        Headroom_OperatingMode; /* Headroom Control On/Off */
+    LVM_HeadroomBandDef_t       *pHeadroomDefinition;   /* Pointer to headroom bands definition */
+    LVM_UINT16                  NHeadroomBands;         /* Number of headroom bands */
+
+} LVM_HeadroomParams_t;
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Function Prototypes                                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetVersionInfo                                          */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to retrieve information about the library's version.          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pVersion                Pointer to an empty version info structure                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         when pVersion is NULL                                       */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetVersionInfo(LVM_VersionInfo_st  *pVersion);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetMemoryTable                                          */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pInstParams             Pointer to the instance parameters                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         When one of pMemoryTable or pInstParams is NULL             */
+/*  LVM_OUTOFRANGE          When any of the Instance parameters are out of range        */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t         hInstance,
+                                       LVM_MemTab_t         *pMemoryTable,
+                                       LVM_InstParams_t     *pInstParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetInstanceHandle                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to create a bundle instance. It returns the created instance  */
+/*  handle through phInstance. All parameters are set to their default, inactive state. */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  phInstance              pointer to the instance handle                              */
+/*  pMemoryTable            Pointer to the memory definition table                      */
+/*  pInstParams             Pointer to the instance parameters                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Initialisation succeeded                                    */
+/*  LVM_NULLADDRESS         One or more memory has a NULL pointer                       */
+/*  LVM_OUTOFRANGE          When any of the Instance parameters are out of range        */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function must not be interrupted by the LVM_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t        *phInstance,
+                                          LVM_MemTab_t        *pMemoryTable,
+                                          LVM_InstParams_t    *pInstParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_ClearAudioBuffers                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to clear the internal audio buffers of the bundle.            */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Initialisation succeeded                                    */
+/*  LVM_NULLADDRESS         Instance memory has a NULL pointer                          */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function must not be interrupted by the LVM_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t  hInstance);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_GetControlParameters                                   */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the LifeVibes module parameters. The current parameter set is returned      */
+/*  via the parameter pointer.                                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance handle                                            */
+/*  pParams                  Pointer to an empty parameter structure                    */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         when any of hInstance or pParams is NULL                    */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t           hInstance,
+                                             LVM_ControlParams_t    *pParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetControlParameters                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the LifeVibes module parameters.                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pParams                 Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         When hInstance, pParams or any control pointers are NULL    */
+/*  LVM_OUTOFRANGE          When any of the control parameters are out of range         */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t           hInstance,
+                                             LVM_ControlParams_t    *pParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_Process                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the LifeVibes module.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*  AudioTime               Audio Time of the current input data in milli-seconds       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS            Succeeded                                                    */
+/*  LVM_INVALIDNUMSAMPLES  When the NumSamples is not a valied multiple in unmanaged    */
+/*                         buffer mode                                                  */
+/*  LVM_ALIGNMENTERROR     When either the input our output buffers are not 32-bit      */
+/*                         aligned in unmanaged mode                                    */
+/*  LVM_NULLADDRESS        When one of hInstance, pInData or pOutData is NULL           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The input and output buffers must be 32-bit aligned                              */
+/*  2. Number of samples is defined as follows:                                         */
+/*      MONO                the number of samples in the block                          */
+/*      MONOINSTEREO        the number of sample pairs in the block                     */
+/*      STEREO              the number of sample pairs in the block                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
+                                const LVM_INT16             *pInData,
+                                LVM_INT16                   *pOutData,
+                                LVM_UINT16                  NumSamples,
+                                LVM_UINT32                  AudioTime);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetHeadroomParams                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to set the automatic headroom management parameters.          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pHeadroomParams         Pointer to headroom parameter structure                     */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_NULLADDRESS         When hInstance or pHeadroomParams is NULL                   */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetHeadroomParams(  LVM_Handle_t            hInstance,
+                                            LVM_HeadroomParams_t    *pHeadroomParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetHeadroomParams                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to get the automatic headroom management parameters.          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pHeadroomParams         Pointer to headroom parameter structure (output)            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         When hInstance or pHeadroomParams are NULL                  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetHeadroomParams(  LVM_Handle_t            hInstance,
+                                            LVM_HeadroomParams_t    *pHeadroomParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetSpectrum                                             */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/* This function is used to retrieve Spectral information at a given Audio time         */
+/* for display usage                                                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pCurrentPeaks           Pointer to location where currents peaks are to be saved    */
+/*  pPastPeaks              Pointer to location where past peaks are to be saved        */
+/*  pCentreFreqs            Pointer to location where centre frequency of each band is  */
+/*                          to be saved                                                 */
+/*  AudioTime               Audio time at which the spectral information is needed      */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         If any of input addresses are NULL                          */
+/*  LVM_WRONGAUDIOTIME      Failure due to audio time error                             */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetSpectrum( LVM_Handle_t            hInstance,
+                                     LVM_UINT8               *pCurrentPeaks,
+                                     LVM_UINT8               *pPastPeaks,
+                                     LVM_INT32               AudioTime);
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetVolumeNoSmoothing                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/* This function is used to set output volume without any smoothing                     */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pParams                 Control Parameters, only volume value is used here          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         If any of input addresses are NULL                          */
+/*  LVM_OUTOFRANGE          When any of the control parameters are out of range         */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t           hInstance,
+                                              LVM_ControlParams_t    *pParams);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif      /* __LVM_H__ */
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c b/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c
new file mode 100755
index 0000000..2f6fa4c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1002 $
+     $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "LVM_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetSpectrum                                             */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/* This function is used to retrieve Spectral information at a given Audio time         */
+/* for display usage                                                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pCurrentPeaks           Pointer to location where currents peaks are to be saved    */
+/*  pPastPeaks              Pointer to location where past peaks are to be saved        */
+/*  AudioTime               Audio time at which the spectral information is needed      */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         If any of input addresses are NULL                          */
+/*  LVM_WRONGAUDIOTIME      Failure due to audio time error                             */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetSpectrum(
+                                    LVM_Handle_t            hInstance,
+                                    LVM_UINT8               *pCurrentPeaks,
+                                    LVM_UINT8               *pPastPeaks,
+                                    LVM_INT32               AudioTime
+                                    )
+{
+    LVM_Instance_t           *pInstance   = (LVM_Instance_t  *)hInstance;
+
+    pLVPSA_Handle_t        *hPSAInstance;
+    LVPSA_RETURN           LVPSA_Status;
+
+
+    if(pInstance == LVM_NULL)
+    {
+        return LVM_NULLADDRESS;
+    }
+
+    /*If PSA is not included at the time of instance creation, return without any processing*/
+    if(pInstance->InstParams.PSA_Included!=LVM_PSA_ON)
+    {
+        return LVM_SUCCESS;
+    }
+
+    hPSAInstance = pInstance->hPSAInstance;
+
+    if((pCurrentPeaks == LVM_NULL) ||
+        (pPastPeaks == LVM_NULL))
+    {
+        return LVM_NULLADDRESS;
+    }
+
+
+    /*
+     * Update new parameters if necessary
+     */
+    if (pInstance->ControlPending == LVM_TRUE)
+    {
+        LVM_ApplyNewSettings(hInstance);
+    }
+
+    /* If PSA module is disabled, do nothing */
+    if(pInstance->Params.PSA_Enable==LVM_PSA_OFF)
+    {
+        return LVM_ALGORITHMDISABLED;
+    }
+
+    LVPSA_Status = LVPSA_GetSpectrum(hPSAInstance,
+                            (LVPSA_Time) (AudioTime),
+                            (LVM_UINT8*) pCurrentPeaks,
+                            (LVM_UINT8*) pPastPeaks );
+
+    if(LVPSA_Status != LVPSA_OK)
+    {
+        if(LVPSA_Status == LVPSA_ERROR_WRONGTIME)
+        {
+            return (LVM_ReturnStatus_en) LVM_WRONGAUDIOTIME;
+        }
+        else
+        {
+            return (LVM_ReturnStatus_en) LVM_NULLADDRESS;
+        }
+    }
+
+    return(LVM_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetVolumeNoSmoothing                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/* This function is used to set output volume without any smoothing                     */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pParams                 Control Parameters, only volume value is used here          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         If any of input addresses are NULL                          */
+/*  LVM_OUTOFRANGE          When any of the control parameters are out of range         */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t           hInstance,
+                                              LVM_ControlParams_t    *pParams)
+{
+    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
+    LVM_ReturnStatus_en Error;
+
+    /*Apply new controls*/
+    Error = LVM_SetControlParameters(hInstance,pParams);
+    pInstance->NoSmoothVolume = LVM_TRUE;
+    return Error;
+}
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
new file mode 100755
index 0000000..7273400
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
@@ -0,0 +1,878 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+
+/****************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1316 $
+     $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                        */
+/*    Includes                                                                              */
+/*                                                                                        */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "VectorArithmetic.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferManagedIn                                        */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Full buffer management allowing the user to provide input and output buffers on   */
+/*  any alignment and with any number of samples. The alignment is corrected within     */
+/*  the buffer management and the samples are grouped in to blocks of the correct size  */
+/*  before processing.                                                                  */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        -    Instance handle                                             */
+/*    pInData            -    Pointer to the input data stream                          */
+/*  *pToProcess        -    Pointer to pointer to the start of data processing          */
+/*  *pProcessed        -    Pointer to pointer to the destination of the processed data */
+/*    pNumSamples        -    Pointer to the number of samples to process               */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
+                         const LVM_INT16    *pInData,
+                         LVM_INT16          **pToProcess,
+                         LVM_INT16          **pProcessed,
+                         LVM_UINT16         *pNumSamples)
+{
+
+    LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
+    LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
+    LVM_INT16        *pStart;
+    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
+    LVM_Buffer_t     *pBuffer;
+    LVM_INT16        *pDest;
+    LVM_INT16        NumChannels =2;
+
+
+    /*
+     * Set the processing address pointers
+     */
+    pBuffer     = pInstance->pBufferManagement;
+    pDest       = pBuffer->pScratch;
+    *pToProcess = pBuffer->pScratch;
+    *pProcessed = pBuffer->pScratch;
+
+    /*
+     * Check if it is the first call of a block
+     */
+    if (pInstance->SamplesToProcess == 0)
+    {
+        /*
+         * First call for a new block of samples
+         */
+        pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
+        pInstance->pInputSamples    = (LVM_INT16 *)pInData;
+        pBuffer->BufferState        = LVM_FIRSTCALL;
+    }
+    pStart = pInstance->pInputSamples;                       /* Pointer to the input samples */
+    pBuffer->SamplesToOutput  = 0;                           /* Samples to output is same as number read for inplace processing */
+
+
+    /*
+     * Calculate the number of samples to process this call and update the buffer state
+     */
+    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+    {
+        /*
+         * Process the maximum bock size of samples.
+         */
+        SampleCount = pInstance->InternalBlockSize;
+        NumSamples  = pInstance->InternalBlockSize;
+    }
+    else
+    {
+        /*
+         * Last call for the block, so calculate how many frames and samples to process
+          */
+        LVM_INT16   NumFrames;
+
+        NumSamples  = pInstance->SamplesToProcess;
+        NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+        SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+
+        /*
+         * Update the buffer state
+         */
+        if (pBuffer->BufferState == LVM_FIRSTCALL)
+        {
+            pBuffer->BufferState = LVM_FIRSTLASTCALL;
+        }
+        else
+        {
+            pBuffer->BufferState = LVM_LASTCALL;
+        }
+    }
+    *pNumSamples = (LVM_UINT16)SampleCount;                        /* Set the number of samples to process this call */
+
+
+    /*
+     * Copy samples from the delay buffer as required
+     */
+    if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
+        (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
+        (pBuffer->InDelaySamples != 0))
+    {
+        Copy_16(&pBuffer->InDelayBuffer[0],                             /* Source */
+                pDest,                                                  /* Destination */
+                (LVM_INT16)(NumChannels*pBuffer->InDelaySamples));      /* Number of delay samples, left and right */
+        NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
+        pDest += NumChannels * pBuffer->InDelaySamples;                 /* Update the destination pointer */
+    }
+
+
+    /*
+     * Copy the rest of the samples for this call from the input buffer
+     */
+    if (NumSamples > 0)
+    {
+        Copy_16(pStart,                                             /* Source */
+                pDest,                                              /* Destination */
+                (LVM_INT16)(NumChannels*NumSamples));               /* Number of input samples */
+        pStart += NumChannels * NumSamples;                         /* Update the input pointer */
+
+        /*
+         * Update the input data pointer and samples to output
+         */
+        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples); /* Update samples to output */
+    }
+
+
+    /*
+      * Update the sample count and input pointer
+     */
+    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);      /* Update the count of samples */
+    pInstance->pInputSamples     = pStart;                                                      /* Update input sample pointer */
+
+
+    /*
+     * Save samples to the delay buffer if any left unprocessed
+     */
+    if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
+        (pBuffer->BufferState == LVM_LASTCALL))
+    {
+        NumSamples = pInstance->SamplesToProcess;
+        pStart     = pBuffer->pScratch;                             /* Start of the buffer */
+        pStart    += NumChannels*SampleCount;                       /* Offset by the number of processed samples */
+        if (NumSamples != 0)
+        {
+            Copy_16(pStart,                                         /* Source */
+                    &pBuffer->InDelayBuffer[0],                     /* Destination */
+                    (LVM_INT16)(NumChannels*NumSamples));           /* Number of input samples */
+        }
+
+
+        /*
+         * Update the delay sample count
+         */
+        pBuffer->InDelaySamples     = NumSamples;                   /* Number of delay sample pairs */
+        pInstance->SamplesToProcess = 0;                            /* All Samples used */
+    }
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferUnmanagedIn                                      */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    This mode is selected by the user code and disables the buffer management with the */
+/*  exception of the maximum block size processing. The user must ensure that the       */
+/*  input and output buffers are 32-bit aligned and also that the number of samples to  */
+/*    process is a correct multiple of samples.                                         */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        -    Instance handle                                             */
+/*  *pToProcess        -    Pointer to the start of data processing                     */
+/*  *pProcessed        -    Pointer to the destination of the processed data            */
+/*    pNumSamples        -    Pointer to the number of samples to process               */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
+                           LVM_INT16        **pToProcess,
+                           LVM_INT16        **pProcessed,
+                           LVM_UINT16       *pNumSamples)
+{
+
+    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
+
+
+    /*
+     * Check if this is the first call of a block
+     */
+    if (pInstance->SamplesToProcess == 0)
+    {
+        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;       /* Get the number of samples on first call */
+        pInstance->pInputSamples    = *pToProcess;                   /* Get the I/O pointers */
+        pInstance->pOutputSamples    = *pProcessed;
+
+
+        /*
+         * Set te block size to process
+         */
+        if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+        {
+            *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+        }
+        else
+        {
+            *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+        }
+    }
+
+    /*
+     * Set the process pointers
+     */
+    *pToProcess = pInstance->pInputSamples;
+    *pProcessed = pInstance->pOutputSamples;
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferOptimisedIn                                      */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Optimised buffer management for the case where the data is outplace processing,   */
+/*    the output data is 32-bit aligned and there are sufficient samples to allow some  */
+/*    processing directly in the output buffer. This saves one data copy per sample     */
+/*    compared with the unoptimsed version.                                             */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        -    Instance handle                                             */
+/*    pInData            -    Pointer to the input data stream                          */
+/*  *pToProcess        -    Pointer to the start of data processing                     */
+/*  *pProcessed        -    Pointer to the destination of the processed data            */
+/*    pNumSamples        -    Pointer to the number of samples to process               */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferOptimisedIn(LVM_Handle_t         hInstance,
+                           const LVM_INT16      *pInData,
+                           LVM_INT16            **pToProcess,
+                           LVM_INT16            **pProcessed,
+                           LVM_UINT16           *pNumSamples)
+{
+
+    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
+    LVM_Buffer_t     *pBuffer    = pInstance->pBufferManagement;
+    LVM_INT16        *pDest;
+    LVM_INT16        SampleCount;
+    LVM_INT16        NumSamples;
+    LVM_INT16        NumFrames;
+
+    /*
+     * Check if it is the first call for this block
+     */
+    if (pInstance->SamplesToProcess == 0)
+    {
+        /*
+         * First call for a new block of samples
+         */
+        pBuffer->BufferState = LVM_FIRSTCALL;
+        pInstance->pInputSamples    = (LVM_INT16 *)pInData;
+        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;
+        pBuffer->SamplesToOutput    = (LVM_INT16)*pNumSamples;
+        pDest = *pProcessed;                                    /* The start of the output buffer */
+
+
+        /*
+         * Copy the already processed samples to the output buffer
+         */
+        if (pBuffer->OutDelaySamples != 0)
+        {
+            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
+                    pDest,                                          /* Detsination */
+                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
+            pDest += 2 * pBuffer->OutDelaySamples;                  /* Update the output pointer */
+            pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - pBuffer->OutDelaySamples); /* Update the numbr of samples to output */
+        }
+        *pToProcess = pDest;                                    /* Set the address to start processing */
+        *pProcessed = pDest;                                    /* Process in the output buffer, now inplace */
+
+        /*
+         * Copy the input delay buffer (unprocessed) samples to the output buffer
+         */
+        if (pBuffer->InDelaySamples != 0)
+        {
+            Copy_16(&pBuffer->InDelayBuffer[0],                     /* Source */
+                    pDest,                                          /* Destination */
+                    (LVM_INT16)(2*pBuffer->InDelaySamples));        /* Number of delay samples */
+            pDest += 2 * pBuffer->InDelaySamples;                   /* Update the output pointer */
+        }
+
+
+        /*
+         * Calculate how many input samples to process and copy
+         */
+        NumSamples    = (LVM_INT16)(*pNumSamples - pBuffer->OutDelaySamples);  /* Number that will fit in the output buffer */
+        if (NumSamples >= pInstance->InternalBlockSize)
+        {
+            NumSamples = pInstance->InternalBlockSize;
+        }
+        NumFrames      = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+        SampleCount   = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+        *pNumSamples  = (LVM_UINT16)SampleCount;                                        /* The number of samples to process */
+        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Update the number of samples to output */
+        SampleCount   = (LVM_INT16)(SampleCount - pBuffer->InDelaySamples);             /* The number of samples to copy from the input */
+
+
+        /*
+         * Copy samples from the input buffer and update counts and pointers
+         */
+        Copy_16(pInstance->pInputSamples,                           /* Source */
+                pDest,                                              /* Destination */
+                (LVM_INT16)(2*SampleCount));                        /* Number of input samples */
+        pInstance->pInputSamples += 2 * SampleCount;                /* Update the input pointer */
+        pInstance->pOutputSamples = pDest + (2 * SampleCount);      /* Update the output pointer */
+        pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
+    }
+    else
+    {
+        /*
+         * Second or subsequent call in optimised mode
+         */
+        if (pBuffer->SamplesToOutput >= MIN_INTERNAL_BLOCKSIZE)
+        {
+            /*
+             * More samples can be processed directly in the output buffer
+             */
+            *pToProcess = pInstance->pOutputSamples;                /* Set the address to start processing */
+            *pProcessed = pInstance->pOutputSamples;                /* Process in the output buffer, now inplace */
+            NumSamples  = pBuffer->SamplesToOutput;                 /* Number that will fit in the output buffer */
+            if (NumSamples >= pInstance->InternalBlockSize)
+            {
+                NumSamples = pInstance->InternalBlockSize;
+            }
+            NumFrames      = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+            SampleCount   = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+            *pNumSamples  = (LVM_UINT16)SampleCount;            /* The number of samples to process */
+
+
+            /*
+             * Copy samples from the input buffer and update counts and pointers
+             */
+            Copy_16(pInstance->pInputSamples,                       /* Source */
+                    pInstance->pOutputSamples,                      /* Destination */
+                    (LVM_INT16)(2*SampleCount));                    /* Number of input samples */
+            pInstance->pInputSamples += 2 * SampleCount;            /* Update the input pointer */
+            pInstance->pOutputSamples += 2 * SampleCount;           /* Update the output pointer */
+            pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);   /* Samples left in the input buffer */
+            pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount);         /* Number that will fit in the output buffer */
+        }
+        else
+        {
+            /*
+             * The remaining samples can not be processed in the output buffer
+             */
+            pBuffer->BufferState = LVM_LASTCALL;                    /* Indicate this is the last bock to process */
+            *pToProcess  = pBuffer->pScratch;                       /* Set the address to start processing */
+            *pProcessed  = pBuffer->pScratch;                       /* Process in the output buffer, now inplace */
+            NumSamples   = pInstance->SamplesToProcess;             /* Number left to be processed */
+            NumFrames     = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+            SampleCount  = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+            *pNumSamples = (LVM_UINT16)SampleCount;                /* The number of samples to process */
+
+
+            /*
+             * Copy samples from the input buffer and update counts and pointers
+             */
+            Copy_16(pInstance->pInputSamples,                       /* Source */
+                    pBuffer->pScratch,                              /* Destination */
+                    (LVM_INT16)(2*SampleCount));                    /* Number of input samples */
+            pInstance->pInputSamples += 2 * SampleCount;            /* Update the input pointer */
+            pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
+        }
+    }
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferIn                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    This function manages the data input, it has the following features:              */
+/*        - Accepts data in 16-bit aligned memory                                       */
+/*        - Copies the data to 32-bit aligned memory                                    */
+/*        - Converts Mono inputs to Mono-in-Stereo                                      */
+/*        - Accepts any number of samples as input, except 0                            */
+/*        - Breaks the input sample stream in to blocks of the configured frame size or */
+/*          multiples of the frame size                                                 */
+/*        - Limits the processing block size to the maximum block size.                 */
+/*        - Works with inplace or outplace processing automatically                     */
+/*                                                                                      */
+/*  To manage the data the function has a number of operating states:                   */
+/*        LVM_FIRSTCALL        - The first call for this block of input samples         */
+/*        LVM_MAXBLOCKCALL    - The current block is the maximum size. Only used for the */
+/*                              second and subsequent blocks.                           */
+/*        LVM_LASTCALL        - The last call for this block of input samples           */
+/*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
+/*                              samples, this occurs when the number of samples to      */
+/*                              process is less than the maximum block size.            */
+/*                                                                                      */
+/*    The function uses an internal delay buffer the size of the minimum frame, this is */
+/*  used to temporarily hold samples when the number of samples to process is not a     */
+/*  multiple of the frame size.                                                         */
+/*                                                                                      */
+/*    To ensure correct operation with inplace buffering the number of samples to output*/
+/*  per call is calculated in this function and is set to the number of samples read    */
+/*  from the input buffer.                                                              */
+/*                                                                                      */
+/*    The total number of samples to process is stored when the function is called for  */
+/*  the first time. The value is overwritten by the size of the block to be processed   */
+/*  in each call so the size of the processing blocks can be controlled. The number of  */
+/*    samples actually processed for each block of input samples is always a multiple of*/
+/*  the frame size so for any particular block of input samples the actual number of    */
+/*  processed samples may not match the number of input samples, sometime it will be    */
+/*  sometimes less. The average is the same and the difference is never more than the   */
+/*  frame size.                                                                         */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        -    Instance handle                                             */
+/*    pInData            -    Pointer to the input data stream                          */
+/*  *pToProcess        -    Pointer to the start of data processing                     */
+/*  *pProcessed        -    Pointer to the destination of the processed data            */
+/*    pNumSamples        -    Pointer to the number of samples to process               */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferIn(LVM_Handle_t      hInstance,
+                  const LVM_INT16   *pInData,
+                  LVM_INT16         **pToProcess,
+                  LVM_INT16         **pProcessed,
+                  LVM_UINT16        *pNumSamples)
+{
+
+    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
+
+
+    /*
+     * Check which mode, managed or unmanaged
+     */
+    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        LVM_BufferManagedIn(hInstance,
+                            pInData,
+                            pToProcess,
+                            pProcessed,
+                            pNumSamples);
+    }
+    else
+    {
+        LVM_BufferUnmanagedIn(hInstance,
+                              pToProcess,
+                              pProcessed,
+                              pNumSamples);
+    }
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferManagedOut                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Full buffer management output. This works in conjunction with the managed input     */
+/*  routine and ensures the correct number of samples are always output to the output   */
+/*  buffer.                                                                             */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        - Instance handle                                                */
+/*    pOutData        - Pointer to the output data stream                               */
+/*    pNumSamples        - Pointer to the number of samples to process                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
+                          LVM_INT16            *pOutData,
+                          LVM_UINT16        *pNumSamples)
+{
+
+    LVM_Instance_t  *pInstance  = (LVM_Instance_t  *)hInstance;
+    LVM_Buffer_t    *pBuffer    = pInstance->pBufferManagement;
+    LVM_INT16       SampleCount = (LVM_INT16)*pNumSamples;
+    LVM_INT16       NumSamples;
+    LVM_INT16       *pStart;
+    LVM_INT16       *pDest;
+
+
+    /*
+     * Set the pointers
+     */
+    NumSamples = pBuffer->SamplesToOutput;
+    pStart     = pBuffer->pScratch;
+
+
+    /*
+     * check if it is the first call of a block
+      */
+    if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
+        (pBuffer->BufferState == LVM_FIRSTLASTCALL))
+    {
+        /* First call for a new block */
+        pInstance->pOutputSamples = pOutData;                        /* Initialise the destination */
+    }
+    pDest = pInstance->pOutputSamples;                               /* Set the output address */
+
+
+    /*
+     * If the number of samples is non-zero then there are still samples to send to
+     * the output buffer
+     */
+    if ((NumSamples != 0) &&
+        (pBuffer->OutDelaySamples != 0))
+    {
+        /*
+         * Copy the delayed output buffer samples to the output
+         */
+        if (pBuffer->OutDelaySamples <= NumSamples)
+        {
+            /*
+             * Copy all output delay samples to the output
+             */
+            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
+                    pDest,                                          /* Detsination */
+                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
+
+            /*
+             * Update the pointer and sample counts
+             */
+            pDest += 2*pBuffer->OutDelaySamples;                                /* Output sample pointer */
+            NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples);    /* Samples left to send */
+            pBuffer->OutDelaySamples = 0;                                       /* No samples left in the buffer */
+
+        }
+        else
+        {
+            /*
+             * Copy only some of the ouput delay samples to the output
+             */
+            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
+                    pDest,                                          /* Detsination */
+                    (LVM_INT16)(2*NumSamples));                     /* Number of delay samples */
+
+            /*
+             * Update the pointer and sample counts
+             */
+            pDest += 2*NumSamples;                                                              /* Output sample pointer */
+            pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);      /* No samples left in the buffer */
+
+
+            /*
+             * Realign the delay buffer data to avoid using circular buffer management
+             */
+            Copy_16(&pBuffer->OutDelayBuffer[2*NumSamples],         /* Source */
+                    &pBuffer->OutDelayBuffer[0],                    /* Destination */
+                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of samples to move */
+            NumSamples = 0;                                         /* Samples left to send */
+        }
+    }
+
+
+    /*
+     * Copy the processed results to the output
+     */
+    if ((NumSamples != 0) &&
+        (SampleCount != 0))
+    {
+        if (SampleCount <= NumSamples)
+        {
+            /*
+             * Copy all processed samples to the output
+             */
+            Copy_16(pStart,                                      /* Source */
+                    pDest,                                       /* Detsination */
+                    (LVM_INT16)(2*SampleCount));                 /* Number of processed samples */
+
+            /*
+             * Update the pointer and sample counts
+             */
+            pDest      += 2 * SampleCount;                          /* Output sample pointer */
+            NumSamples  = (LVM_INT16)(NumSamples - SampleCount);    /* Samples left to send */
+            SampleCount = 0;                                        /* No samples left in the buffer */
+        }
+        else
+        {
+            /*
+             * Copy only some processed samples to the output
+             */
+            Copy_16(pStart,                                         /* Source */
+                    pDest,                                          /* Destination */
+                    (LVM_INT16)(2*NumSamples));                     /* Number of processed samples */
+
+
+            /*
+             * Update the pointers and sample counts
+               */
+            pStart      += 2 * NumSamples;                          /* Processed sample pointer */
+            pDest        += 2 * NumSamples;                         /* Output sample pointer */
+            SampleCount  = (LVM_INT16)(SampleCount - NumSamples);   /* Processed samples left */
+            NumSamples   = 0;                                       /* Clear the sample count */
+        }
+    }
+
+
+    /*
+     * Copy the remaining processed data to the output delay buffer
+     */
+    if (SampleCount != 0)
+    {
+        Copy_16(pStart,                                                 /* Source */
+                &pBuffer->OutDelayBuffer[2*pBuffer->OutDelaySamples],   /* Destination */
+                (LVM_INT16)(2*SampleCount));                            /* Number of processed samples */
+        pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount); /* Update the buffer count */
+    }
+
+
+    /*
+     * pointers, counts and set default buffer processing
+     */
+    pBuffer->SamplesToOutput  = NumSamples;                         /* Samples left to send */
+    pInstance->pOutputSamples = pDest;                              /* Output sample pointer */
+    pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call block size */
+    *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;         /* This will terminate the loop when all samples processed */
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferUnmanagedOut                                     */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This works in conjunction with the unmanaged input routine and updates the number   */
+/*    of samples left to be processed    and adjusts the buffer pointers.               */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        - Instance handle                                                */
+/*    pNumSamples        - Pointer to the number of samples to process                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferUnmanagedOut(LVM_Handle_t        hInstance,
+                            LVM_UINT16          *pNumSamples)
+{
+
+    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
+    LVM_INT16           NumChannels =2;
+
+
+    /*
+     * Update sample counts
+     */
+    pInstance->pInputSamples    += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
+    pInstance->pOutputSamples   += (LVM_INT16)(*pNumSamples * 2);
+    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
+
+    /*
+     * Set te block size to process
+     */
+    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+    {
+        *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+    }
+    else
+    {
+        *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+    }
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferOptimisedOut                                     */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This works in conjunction with the optimised input routine and copies the last few  */
+/*  processed and unprocessed samples to their respective buffers.                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        - Instance handle                                                */
+/*    pNumSamples        - Pointer to the number of samples to process                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferOptimisedOut(LVM_Handle_t    hInstance,
+                            LVM_UINT16        *pNumSamples)
+{
+
+    LVM_Instance_t      *pInstance = (LVM_Instance_t  *)hInstance;
+    LVM_Buffer_t        *pBuffer   = pInstance->pBufferManagement;
+
+    /*
+     * Check if it is the last block to process
+     */
+    if (pBuffer->BufferState == LVM_LASTCALL)
+    {
+        LVM_INT16    *pSrc = pBuffer->pScratch;
+
+        /*
+         * Copy the unprocessed samples to the input delay buffer
+         */
+        if (pInstance->SamplesToProcess != 0)
+        {
+            Copy_16(pInstance->pInputSamples,                       /* Source */
+                    &pBuffer->InDelayBuffer[0],                     /* Destination */
+                    (LVM_INT16)(2*pInstance->SamplesToProcess));    /* Number of input samples */
+            pBuffer->InDelaySamples = pInstance->SamplesToProcess;
+            pInstance->SamplesToProcess = 0;
+        }
+        else
+        {
+            pBuffer->InDelaySamples = 0;
+        }
+
+
+        /*
+         * Fill the last empty spaces in the output buffer
+         */
+        if (pBuffer->SamplesToOutput != 0)
+        {
+            Copy_16(pSrc,                                           /* Source */
+                    pInstance->pOutputSamples,                      /* Destination */
+                    (LVM_INT16)(2*pBuffer->SamplesToOutput));       /* Number of input samples */
+            *pNumSamples = (LVM_UINT16)(*pNumSamples - pBuffer->SamplesToOutput);
+            pSrc += 2 * pBuffer->SamplesToOutput;                  /* Update scratch pointer */
+            pBuffer->SamplesToOutput = 0;                          /* No more samples in this block */
+        }
+
+
+        /*
+         * Save any remaining processed samples in the output delay buffer
+         */
+        if (*pNumSamples != 0)
+        {
+            Copy_16(pSrc,                                           /* Source */
+                    &pBuffer->OutDelayBuffer[0],                    /* Destination */
+                    (LVM_INT16)(2**pNumSamples));                   /* Number of input samples */
+
+            pBuffer->OutDelaySamples = (LVM_INT16)*pNumSamples;
+
+            *pNumSamples = 0;                                      /* No more samples in this block */
+        }
+        else
+        {
+            pBuffer->OutDelaySamples = 0;
+        }
+    }
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVM_BufferOut                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function manages the data output, it has the following features:               */
+/*        - Output data to 16-bit aligned memory                                        */
+/*        - Reads data from 32-bit aligned memory                                       */
+/*        - Reads data only in blocks of frame size or multiples of frame size          */
+/*        - Writes the same number of samples as the LVM_BufferIn function reads        */
+/*        - Works with inplace or outplace processing automatically                     */
+/*                                                                                      */
+/*  To manage the data the function has a number of operating states:                   */
+/*        LVM_FIRSTCALL        - The first call for this block of input samples         */
+/*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
+/*                              samples, this occurs when the number of samples to      */
+/*                              process is less than the maximum block size.            */
+/*                                                                                      */
+/*    The function uses an internal delay buffer the size of the minimum frame, this is */
+/*  used to temporarily hold samples when the number of samples to write is not a       */
+/*  multiple of the frame size.                                                         */
+/*                                                                                      */
+/*    To ensure correct operation with inplace buffering the number of samples to output*/
+/*  per call is always the same as the number of samples read from the input buffer.    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    hInstance        - Instance handle                                                */
+/*    pOutData        - Pointer to the output data stream                               */
+/*    pNumSamples        - Pointer to the number of samples to process                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void LVM_BufferOut(LVM_Handle_t     hInstance,
+                   LVM_INT16        *pOutData,
+                   LVM_UINT16       *pNumSamples)
+{
+
+    LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
+
+
+    /*
+     * Check which mode, managed or unmanaged
+     */
+    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        LVM_BufferManagedOut(hInstance,
+                             pOutData,
+                             pNumSamples);
+    }
+    else
+    {
+        LVM_BufferUnmanagedOut(hInstance,
+                               pNumSamples);
+    }
+}
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
new file mode 100755
index 0000000..f578db9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
@@ -0,0 +1,573 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 __LVM_COEFFS_H__
+#define __LVM_COEFFS_H__
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* High Pass Shelving Filter coefficients                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+#define TrebleBoostCorner                                  8000
+#define TrebleBoostMinRate                                     4
+#define TrebleBoostSteps                                    15
+
+
+/* Coefficients for sample rate 22050Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs22050_Gain1_A0                             5383         /* Floating point value 0.164291 */
+#define HPF_Fs22050_Gain1_A1                            16859         /* Floating point value 0.514492 */
+#define HPF_Fs22050_Gain1_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain1_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain1_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain1_Shift                             1         /* Shift value */
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs22050_Gain2_A0                             4683         /* Floating point value 0.142925 */
+#define HPF_Fs22050_Gain2_A1                            17559         /* Floating point value 0.535858 */
+#define HPF_Fs22050_Gain2_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain2_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain2_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain2_Shift                             1         /* Shift value */
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs22050_Gain3_A0                             3898         /* Floating point value 0.118953 */
+#define HPF_Fs22050_Gain3_A1                            18345         /* Floating point value 0.559830 */
+#define HPF_Fs22050_Gain3_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain3_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain3_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain3_Shift                             1         /* Shift value */
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs22050_Gain4_A0                             3016         /* Floating point value 0.092055 */
+#define HPF_Fs22050_Gain4_A1                            19226         /* Floating point value 0.586728 */
+#define HPF_Fs22050_Gain4_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain4_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain4_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain4_Shift                             1         /* Shift value */
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs22050_Gain5_A0                             2028         /* Floating point value 0.061876 */
+#define HPF_Fs22050_Gain5_A1                            20215         /* Floating point value 0.616907 */
+#define HPF_Fs22050_Gain5_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain5_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain5_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain5_Shift                             1         /* Shift value */
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs22050_Gain6_A0                              918         /* Floating point value 0.028013 */
+#define HPF_Fs22050_Gain6_A1                            21324         /* Floating point value 0.650770 */
+#define HPF_Fs22050_Gain6_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain6_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain6_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain6_Shift                             1         /* Shift value */
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs22050_Gain7_A0                             -164         /* Floating point value -0.005002 */
+#define HPF_Fs22050_Gain7_A1                            11311         /* Floating point value 0.345199 */
+#define HPF_Fs22050_Gain7_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain7_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain7_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain7_Shift                             2         /* Shift value */
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs22050_Gain8_A0                             -864         /* Floating point value -0.026368 */
+#define HPF_Fs22050_Gain8_A1                            12012         /* Floating point value 0.366565 */
+#define HPF_Fs22050_Gain8_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain8_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain8_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain8_Shift                             2         /* Shift value */
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs22050_Gain9_A0                            -1650         /* Floating point value -0.050340 */
+#define HPF_Fs22050_Gain9_A1                            12797         /* Floating point value 0.390537 */
+#define HPF_Fs22050_Gain9_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain9_B1                            12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain9_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain9_Shift                             2         /* Shift value */
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs22050_Gain10_A0                           -2531         /* Floating point value -0.077238 */
+#define HPF_Fs22050_Gain10_A1                           13679         /* Floating point value 0.417435 */
+#define HPF_Fs22050_Gain10_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain10_B1                           12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain10_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain10_Shift                            2         /* Shift value */
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs22050_Gain11_A0                           -3520         /* Floating point value -0.107417 */
+#define HPF_Fs22050_Gain11_A1                           14667         /* Floating point value 0.447615 */
+#define HPF_Fs22050_Gain11_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain11_B1                           12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain11_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain11_Shift                            2         /* Shift value */
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs22050_Gain12_A0                           -4629         /* Floating point value -0.141279 */
+#define HPF_Fs22050_Gain12_A1                           15777         /* Floating point value 0.481477 */
+#define HPF_Fs22050_Gain12_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain12_B1                           12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain12_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain12_Shift                            2         /* Shift value */
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs22050_Gain13_A0                           -2944         /* Floating point value -0.089849 */
+#define HPF_Fs22050_Gain13_A1                            8531         /* Floating point value 0.260352 */
+#define HPF_Fs22050_Gain13_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain13_B1                           12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain13_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain13_Shift                            3         /* Shift value */
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs22050_Gain14_A0                           -3644         /* Floating point value -0.111215 */
+#define HPF_Fs22050_Gain14_A1                            9231         /* Floating point value 0.281718 */
+#define HPF_Fs22050_Gain14_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain14_B1                           12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain14_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain14_Shift                            3         /* Shift value */
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs22050_Gain15_A0                           -4430         /* Floating point value -0.135187 */
+#define HPF_Fs22050_Gain15_A1                           10017         /* Floating point value 0.305690 */
+#define HPF_Fs22050_Gain15_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain15_B1                           12125         /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain15_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain15_Shift                            3         /* Shift value */
+
+
+/* Coefficients for sample rate 24000Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs24000_Gain1_A0                             3625         /* Floating point value 0.110628 */
+#define HPF_Fs24000_Gain1_A1                            16960         /* Floating point value 0.517578 */
+#define HPF_Fs24000_Gain1_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain1_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain1_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain1_Shift                             1         /* Shift value */
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs24000_Gain2_A0                             2811         /* Floating point value 0.085800 */
+#define HPF_Fs24000_Gain2_A1                            17774         /* Floating point value 0.542406 */
+#define HPF_Fs24000_Gain2_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain2_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain2_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain2_Shift                             1         /* Shift value */
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs24000_Gain3_A0                             1899         /* Floating point value 0.057943 */
+#define HPF_Fs24000_Gain3_A1                            18686         /* Floating point value 0.570263 */
+#define HPF_Fs24000_Gain3_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain3_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain3_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain3_Shift                             1         /* Shift value */
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs24000_Gain4_A0                              874         /* Floating point value 0.026687 */
+#define HPF_Fs24000_Gain4_A1                            19711         /* Floating point value 0.601519 */
+#define HPF_Fs24000_Gain4_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain4_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain4_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain4_Shift                             1         /* Shift value */
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs24000_Gain5_A0                             -275         /* Floating point value -0.008383 */
+#define HPF_Fs24000_Gain5_A1                            20860         /* Floating point value 0.636589 */
+#define HPF_Fs24000_Gain5_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain5_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain5_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain5_Shift                             1         /* Shift value */
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs24000_Gain6_A0                            -1564         /* Floating point value -0.047733 */
+#define HPF_Fs24000_Gain6_A1                            22149         /* Floating point value 0.675938 */
+#define HPF_Fs24000_Gain6_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain6_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain6_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain6_Shift                             1         /* Shift value */
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs24000_Gain7_A0                            -1509         /* Floating point value -0.046051 */
+#define HPF_Fs24000_Gain7_A1                            11826         /* Floating point value 0.360899 */
+#define HPF_Fs24000_Gain7_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain7_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain7_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain7_Shift                             2         /* Shift value */
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs24000_Gain8_A0                            -2323         /* Floating point value -0.070878 */
+#define HPF_Fs24000_Gain8_A1                            12640         /* Floating point value 0.385727 */
+#define HPF_Fs24000_Gain8_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain8_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain8_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain8_Shift                             2         /* Shift value */
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs24000_Gain9_A0                            -3235         /* Floating point value -0.098736 */
+#define HPF_Fs24000_Gain9_A1                            13552         /* Floating point value 0.413584 */
+#define HPF_Fs24000_Gain9_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain9_B1                             8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain9_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain9_Shift                             2         /* Shift value */
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs24000_Gain10_A0                           -4260         /* Floating point value -0.129992 */
+#define HPF_Fs24000_Gain10_A1                           14577         /* Floating point value 0.444841 */
+#define HPF_Fs24000_Gain10_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain10_B1                            8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain10_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain10_Shift                            2         /* Shift value */
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs24000_Gain11_A0                           -5409         /* Floating point value -0.165062 */
+#define HPF_Fs24000_Gain11_A1                           15726         /* Floating point value 0.479911 */
+#define HPF_Fs24000_Gain11_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain11_B1                            8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain11_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain11_Shift                            2         /* Shift value */
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs24000_Gain12_A0                           -6698         /* Floating point value -0.204411 */
+#define HPF_Fs24000_Gain12_A1                           17015         /* Floating point value 0.519260 */
+#define HPF_Fs24000_Gain12_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain12_B1                            8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain12_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain12_Shift                            2         /* Shift value */
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs24000_Gain13_A0                           -4082         /* Floating point value -0.124576 */
+#define HPF_Fs24000_Gain13_A1                            9253         /* Floating point value 0.282374 */
+#define HPF_Fs24000_Gain13_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain13_B1                            8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain13_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain13_Shift                            3         /* Shift value */
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs24000_Gain14_A0                           -4896         /* Floating point value -0.149404 */
+#define HPF_Fs24000_Gain14_A1                           10066         /* Floating point value 0.307202 */
+#define HPF_Fs24000_Gain14_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain14_B1                            8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain14_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain14_Shift                            3         /* Shift value */
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs24000_Gain15_A0                           -5808         /* Floating point value -0.177261 */
+#define HPF_Fs24000_Gain15_A1                           10979         /* Floating point value 0.335059 */
+#define HPF_Fs24000_Gain15_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain15_B1                            8780         /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain15_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain15_Shift                            3         /* Shift value */
+
+
+/* Coefficients for sample rate 32000Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs32000_Gain1_A0                            17225         /* Floating point value 0.525677 */
+#define HPF_Fs32000_Gain1_A1                             -990         /* Floating point value -0.030227 */
+#define HPF_Fs32000_Gain1_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain1_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain1_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain1_Shift                             1         /* Shift value */
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs32000_Gain2_A0                            18337         /* Floating point value 0.559593 */
+#define HPF_Fs32000_Gain2_A1                            -2102         /* Floating point value -0.064142 */
+#define HPF_Fs32000_Gain2_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain2_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain2_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain2_Shift                             1         /* Shift value */
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs32000_Gain3_A0                            19584         /* Floating point value 0.597646 */
+#define HPF_Fs32000_Gain3_A1                            -3349         /* Floating point value -0.102196 */
+#define HPF_Fs32000_Gain3_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain3_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain3_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain3_Shift                             1         /* Shift value */
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs32000_Gain4_A0                            20983         /* Floating point value 0.640343 */
+#define HPF_Fs32000_Gain4_A1                            -4748         /* Floating point value -0.144893 */
+#define HPF_Fs32000_Gain4_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain4_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain4_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain4_Shift                             1         /* Shift value */
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs32000_Gain5_A0                            22553         /* Floating point value 0.688250 */
+#define HPF_Fs32000_Gain5_A1                            -6318         /* Floating point value -0.192799 */
+#define HPF_Fs32000_Gain5_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain5_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain5_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain5_Shift                             1         /* Shift value */
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs32000_Gain6_A0                            24314         /* Floating point value 0.742002 */
+#define HPF_Fs32000_Gain6_A1                            -8079         /* Floating point value -0.246551 */
+#define HPF_Fs32000_Gain6_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain6_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain6_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain6_Shift                             1         /* Shift value */
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs32000_Gain7_A0                            13176         /* Floating point value 0.402109 */
+#define HPF_Fs32000_Gain7_A1                            -5040         /* Floating point value -0.153795 */
+#define HPF_Fs32000_Gain7_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain7_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain7_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain7_Shift                             2         /* Shift value */
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs32000_Gain8_A0                            14288         /* Floating point value 0.436024 */
+#define HPF_Fs32000_Gain8_A1                            -6151         /* Floating point value -0.187711 */
+#define HPF_Fs32000_Gain8_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain8_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain8_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain8_Shift                             2         /* Shift value */
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs32000_Gain9_A0                            15535         /* Floating point value 0.474078 */
+#define HPF_Fs32000_Gain9_A1                            -7398         /* Floating point value -0.225764 */
+#define HPF_Fs32000_Gain9_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain9_B1                                0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain9_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain9_Shift                             2         /* Shift value */
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs32000_Gain10_A0                           16934         /* Floating point value 0.516774 */
+#define HPF_Fs32000_Gain10_A1                           -8797         /* Floating point value -0.268461 */
+#define HPF_Fs32000_Gain10_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain10_B1                               0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain10_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain10_Shift                            2         /* Shift value */
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs32000_Gain11_A0                           18503         /* Floating point value 0.564681 */
+#define HPF_Fs32000_Gain11_A1                          -10367         /* Floating point value -0.316368 */
+#define HPF_Fs32000_Gain11_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain11_B1                               0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain11_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain11_Shift                            2         /* Shift value */
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs32000_Gain12_A0                           20265         /* Floating point value 0.618433 */
+#define HPF_Fs32000_Gain12_A1                          -12128         /* Floating point value -0.370120 */
+#define HPF_Fs32000_Gain12_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain12_B1                               0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain12_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain12_Shift                            2         /* Shift value */
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs32000_Gain13_A0                           11147         /* Floating point value 0.340178 */
+#define HPF_Fs32000_Gain13_A1                           -7069         /* Floating point value -0.215726 */
+#define HPF_Fs32000_Gain13_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain13_B1                               0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain13_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain13_Shift                            3         /* Shift value */
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs32000_Gain14_A0                           12258         /* Floating point value 0.374093 */
+#define HPF_Fs32000_Gain14_A1                           -8180         /* Floating point value -0.249642 */
+#define HPF_Fs32000_Gain14_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain14_B1                               0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain14_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain14_Shift                            3         /* Shift value */
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs32000_Gain15_A0                           13505         /* Floating point value 0.412147 */
+#define HPF_Fs32000_Gain15_A1                           -9427         /* Floating point value -0.287695 */
+#define HPF_Fs32000_Gain15_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain15_B1                               0         /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain15_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain15_Shift                            3         /* Shift value */
+
+
+/* Coefficients for sample rate 44100Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs44100_Gain1_A0                            17442         /* Floating point value 0.532294 */
+#define HPF_Fs44100_Gain1_A1                            -4761         /* Floating point value -0.145294 */
+#define HPF_Fs44100_Gain1_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain1_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain1_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain1_Shift                             1         /* Shift value */
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs44100_Gain2_A0                            18797         /* Floating point value 0.573633 */
+#define HPF_Fs44100_Gain2_A1                            -6116         /* Floating point value -0.186634 */
+#define HPF_Fs44100_Gain2_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain2_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain2_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain2_Shift                             1         /* Shift value */
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs44100_Gain3_A0                            20317         /* Floating point value 0.620016 */
+#define HPF_Fs44100_Gain3_A1                            -7635         /* Floating point value -0.233017 */
+#define HPF_Fs44100_Gain3_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain3_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain3_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain3_Shift                             1         /* Shift value */
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs44100_Gain4_A0                            22022         /* Floating point value 0.672059 */
+#define HPF_Fs44100_Gain4_A1                            -9341         /* Floating point value -0.285060 */
+#define HPF_Fs44100_Gain4_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain4_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain4_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain4_Shift                             1         /* Shift value */
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs44100_Gain5_A0                            23935         /* Floating point value 0.730452 */
+#define HPF_Fs44100_Gain5_A1                           -11254         /* Floating point value -0.343453 */
+#define HPF_Fs44100_Gain5_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain5_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain5_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain5_Shift                             1         /* Shift value */
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs44100_Gain6_A0                            26082         /* Floating point value 0.795970 */
+#define HPF_Fs44100_Gain6_A1                           -13401         /* Floating point value -0.408971 */
+#define HPF_Fs44100_Gain6_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain6_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain6_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain6_Shift                             1         /* Shift value */
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs44100_Gain7_A0                            14279         /* Floating point value 0.435774 */
+#define HPF_Fs44100_Gain7_A1                            -7924         /* Floating point value -0.241815 */
+#define HPF_Fs44100_Gain7_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain7_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain7_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain7_Shift                             2         /* Shift value */
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs44100_Gain8_A0                            15634         /* Floating point value 0.477113 */
+#define HPF_Fs44100_Gain8_A1                            -9278         /* Floating point value -0.283154 */
+#define HPF_Fs44100_Gain8_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain8_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain8_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain8_Shift                             2         /* Shift value */
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs44100_Gain9_A0                            17154         /* Floating point value 0.523496 */
+#define HPF_Fs44100_Gain9_A1                           -10798         /* Floating point value -0.329537 */
+#define HPF_Fs44100_Gain9_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain9_B1                            -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain9_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain9_Shift                             2         /* Shift value */
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs44100_Gain10_A0                           18859         /* Floating point value 0.575539 */
+#define HPF_Fs44100_Gain10_A1                          -12504         /* Floating point value -0.381580 */
+#define HPF_Fs44100_Gain10_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain10_B1                           -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain10_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain10_Shift                            2         /* Shift value */
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs44100_Gain11_A0                           20773         /* Floating point value 0.633932 */
+#define HPF_Fs44100_Gain11_A1                          -14417         /* Floating point value -0.439973 */
+#define HPF_Fs44100_Gain11_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain11_B1                           -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain11_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain11_Shift                            2         /* Shift value */
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs44100_Gain12_A0                           22920         /* Floating point value 0.699450 */
+#define HPF_Fs44100_Gain12_A1                          -16564         /* Floating point value -0.505491 */
+#define HPF_Fs44100_Gain12_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain12_B1                           -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain12_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain12_Shift                            2         /* Shift value */
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs44100_Gain13_A0                           12694         /* Floating point value 0.387399 */
+#define HPF_Fs44100_Gain13_A1                           -9509         /* Floating point value -0.290189 */
+#define HPF_Fs44100_Gain13_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain13_B1                           -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain13_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain13_Shift                            3         /* Shift value */
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs44100_Gain14_A0                           14049         /* Floating point value 0.428738 */
+#define HPF_Fs44100_Gain14_A1                          -10864         /* Floating point value -0.331528 */
+#define HPF_Fs44100_Gain14_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain14_B1                           -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain14_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain14_Shift                            3         /* Shift value */
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs44100_Gain15_A0                           15569         /* Floating point value 0.475121 */
+#define HPF_Fs44100_Gain15_A1                          -12383         /* Floating point value -0.377912 */
+#define HPF_Fs44100_Gain15_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain15_B1                           -7173         /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain15_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain15_Shift                            3         /* Shift value */
+
+
+/* Coefficients for sample rate 48000Hz */
+                                                                    /* Gain =  1.000000 dB */
+#define HPF_Fs48000_Gain1_A0                            17491         /* Floating point value 0.533777 */
+#define HPF_Fs48000_Gain1_A1                            -5606         /* Floating point value -0.171082 */
+#define HPF_Fs48000_Gain1_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain1_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain1_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain1_Shift                             1         /* Shift value */
+                                                                    /* Gain =  2.000000 dB */
+#define HPF_Fs48000_Gain2_A0                            18900         /* Floating point value 0.576779 */
+#define HPF_Fs48000_Gain2_A1                            -7015         /* Floating point value -0.214085 */
+#define HPF_Fs48000_Gain2_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain2_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain2_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain2_Shift                             1         /* Shift value */
+                                                                    /* Gain =  3.000000 dB */
+#define HPF_Fs48000_Gain3_A0                            20481         /* Floating point value 0.625029 */
+#define HPF_Fs48000_Gain3_A1                            -8596         /* Floating point value -0.262335 */
+#define HPF_Fs48000_Gain3_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain3_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain3_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain3_Shift                             1         /* Shift value */
+                                                                    /* Gain =  4.000000 dB */
+#define HPF_Fs48000_Gain4_A0                            22255         /* Floating point value 0.679167 */
+#define HPF_Fs48000_Gain4_A1                           -10370         /* Floating point value -0.316472 */
+#define HPF_Fs48000_Gain4_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain4_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain4_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain4_Shift                             1         /* Shift value */
+                                                                    /* Gain =  5.000000 dB */
+#define HPF_Fs48000_Gain5_A0                            24245         /* Floating point value 0.739910 */
+#define HPF_Fs48000_Gain5_A1                           -12361         /* Floating point value -0.377215 */
+#define HPF_Fs48000_Gain5_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain5_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain5_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain5_Shift                             1         /* Shift value */
+                                                                    /* Gain =  6.000000 dB */
+#define HPF_Fs48000_Gain6_A0                            26479         /* Floating point value 0.808065 */
+#define HPF_Fs48000_Gain6_A1                           -14594         /* Floating point value -0.445370 */
+#define HPF_Fs48000_Gain6_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain6_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain6_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain6_Shift                             1         /* Shift value */
+                                                                    /* Gain =  7.000000 dB */
+#define HPF_Fs48000_Gain7_A0                            14527         /* Floating point value 0.443318 */
+#define HPF_Fs48000_Gain7_A1                            -8570         /* Floating point value -0.261540 */
+#define HPF_Fs48000_Gain7_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain7_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain7_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain7_Shift                             2         /* Shift value */
+                                                                    /* Gain =  8.000000 dB */
+#define HPF_Fs48000_Gain8_A0                            15936         /* Floating point value 0.486321 */
+#define HPF_Fs48000_Gain8_A1                            -9979         /* Floating point value -0.304543 */
+#define HPF_Fs48000_Gain8_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain8_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain8_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain8_Shift                             2         /* Shift value */
+                                                                    /* Gain =  9.000000 dB */
+#define HPF_Fs48000_Gain9_A0                            17517         /* Floating point value 0.534571 */
+#define HPF_Fs48000_Gain9_A1                           -11560         /* Floating point value -0.352793 */
+#define HPF_Fs48000_Gain9_A2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain9_B1                            -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain9_B2                                0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain9_Shift                             2         /* Shift value */
+                                                                    /* Gain =  10.000000 dB */
+#define HPF_Fs48000_Gain10_A0                           19291         /* Floating point value 0.588708 */
+#define HPF_Fs48000_Gain10_A1                          -13334         /* Floating point value -0.406930 */
+#define HPF_Fs48000_Gain10_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain10_B1                           -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain10_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain10_Shift                            2         /* Shift value */
+                                                                    /* Gain =  11.000000 dB */
+#define HPF_Fs48000_Gain11_A0                           21281         /* Floating point value 0.649452 */
+#define HPF_Fs48000_Gain11_A1                          -15325         /* Floating point value -0.467674 */
+#define HPF_Fs48000_Gain11_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain11_B1                           -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain11_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain11_Shift                            2         /* Shift value */
+                                                                    /* Gain =  12.000000 dB */
+#define HPF_Fs48000_Gain12_A0                           23515         /* Floating point value 0.717607 */
+#define HPF_Fs48000_Gain12_A1                          -17558         /* Floating point value -0.535829 */
+#define HPF_Fs48000_Gain12_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain12_B1                           -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain12_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain12_Shift                            2         /* Shift value */
+                                                                    /* Gain =  13.000000 dB */
+#define HPF_Fs48000_Gain13_A0                           13041         /* Floating point value 0.397982 */
+#define HPF_Fs48000_Gain13_A1                          -10056         /* Floating point value -0.306877 */
+#define HPF_Fs48000_Gain13_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain13_B1                           -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain13_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain13_Shift                            3         /* Shift value */
+                                                                    /* Gain =  14.000000 dB */
+#define HPF_Fs48000_Gain14_A0                           14450         /* Floating point value 0.440984 */
+#define HPF_Fs48000_Gain14_A1                          -11465         /* Floating point value -0.349880 */
+#define HPF_Fs48000_Gain14_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain14_B1                           -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain14_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain14_Shift                            3         /* Shift value */
+                                                                    /* Gain =  15.000000 dB */
+#define HPF_Fs48000_Gain15_A0                           16031         /* Floating point value 0.489234 */
+#define HPF_Fs48000_Gain15_A1                          -13046         /* Floating point value -0.398130 */
+#define HPF_Fs48000_Gain15_A2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain15_B1                           -8780         /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain15_B2                               0         /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain15_Shift                            3         /* Shift value */
+
+
+#endif
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
new file mode 100755
index 0000000..922f77d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
@@ -0,0 +1,1033 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1316 $
+     $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+
+*****************************************************************************************/
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* Includes                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+#include "LVM_Coeffs.h"
+#include "LVM_Tables.h"
+#include "LVM_Private.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:           LVM_SetControlParameters                                         */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the LifeVibes module parameters.                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance          Instance handle                                                  */
+/*  pParams            Pointer to a parameter structure                                 */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS        Succeeded                                                        */
+/*  LVM_NULLADDRESS    When hInstance, pParams or any control pointers are NULL         */
+/*  LVM_OUTOFRANGE     When any of the control parameters are out of range              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t           hInstance,
+                                             LVM_ControlParams_t    *pParams)
+{
+    LVM_Instance_t    *pInstance =(LVM_Instance_t  *)hInstance;
+
+
+    if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    pInstance->NewParams = *pParams;
+
+    if(
+        /* General parameters */
+        ((pParams->OperatingMode != LVM_MODE_OFF) && (pParams->OperatingMode != LVM_MODE_ON))                                         ||
+        ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000)       &&
+        (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000)       &&
+        (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000))      ||
+        ((pParams->SourceFormat != LVM_STEREO) && (pParams->SourceFormat != LVM_MONOINSTEREO) && (pParams->SourceFormat != LVM_MONO)) ||
+        (pParams->SpeakerType > LVM_EX_HEADPHONES))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * Cinema Sound parameters
+     */
+    if((pParams->VirtualizerOperatingMode != LVM_MODE_OFF) && (pParams->VirtualizerOperatingMode != LVM_MODE_ON))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pParams->VirtualizerType != LVM_CONCERTSOUND)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pParams->VirtualizerReverbLevel > LVM_VIRTUALIZER_MAX_REVERB_LEVEL)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pParams->CS_EffectLevel < LVM_CS_MIN_EFFECT_LEVEL)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * N-Band Equalizer
+     */
+    if(pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /* Definition pointer */
+    if ((pParams->pEQNB_BandDefinition == LVM_NULL) &&
+        (pParams->EQNB_NBands != 0))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /*
+     * Copy the filter definitions for the Equaliser
+     */
+    {
+        LVM_INT16           i;
+
+        if (pParams->EQNB_NBands != 0)
+        {
+            for (i=0; i<pParams->EQNB_NBands; i++)
+            {
+                pInstance->pEQNB_BandDefs[i] = pParams->pEQNB_BandDefinition[i];
+            }
+            pInstance->NewParams.pEQNB_BandDefinition = pInstance->pEQNB_BandDefs;
+        }
+    }
+    if( /* N-Band Equaliser parameters */
+        ((pParams->EQNB_OperatingMode != LVM_EQNB_OFF) && (pParams->EQNB_OperatingMode != LVM_EQNB_ON)) ||
+        (pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+    /* Band parameters*/
+    {
+        LVM_INT16 i;
+        for(i = 0; i < pParams->EQNB_NBands; i++)
+        {
+            if(((pParams->pEQNB_BandDefinition[i].Frequency < LVM_EQNB_MIN_BAND_FREQ)  ||
+                (pParams->pEQNB_BandDefinition[i].Frequency > LVM_EQNB_MAX_BAND_FREQ)) ||
+                ((pParams->pEQNB_BandDefinition[i].Gain     < LVM_EQNB_MIN_BAND_GAIN)  ||
+                (pParams->pEQNB_BandDefinition[i].Gain      > LVM_EQNB_MAX_BAND_GAIN)) ||
+                ((pParams->pEQNB_BandDefinition[i].QFactor  < LVM_EQNB_MIN_QFACTOR)     ||
+                (pParams->pEQNB_BandDefinition[i].QFactor   > LVM_EQNB_MAX_QFACTOR)))
+            {
+                return (LVM_OUTOFRANGE);
+            }
+        }
+    }
+
+    /*
+     * Bass Enhancement parameters
+     */
+    if(((pParams->BE_OperatingMode != LVM_BE_OFF) && (pParams->BE_OperatingMode != LVM_BE_ON))                      ||
+        ((pParams->BE_EffectLevel < LVM_BE_MIN_EFFECTLEVEL ) || (pParams->BE_EffectLevel > LVM_BE_MAX_EFFECTLEVEL ))||
+        ((pParams->BE_CentreFreq != LVM_BE_CENTRE_55Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_66Hz)           &&
+        (pParams->BE_CentreFreq != LVM_BE_CENTRE_78Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_90Hz))           ||
+        ((pParams->BE_HPF != LVM_BE_HPF_OFF) && (pParams->BE_HPF != LVM_BE_HPF_ON)))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * Volume Control parameters
+     */
+    if((pParams->VC_EffectLevel < LVM_VC_MIN_EFFECTLEVEL ) || (pParams->VC_EffectLevel > LVM_VC_MAX_EFFECTLEVEL ))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+    if((pParams->VC_Balance < LVM_VC_BALANCE_MIN ) || (pParams->VC_Balance > LVM_VC_BALANCE_MAX ))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * PSA parameters
+     */
+    if( (pParams->PSA_PeakDecayRate > LVPSA_SPEED_HIGH) ||
+        (pParams->PSA_Enable > LVM_PSA_ON))
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+
+    /*
+    * Set the flag to indicate there are new parameters to use
+    *
+    * Protect the copy of the new parameters from interrupts to avoid possible problems
+    * with loss control parameters. This problem can occur if this control function is called more
+    * than once before a call to the process function. If the process function interrupts
+    * the copy to NewParams then one frame may have mixed parameters, some old and some new.
+    */
+    pInstance->ControlPending = LVM_TRUE;
+    pInstance->NoSmoothVolume = LVM_FALSE;
+
+    return(LVM_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:             LVM_GetControlParameters                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the LifeVibes module parameters. The current parameter set is returned      */
+/*  via the parameter pointer.                                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance            Instance handle                                                */
+/*  pParams              Pointer to an empty parameter structure                        */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS          Succeeded                                                      */
+/*  LVM_NULLADDRESS      when any of hInstance or pParams is NULL                       */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function may be interrupted by the LVM_Process function                     */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t           hInstance,
+                                             LVM_ControlParams_t    *pParams)
+{
+    LVM_Instance_t    *pInstance =(LVM_Instance_t  *)hInstance;
+
+
+    /*
+     * Check pointer
+     */
+    if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+    *pParams = pInstance->NewParams;
+
+    /*
+     * Copy the filter definitions for the Equaliser
+     */
+    {
+        LVM_INT16           i;
+
+        if (pInstance->NewParams.EQNB_NBands != 0)
+        for (i=0; i<pInstance->NewParams.EQNB_NBands; i++)
+        {
+            pInstance->pEQNB_UserDefs[i] = pInstance->pEQNB_BandDefs[i];
+        }
+        pParams->pEQNB_BandDefinition = pInstance->pEQNB_UserDefs;
+    }
+
+    return(LVM_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetTrebleBoost                                          */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Enable the treble boost when the settings are appropriate, i.e. non-zero gain       */
+/*  and the sample rate is high enough for the effect to be heard.                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pInstance               Pointer to the instance structure                           */
+/*  pParams                 Pointer to the parameters to use                            */
+/*                                                                                      */
+/****************************************************************************************/
+void LVM_SetTrebleBoost(LVM_Instance_t         *pInstance,
+                        LVM_ControlParams_t    *pParams)
+{
+    extern FO_C16_LShx_Coefs_t  LVM_TrebleBoostCoefs[];
+    LVM_INT16               Offset;
+    LVM_INT16               EffectLevel = 0;
+
+    /*
+     * Load the coefficients
+     */
+    if ((pParams->TE_OperatingMode == LVM_TE_ON) &&
+        (pParams->SampleRate >= TrebleBoostMinRate) &&
+        (pParams->OperatingMode == LVM_MODE_ON) &&
+        (pParams->TE_EffectLevel > 0))
+    {
+        if((pParams->TE_EffectLevel == LVM_TE_LOW_MIPS) &&
+            ((pParams->SpeakerType == LVM_HEADPHONES)||
+            (pParams->SpeakerType == LVM_EX_HEADPHONES)))
+        {
+            pInstance->TE_Active = LVM_FALSE;
+        }
+        else
+        {
+            EffectLevel = pParams->TE_EffectLevel;
+            pInstance->TE_Active = LVM_TRUE;
+        }
+
+        if(pInstance->TE_Active == LVM_TRUE)
+        {
+            /*
+             * Load the coefficients and enabled the treble boost
+             */
+            Offset = (LVM_INT16)(EffectLevel - 1 + TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
+            FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
+                                            &pInstance->pTE_Taps->TrebleBoost_Taps,
+                                            &LVM_TrebleBoostCoefs[Offset]);
+
+            /*
+             * Clear the taps
+             */
+            LoadConst_16((LVM_INT16)0,                                     /* Value */
+                         (void *)&pInstance->pTE_Taps->TrebleBoost_Taps,  /* Destination.\
+                                                     Cast to void: no dereferencing in function */
+                         (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps)/sizeof(LVM_INT16))); /* Number of words */
+        }
+    }
+    else
+    {
+        /*
+         * Disable the treble boost
+         */
+        pInstance->TE_Active = LVM_FALSE;
+    }
+
+    return;
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVM_SetVolume                                               */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Converts the input volume demand from dBs to linear.                            */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/************************************************************************************/
+void    LVM_SetVolume(LVM_Instance_t         *pInstance,
+                      LVM_ControlParams_t    *pParams)
+{
+
+    LVM_UINT16      dBShifts;                                   /* 6dB shifts */
+    LVM_UINT16      dBOffset;                                   /* Table offset */
+    LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
+
+    /*
+     * Limit the gain to the maximum allowed
+     */
+     if  (pParams->VC_EffectLevel > 0)
+     {
+         Volume = 0;
+     }
+     else
+     {
+         Volume = pParams->VC_EffectLevel;
+     }
+
+     /* Compensate this volume in PSA plot */
+     if(Volume > -60)  /* Limit volume loss to PSA Limits*/
+         pInstance->PSA_GainOffset=(LVM_INT16)(-Volume);/* Loss is compensated by Gain*/
+     else
+         pInstance->PSA_GainOffset=(LVM_INT16)60;/* Loss is compensated by Gain*/
+
+    pInstance->VC_AVLFixedVolume = 0;
+
+    /*
+     * Set volume control and AVL volumes according to headroom and volume user setting
+     */
+    if(pParams->OperatingMode == LVM_MODE_ON)
+    {
+        /* Default Situation with no AVL and no RS */
+        if(pParams->EQNB_OperatingMode == LVM_EQNB_ON)
+        {
+            if(Volume > -pInstance->Headroom)
+                Volume = (LVM_INT16)-pInstance->Headroom;
+        }
+    }
+
+    /*
+     * Activate volume control if necessary
+     */
+    pInstance->VC_Active   = LVM_TRUE;
+    if (Volume != 0)
+    {
+        pInstance->VC_VolumedB = Volume;
+    }
+    else
+    {
+        pInstance->VC_VolumedB = 0;
+    }
+
+    /*
+     * Calculate the required gain and shifts
+     */
+    dBOffset = (LVM_UINT16)((-Volume) % 6);             /* Get the dBs 0-5 */
+    dBShifts = (LVM_UINT16)(Volume / -6);               /* Get the 6dB shifts */
+
+
+    /*
+     * Set the parameters
+     */
+    if(dBShifts == 0)
+    {
+        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
+                                (LVM_INT32)LVM_VolumeTable[dBOffset]);
+    }
+    else
+    {
+        LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
+                                (((LVM_INT32)LVM_VolumeTable[dBOffset])>>dBShifts));
+    }
+    pInstance->VC_Volume.MixerStream[0].CallbackSet = 1;
+    if(pInstance->NoSmoothVolume == LVM_TRUE)
+    {
+        LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,pInstance->Params.SampleRate,2);
+    }
+    else
+    {
+        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],LVM_VC_MIXER_TIME,pInstance->Params.SampleRate,2);
+    }
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVM_SetHeadroom                                             */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Find suitable headroom based on EQ settings.                                    */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  void                Nothing                                                     */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+void    LVM_SetHeadroom(LVM_Instance_t         *pInstance,
+                        LVM_ControlParams_t    *pParams)
+{
+    LVM_INT16   ii, jj;
+    LVM_INT16   Headroom = 0;
+    LVM_INT16   MaxGain = 0;
+
+
+    if ((pParams->EQNB_OperatingMode == LVEQNB_ON) && (pInstance->HeadroomParams.Headroom_OperatingMode == LVM_HEADROOM_ON))
+    {
+        /* Find typical headroom value */
+        for(jj = 0; jj < pInstance->HeadroomParams.NHeadroomBands; jj++)
+        {
+            MaxGain = 0;
+            for( ii = 0; ii < pParams->EQNB_NBands; ii++)
+            {
+                if((pParams->pEQNB_BandDefinition[ii].Frequency >= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_Low) &&
+                   (pParams->pEQNB_BandDefinition[ii].Frequency <= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_High))
+                {
+                    if(pParams->pEQNB_BandDefinition[ii].Gain > MaxGain)
+                    {
+                        MaxGain = pParams->pEQNB_BandDefinition[ii].Gain;
+                    }
+                }
+            }
+
+            if((MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset) > Headroom){
+                Headroom = (LVM_INT16)(MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset);
+            }
+        }
+
+        /* Saturate */
+        if(Headroom < 0)
+            Headroom = 0;
+    }
+    pInstance->Headroom = (LVM_UINT16)Headroom ;
+
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_ApplyNewSettings                                        */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Applies changes to parametres. This function makes no assumptions about what        */
+/*  each module needs for initialisation and hence passes all parameters to all the     */
+/*  the modules in turn.                                                                */
+/*                                                                                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_Success             Succeeded                                                   */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_ApplyNewSettings(LVM_Handle_t   hInstance)
+{
+    LVM_Instance_t         *pInstance =(LVM_Instance_t *)hInstance;
+    LVM_ControlParams_t    LocalParams;
+    LVM_INT16              Count = 5;
+
+
+    /*
+     * Copy the new parameters but make sure they didn't change while copying
+     */
+    do
+    {
+        pInstance->ControlPending = LVM_FALSE;
+        LocalParams = pInstance->NewParams;
+        pInstance->HeadroomParams = pInstance->NewHeadroomParams;
+        Count--;
+    } while ((pInstance->ControlPending != LVM_FALSE) &&
+             (Count > 0));
+
+    /* Clear all internal data if format change*/
+    if(LocalParams.SourceFormat != pInstance->Params.SourceFormat)
+    {
+        LVM_ClearAudioBuffers(pInstance);
+        pInstance->ControlPending = LVM_FALSE;
+    }
+
+    /*
+     * Update the treble boost if required
+     */
+    if ((pInstance->Params.SampleRate != LocalParams.SampleRate) ||
+        (pInstance->Params.TE_EffectLevel != LocalParams.TE_EffectLevel) ||
+        (pInstance->Params.TE_OperatingMode != LocalParams.TE_OperatingMode) ||
+        (pInstance->Params.OperatingMode != LocalParams.OperatingMode) ||
+        (pInstance->Params.SpeakerType != LocalParams.SpeakerType))
+    {
+        LVM_SetTrebleBoost(pInstance,
+                           &LocalParams);
+    }
+
+    /*
+     * Update the headroom if required
+     */
+        LVM_SetHeadroom(pInstance,                      /* Instance pointer */
+                        &LocalParams);                  /* New parameters */
+
+    /*
+     * Update the volume if required
+     */
+    {
+        LVM_SetVolume(pInstance,                      /* Instance pointer */
+                      &LocalParams);                  /* New parameters */
+    }
+    /* Apply balance changes*/
+    if(pInstance->Params.VC_Balance != LocalParams.VC_Balance)
+    {
+        /* Configure Mixer module for gradual changes to volume*/
+        if(LocalParams.VC_Balance < 0)
+        {
+            LVM_INT32 Target;
+            /* Drop in right channel volume*/
+            Target = LVM_MAXINT_16;
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+
+            Target = dB_to_Lin32((LVM_INT16)(LocalParams.VC_Balance<<4));
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+        }
+        else if(LocalParams.VC_Balance >0)
+        {
+            LVM_INT32 Target;
+            /* Drop in left channel volume*/
+            Target = dB_to_Lin32((LVM_INT16)((-LocalParams.VC_Balance)<<4));
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+
+            Target = LVM_MAXINT_16;
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+        }
+        else
+        {
+            LVM_INT32 Target;
+            /* No drop*/
+            Target = LVM_MAXINT_16;
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+
+            LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+        }
+    }
+    /*
+     * Update the bass enhancement
+     */
+    {
+        LVDBE_ReturnStatus_en       DBE_Status;
+        LVDBE_Params_t              DBE_Params;
+        LVDBE_Handle_t              *hDBEInstance = pInstance->hDBEInstance;
+
+
+        /*
+         * Set the new parameters
+         */
+        if(LocalParams.OperatingMode == LVM_MODE_OFF)
+        {
+            DBE_Params.OperatingMode = LVDBE_OFF;
+        }
+        else
+        {
+            DBE_Params.OperatingMode    = (LVDBE_Mode_en)LocalParams.BE_OperatingMode;
+        }
+        DBE_Params.SampleRate       = (LVDBE_Fs_en)LocalParams.SampleRate;
+        DBE_Params.EffectLevel      = LocalParams.BE_EffectLevel;
+        DBE_Params.CentreFrequency  = (LVDBE_CentreFreq_en)LocalParams.BE_CentreFreq;
+        DBE_Params.HPFSelect        = (LVDBE_FilterSelect_en)LocalParams.BE_HPF;
+        DBE_Params.HeadroomdB       = 0;
+        DBE_Params.VolumeControl    = LVDBE_VOLUME_OFF;
+        DBE_Params.VolumedB         = 0;
+
+        /*
+         * Make the changes
+         */
+        DBE_Status = LVDBE_Control(hDBEInstance,
+                                   &DBE_Params);
+
+
+        /*
+         * Quit if the changes were not accepted
+         */
+        if (DBE_Status != LVDBE_SUCCESS)
+        {
+            return((LVM_ReturnStatus_en)DBE_Status);
+        }
+
+
+        /*
+         * Set the control flag
+         */
+        pInstance->DBE_Active = LVM_TRUE;
+    }
+
+    /*
+     * Update the N-Band Equaliser
+     */
+    {
+        LVEQNB_ReturnStatus_en      EQNB_Status;
+        LVEQNB_Params_t             EQNB_Params;
+        LVEQNB_Handle_t             *hEQNBInstance = pInstance->hEQNBInstance;
+
+
+        /*
+         * Set the new parameters
+         */
+
+        if(LocalParams.OperatingMode == LVM_MODE_OFF)
+        {
+            EQNB_Params.OperatingMode    = LVEQNB_BYPASS;
+        }
+        else
+        {
+            EQNB_Params.OperatingMode    = (LVEQNB_Mode_en)LocalParams.EQNB_OperatingMode;
+        }
+
+        EQNB_Params.SampleRate       = (LVEQNB_Fs_en)LocalParams.SampleRate;
+        EQNB_Params.NBands           = LocalParams.EQNB_NBands;
+        EQNB_Params.pBandDefinition  = (LVEQNB_BandDef_t *)LocalParams.pEQNB_BandDefinition;
+        if (LocalParams.SourceFormat == LVM_STEREO)    /* Mono format not supported */
+        {
+            EQNB_Params.SourceFormat = LVEQNB_STEREO;
+        }
+        else
+        {
+            EQNB_Params.SourceFormat = LVEQNB_MONOINSTEREO;     /* Force to Mono-in-Stereo mode */
+        }
+
+
+        /*
+         * Set the control flag
+         */
+        if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
+            (LocalParams.EQNB_OperatingMode == LVM_EQNB_ON))
+        {
+            pInstance->EQNB_Active = LVM_TRUE;
+        }
+        else
+        {
+            EQNB_Params.OperatingMode = LVEQNB_BYPASS;
+        }
+
+        /*
+         * Make the changes
+         */
+        EQNB_Status = LVEQNB_Control(hEQNBInstance,
+                                     &EQNB_Params);
+
+
+        /*
+         * Quit if the changes were not accepted
+         */
+        if (EQNB_Status != LVEQNB_SUCCESS)
+        {
+            return((LVM_ReturnStatus_en)EQNB_Status);
+        }
+
+    }
+
+
+    /*
+     * Update concert sound
+     */
+    {
+        LVCS_ReturnStatus_en        CS_Status;
+        LVCS_Params_t               CS_Params;
+        LVCS_Handle_t               *hCSInstance = pInstance->hCSInstance;
+        LVM_Mode_en                 CompressorMode=LVM_MODE_ON;
+
+        /*
+         * Set the new parameters
+         */
+        if(LocalParams.VirtualizerOperatingMode == LVM_MODE_ON)
+        {
+            CS_Params.OperatingMode    = LVCS_ON;
+        }
+        else
+        {
+            CS_Params.OperatingMode    = LVCS_OFF;
+        }
+
+        if((LocalParams.TE_OperatingMode == LVM_TE_ON) && (LocalParams.TE_EffectLevel == LVM_TE_LOW_MIPS))
+        {
+            CS_Params.SpeakerType  = LVCS_EX_HEADPHONES;
+        }
+        else
+        {
+            CS_Params.SpeakerType  = LVCS_HEADPHONES;
+        }
+
+        if (LocalParams.SourceFormat == LVM_STEREO)    /* Mono format not supported */
+        {
+            CS_Params.SourceFormat = LVCS_STEREO;
+        }
+        else
+        {
+            CS_Params.SourceFormat = LVCS_MONOINSTEREO;          /* Force to Mono-in-Stereo mode */
+        }
+        CS_Params.SampleRate  = LocalParams.SampleRate;
+        CS_Params.ReverbLevel = LocalParams.VirtualizerReverbLevel;
+        CS_Params.EffectLevel = LocalParams.CS_EffectLevel;
+
+
+        /*
+         * Set the control flag
+         */
+        if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
+            (LocalParams.VirtualizerOperatingMode != LVCS_OFF))
+        {
+            pInstance->CS_Active = LVM_TRUE;
+        }
+        else
+        {
+            CS_Params.OperatingMode = LVCS_OFF;
+        }
+
+        CS_Params.CompressorMode=CompressorMode;
+
+        /*
+         * Make the changes
+         */
+        CS_Status = LVCS_Control(hCSInstance,
+                                 &CS_Params);
+
+
+        /*
+         * Quit if the changes were not accepted
+         */
+        if (CS_Status != LVCS_SUCCESS)
+        {
+            return((LVM_ReturnStatus_en)CS_Status);
+        }
+
+    }
+
+    /*
+     * Update the Power Spectrum Analyser
+     */
+    {
+        LVPSA_RETURN                PSA_Status;
+        LVPSA_ControlParams_t       PSA_Params;
+        pLVPSA_Handle_t             *hPSAInstance = pInstance->hPSAInstance;
+
+
+        /*
+         * Set the new parameters
+         */
+        PSA_Params.Fs = LocalParams.SampleRate;
+        PSA_Params.LevelDetectionSpeed = (LVPSA_LevelDetectSpeed_en)LocalParams.PSA_PeakDecayRate;
+
+        /*
+         * Make the changes
+         */
+        if(pInstance->InstParams.PSA_Included==LVM_PSA_ON)
+        {
+            PSA_Status = LVPSA_Control(hPSAInstance,
+                &PSA_Params);
+
+            if (PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en)PSA_Status);
+            }
+
+            /*
+             * Apply new settings
+             */
+            PSA_Status = LVPSA_ApplyNewSettings ((LVPSA_InstancePr_t*)hPSAInstance);
+            if(PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en)PSA_Status);
+            }
+        }
+    }
+
+    /*
+     * Update the parameters and clear the flag
+     */
+    pInstance->Params =  LocalParams;
+
+
+    return(LVM_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_SetHeadroomParams                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to set the automatiuc headroom management parameters.         */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pHeadroomParams         Pointer to headroom parameter structure                     */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_Success             Succeeded                                                   */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_SetHeadroomParams(LVM_Handle_t              hInstance,
+                                          LVM_HeadroomParams_t      *pHeadroomParams)
+{
+    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
+    LVM_UINT16          ii, NBands;
+
+    /* Check for NULL pointers */
+    if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+    if ((pHeadroomParams->NHeadroomBands != 0) && (pHeadroomParams->pHeadroomDefinition == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /* Consider only the LVM_HEADROOM_MAX_NBANDS first bands*/
+    if (pHeadroomParams->NHeadroomBands > LVM_HEADROOM_MAX_NBANDS)
+    {
+        NBands = LVM_HEADROOM_MAX_NBANDS;
+    }
+    else
+    {
+        NBands = pHeadroomParams->NHeadroomBands;
+    }
+    pInstance->NewHeadroomParams.NHeadroomBands = NBands;
+
+    /* Copy settings in memory */
+    for(ii = 0; ii < NBands; ii++)
+    {
+        pInstance->pHeadroom_BandDefs[ii] = pHeadroomParams->pHeadroomDefinition[ii];
+    }
+
+    pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
+    pInstance->NewHeadroomParams.Headroom_OperatingMode = pHeadroomParams->Headroom_OperatingMode;
+    pInstance->ControlPending = LVM_TRUE;
+
+    return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetHeadroomParams                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to get the automatic headroom management parameters.          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pHeadroomParams         Pointer to headroom parameter structure (output)            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         When hInstance or pHeadroomParams are NULL                  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetHeadroomParams(LVM_Handle_t          hInstance,
+                                          LVM_HeadroomParams_t  *pHeadroomParams)
+{
+    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)hInstance;
+    LVM_UINT16          ii;
+
+    /* Check for NULL pointers */
+    if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    pHeadroomParams->NHeadroomBands = pInstance->NewHeadroomParams.NHeadroomBands;
+
+
+    /* Copy settings in memory */
+    for(ii = 0; ii < pInstance->NewHeadroomParams.NHeadroomBands; ii++)
+    {
+        pInstance->pHeadroom_UserDefs[ii] = pInstance->pHeadroom_BandDefs[ii];
+    }
+
+
+    pHeadroomParams->pHeadroomDefinition = pInstance->pHeadroom_UserDefs;
+    pHeadroomParams->Headroom_OperatingMode = pInstance->NewHeadroomParams.Headroom_OperatingMode;
+    return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_AlgoCallBack                                            */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This is the callback function of the algorithm.                                     */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pBundleHandle           Pointer to the Instance Handle                              */
+/*  pData                   Pointer to the data                                         */
+/*  callbackId              ID of the callback                                          */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32 LVM_AlgoCallBack( void          *pBundleHandle,
+                            void          *pData,
+                            LVM_INT16     callbackId)
+{
+    LVM_Instance_t      *pInstance =(LVM_Instance_t  *)pBundleHandle;
+
+    (void) pData;
+
+    switch(callbackId & 0xFF00){
+        case ALGORITHM_CS_ID:
+            switch(callbackId & 0x00FF)
+            {
+                case LVCS_EVENT_ALGOFF:
+                    pInstance->CS_Active = LVM_FALSE;
+                    break;
+                default:
+                    break;
+            }
+            break;
+        case ALGORITHM_EQNB_ID:
+            switch(callbackId & 0x00FF)
+            {
+                case LVEQNB_EVENT_ALGOFF:
+                    pInstance->EQNB_Active = LVM_FALSE;
+                    break;
+                default:
+                    break;
+            }
+            break;
+        default:
+            break;
+    }
+
+    return 0;
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_VCCallBack                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This is the callback function of the Volume control.                                */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pBundleHandle           Pointer to the Instance Handle                              */
+/*  pGeneralPurpose         Pointer to the data                                         */
+/*  CallBackParam           ID of the callback                                          */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32    LVM_VCCallBack(void*   pBundleHandle,
+                            void*   pGeneralPurpose,
+                            short   CallBackParam)
+{
+    LVM_Instance_t *pInstance =(LVM_Instance_t  *)pBundleHandle;
+    LVM_INT32    Target;
+
+    (void) pGeneralPurpose;
+    (void) CallBackParam;
+
+    /* When volume mixer has reached 0 dB target then stop it to avoid
+       unnecessary processing. */
+    Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
+
+    if(Target == 0x7FFF)
+    {
+        pInstance->VC_Active = LVM_FALSE;
+    }
+    return 1;
+}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
new file mode 100755
index 0000000..323a2a3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
@@ -0,0 +1,1003 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1316 $
+     $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVM_Private.h"
+#include "LVM_Tables.h"
+#include "VectorArithmetic.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetMemoryTable                                          */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pCapabilities           Pointer to the default capabilities                         */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Succeeded                                                   */
+/*  LVM_NULLADDRESS         When one of pMemoryTable or pInstParams is NULL             */
+/*  LVM_OUTOFRANGE          When any of the Instance parameters are out of range        */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVM_Process function                    */
+/*  2.  The scratch memory is the largest required by any of the sub-modules plus any   */
+/*      additional scratch requirements of the bundle                                   */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t         hInstance,
+                                       LVM_MemTab_t         *pMemoryTable,
+                                       LVM_InstParams_t     *pInstParams)
+{
+
+    LVM_Instance_t      *pInstance = (LVM_Instance_t *)hInstance;
+    LVM_UINT32          AlgScratchSize;
+    LVM_UINT32          BundleScratchSize;
+    LVM_UINT16          InternalBlockSize;
+    INST_ALLOC          AllocMem[LVM_NR_MEMORY_REGIONS];
+    LVM_INT16           i;
+
+
+    /*
+     * Check parameters
+     */
+    if(pMemoryTable == LVM_NULL)
+    {
+        return LVM_NULLADDRESS;
+    }
+
+
+    /*
+     * Return memory table if the instance has already been created
+     */
+    if (hInstance != LVM_NULL)
+    {
+       /* Read back memory allocation table */
+        *pMemoryTable = pInstance->MemoryTable;
+        return(LVM_SUCCESS);
+    }
+
+    if(pInstParams == LVM_NULL)
+    {
+        return LVM_NULLADDRESS;
+    }
+
+    /*
+     *  Power Spectrum Analyser
+     */
+    if(pInstParams->PSA_Included > LVM_PSA_ON)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * Check the instance parameters
+     */
+    if( (pInstParams->BufferMode != LVM_MANAGED_BUFFERS) && (pInstParams->BufferMode != LVM_UNMANAGED_BUFFERS) )
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /* N-Band Equalizer */
+    if( pInstParams->EQNB_NumBands > 32 )
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_MANAGED_MAX_MAXBLOCKSIZE ) )
+        {
+            return (LVM_OUTOFRANGE);
+        }
+    }
+    else
+    {
+        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_UNMANAGED_MAX_MAXBLOCKSIZE) )
+        {
+            return (LVM_OUTOFRANGE);
+        }
+    }
+
+    /*
+    * Initialise the AllocMem structures
+    */
+    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+    {
+        InstAlloc_Init(&AllocMem[i], LVM_NULL);
+    }
+    InternalBlockSize = (LVM_UINT16)((pInstParams->MaxBlockSize) & MIN_INTERNAL_BLOCKMASK); /* Force to a multiple of MIN_INTERNAL_BLOCKSIZE */
+
+    if (InternalBlockSize < MIN_INTERNAL_BLOCKSIZE)
+    {
+        InternalBlockSize = MIN_INTERNAL_BLOCKSIZE;
+    }
+
+    /* Maximum Internal Black Size should not be more than MAX_INTERNAL_BLOCKSIZE*/
+    if(InternalBlockSize > MAX_INTERNAL_BLOCKSIZE)
+    {
+        InternalBlockSize = MAX_INTERNAL_BLOCKSIZE;
+    }
+
+    /*
+    * Bundle requirements
+    */
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+        sizeof(LVM_Instance_t));
+
+
+    /*
+     * Set the algorithm and bundle scratch requirements
+     */
+    AlgScratchSize    = 0;
+    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        BundleScratchSize = 6 * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_INT16);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],        /* Scratch buffer */
+                            BundleScratchSize);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                            sizeof(LVM_Buffer_t));
+    }
+
+    /*
+     * Treble Enhancement requirements
+     */
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                        sizeof(LVM_TE_Data_t));
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                        sizeof(LVM_TE_Coefs_t));
+
+    /*
+     * N-Band Equalizer requirements
+     */
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],      /* Local storage */
+                        (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],      /* User storage */
+                        (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+
+    /*
+     * Concert Sound requirements
+     */
+    {
+        LVCS_MemTab_t           CS_MemTab;
+        LVCS_Capabilities_t     CS_Capabilities;
+
+        /*
+         * Set the capabilities
+         */
+        CS_Capabilities.MaxBlockSize     = InternalBlockSize;
+
+        /*
+         * Get the memory requirements
+         */
+        LVCS_Memory(LVM_NULL,
+                    &CS_MemTab,
+                    &CS_Capabilities);
+
+        /*
+         * Update the memory allocation structures
+         */
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                            CS_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                            CS_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+        if (CS_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = CS_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+    }
+
+
+    /*
+     * Dynamic Bass Enhancement requirements
+     */
+    {
+        LVDBE_MemTab_t          DBE_MemTab;
+        LVDBE_Capabilities_t    DBE_Capabilities;
+
+        /*
+         * Set the capabilities
+         */
+        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
+        DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
+        DBE_Capabilities.MaxBlockSize    = InternalBlockSize;
+
+        /*
+         * Get the memory requirements
+         */
+        LVDBE_Memory(LVM_NULL,
+                    &DBE_MemTab,
+
+                    &DBE_Capabilities);
+        /*
+         * Update the bundle table
+         */
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                            DBE_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                            DBE_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+        if (DBE_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = DBE_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+    }
+
+
+    /*
+     * N-Band equaliser requirements
+     */
+    {
+        LVEQNB_MemTab_t         EQNB_MemTab;            /* For N-Band Equaliser */
+        LVEQNB_Capabilities_t   EQNB_Capabilities;
+
+        /*
+         * Set the capabilities
+         */
+        EQNB_Capabilities.SampleRate   = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
+        EQNB_Capabilities.SourceFormat = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
+        EQNB_Capabilities.MaxBlockSize = InternalBlockSize;
+        EQNB_Capabilities.MaxBands     = pInstParams->EQNB_NumBands;
+
+        /*
+         * Get the memory requirements
+         */
+        LVEQNB_Memory(LVM_NULL,
+                      &EQNB_MemTab,
+                      &EQNB_Capabilities);
+
+        /*
+         * Update the bundle table
+         */
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                            EQNB_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+        InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                            EQNB_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+        if (EQNB_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = EQNB_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+    }
+
+    /*
+     * Headroom management memory allocation
+     */
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+
+
+    /*
+     * Spectrum Analyzer memory requirements
+     */
+    {
+        pLVPSA_Handle_t     hPSAInst = LVM_NULL;
+        LVPSA_MemTab_t      PSA_MemTab;
+        LVPSA_InitParams_t  PSA_InitParams;
+        LVPSA_FilterParam_t FiltersParams[9];
+        LVPSA_RETURN        PSA_Status;
+
+        if(pInstParams->PSA_Included == LVM_PSA_ON)
+        {
+            PSA_InitParams.SpectralDataBufferDuration   = (LVM_UINT16) 500;
+            PSA_InitParams.MaxInputBlockSize            = (LVM_UINT16) 1000;
+            PSA_InitParams.nBands                       = (LVM_UINT16) 9;
+
+            PSA_InitParams.pFiltersParams = &FiltersParams[0];
+            for(i = 0; i < PSA_InitParams.nBands; i++)
+            {
+                FiltersParams[i].CenterFrequency    = (LVM_UINT16) 1000;
+                FiltersParams[i].QFactor            = (LVM_UINT16) 25;
+                FiltersParams[i].PostGain           = (LVM_INT16)  0;
+            }
+
+            /*
+            * Get the memory requirements
+            */
+            PSA_Status = LVPSA_Memory (hPSAInst,
+                                        &PSA_MemTab,
+                                        &PSA_InitParams);
+
+            if (PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+            }
+
+            /*
+            * Update the bundle table
+            */
+            /* Slow Data */
+            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].Size);
+
+            /* Fast Data */
+            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].Size);
+
+            /* Fast Coef */
+            InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
+
+            /* Fast Temporary */
+            InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
+                                MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_INT16));
+
+            if (PSA_MemTab.Region[LVM_TEMPORARY_FAST].Size > AlgScratchSize)
+            {
+                AlgScratchSize = PSA_MemTab.Region[LVM_TEMPORARY_FAST].Size;
+            }
+        }
+    }
+
+    /*
+     * Return the memory table
+     */
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA]);
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].Type         = LVM_PERSISTENT_SLOW_DATA;
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA]);
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Type         = LVM_PERSISTENT_FAST_DATA;
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+    if (pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size < 4)
+    {
+        pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size = 0;
+    }
+
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size         = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF]);
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Type         = LVM_PERSISTENT_FAST_COEF;
+    pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+    if (pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size < 4)
+    {
+        pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size = 0;
+    }
+
+    InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+                        AlgScratchSize);
+    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size             = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST]);
+    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Type             = LVM_TEMPORARY_FAST;
+    pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].pBaseAddress     = LVM_NULL;
+    if (pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size < 4)
+    {
+        pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size = 0;
+    }
+
+    return(LVM_SUCCESS);
+
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_GetInstanceHandle                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to create a bundle instance. It returns the created instance  */
+/*  handle through phInstance. All parameters are set to their default, inactive state. */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  phInstance              pointer to the instance handle                              */
+/*  pMemoryTable            Pointer to the memory definition table                      */
+/*  pInstParams             Pointer to the initialisation capabilities                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Initialisation succeeded                                    */
+/*  LVM_OUTOFRANGE          When any of the Instance parameters are out of range        */
+/*  LVM_NULLADDRESS         When one of phInstance, pMemoryTable or pInstParams are NULL*/
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function must not be interrupted by the LVM_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t           *phInstance,
+                                          LVM_MemTab_t           *pMemoryTable,
+                                          LVM_InstParams_t       *pInstParams)
+{
+
+    LVM_ReturnStatus_en     Status = LVM_SUCCESS;
+    LVM_Instance_t          *pInstance;
+    INST_ALLOC              AllocMem[LVM_NR_MEMORY_REGIONS];
+    LVM_INT16               i;
+    LVM_UINT16              InternalBlockSize;
+    LVM_INT32               BundleScratchSize;
+
+
+    /*
+     * Check valid points have been given
+     */
+    if ((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstParams == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /*
+     * Check the memory table for NULL pointers
+     */
+    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+    {
+        if ((pMemoryTable->Region[i].Size != 0) &&
+            (pMemoryTable->Region[i].pBaseAddress==LVM_NULL))
+        {
+            return(LVM_NULLADDRESS);
+        }
+    }
+
+    /*
+     * Check the instance parameters
+     */
+    if( (pInstParams->BufferMode != LVM_MANAGED_BUFFERS) && (pInstParams->BufferMode != LVM_UNMANAGED_BUFFERS) )
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if( pInstParams->EQNB_NumBands > 32 )
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    if(pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_MANAGED_MAX_MAXBLOCKSIZE ) )
+        {
+            return (LVM_OUTOFRANGE);
+        }
+    }
+    else
+    {
+        if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_UNMANAGED_MAX_MAXBLOCKSIZE) )
+        {
+            return (LVM_OUTOFRANGE);
+        }
+    }
+
+    if(pInstParams->PSA_Included > LVM_PSA_ON)
+    {
+        return (LVM_OUTOFRANGE);
+    }
+
+    /*
+     * Initialise the AllocMem structures
+     */
+    for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+    {
+        InstAlloc_Init(&AllocMem[i],
+                       pMemoryTable->Region[i].pBaseAddress);
+    }
+
+
+    /*
+     * Set the instance handle
+     */
+    *phInstance  = (LVM_Handle_t)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                                                     sizeof(LVM_Instance_t));
+    pInstance =(LVM_Instance_t  *)*phInstance;
+
+
+    /*
+     * Save the memory table, parameters and capabilities
+     */
+    pInstance->MemoryTable    = *pMemoryTable;
+    pInstance->InstParams     = *pInstParams;
+
+
+    /*
+     * Set the bundle scratch memory and initialse the buffer management
+     */
+    InternalBlockSize = (LVM_UINT16)((pInstParams->MaxBlockSize) & MIN_INTERNAL_BLOCKMASK); /* Force to a multiple of MIN_INTERNAL_BLOCKSIZE */
+    if (InternalBlockSize < MIN_INTERNAL_BLOCKSIZE)
+    {
+        InternalBlockSize = MIN_INTERNAL_BLOCKSIZE;
+    }
+
+    /* Maximum Internal Black Size should not be more than MAX_INTERNAL_BLOCKSIZE*/
+    if(InternalBlockSize > MAX_INTERNAL_BLOCKSIZE)
+    {
+        InternalBlockSize = MAX_INTERNAL_BLOCKSIZE;
+    }
+    pInstance->InternalBlockSize = (LVM_INT16)InternalBlockSize;
+
+
+    /*
+     * Common settings for managed and unmanaged buffers
+     */
+    pInstance->SamplesToProcess = 0;                /* No samples left to process */
+    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        /*
+         * Managed buffers required
+         */
+        pInstance->pBufferManagement = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                                                           sizeof(LVM_Buffer_t));
+        BundleScratchSize = (LVM_INT32)(6 * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_INT16));
+        pInstance->pBufferManagement->pScratch = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],   /* Scratch 1 buffer */
+                                                                     (LVM_UINT32)BundleScratchSize);
+
+        LoadConst_16(0,                                                        /* Clear the input delay buffer */
+                     (LVM_INT16 *)&pInstance->pBufferManagement->InDelayBuffer,
+                     (LVM_INT16)(2 * MIN_INTERNAL_BLOCKSIZE));
+        pInstance->pBufferManagement->InDelaySamples = MIN_INTERNAL_BLOCKSIZE; /* Set the number of delay samples */
+        pInstance->pBufferManagement->OutDelaySamples = 0;                     /* No samples in the output buffer */
+        pInstance->pBufferManagement->BufferState = LVM_FIRSTCALL;             /* Set the state ready for the first call */
+    }
+
+
+    /*
+     * Set default parameters
+     */
+    pInstance->Params.OperatingMode    = LVM_MODE_OFF;
+    pInstance->Params.SampleRate       = LVM_FS_8000;
+    pInstance->Params.SourceFormat     = LVM_MONO;
+    pInstance->Params.SpeakerType      = LVM_HEADPHONES;
+    pInstance->Params.VC_EffectLevel   = 0;
+    pInstance->Params.VC_Balance       = 0;
+
+    /*
+     * Set callback
+     */
+    pInstance->CallBack = LVM_AlgoCallBack;
+
+
+    /*
+     * DC removal filter
+     */
+    DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+
+
+    /*
+     * Treble Enhancement
+     */
+    pInstance->pTE_Taps  = (LVM_TE_Data_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                                sizeof(LVM_TE_Data_t));
+
+    pInstance->pTE_State = (LVM_TE_Coefs_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                                                                 sizeof(LVM_TE_Coefs_t));
+    pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
+    pInstance->Params.TE_EffectLevel   = 0;
+    pInstance->TE_Active               = LVM_FALSE;
+
+
+    /*
+     * Set the volume control and initialise Current to Target
+     */
+    pInstance->VC_Volume.MixerStream[0].CallbackParam      = 0;
+    pInstance->VC_Volume.MixerStream[0].CallbackSet        = 0;
+    pInstance->VC_Volume.MixerStream[0].pCallbackHandle    = pInstance;
+    pInstance->VC_Volume.MixerStream[0].pCallBack          = LVM_VCCallBack;
+
+    /* In managed buffering, start with low signal level as delay in buffer management causes a click*/
+    if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+    {
+        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0],0,0);
+    }
+    else
+    {
+        LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0],LVM_MAXINT_16,LVM_MAXINT_16);
+    }
+
+    LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,LVM_FS_8000,2);
+
+    pInstance->VC_VolumedB                  = 0;
+    pInstance->VC_AVLFixedVolume            = 0;
+    pInstance->VC_Active                    = LVM_FALSE;
+
+    pInstance->VC_BalanceMix.MixerStream[0].CallbackParam      = 0;
+    pInstance->VC_BalanceMix.MixerStream[0].CallbackSet        = 0;
+    pInstance->VC_BalanceMix.MixerStream[0].pCallbackHandle    = pInstance;
+    pInstance->VC_BalanceMix.MixerStream[0].pCallBack          = LVM_VCCallBack;
+    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[0],LVM_MAXINT_16,LVM_MAXINT_16);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
+
+    pInstance->VC_BalanceMix.MixerStream[1].CallbackParam      = 0;
+    pInstance->VC_BalanceMix.MixerStream[1].CallbackSet        = 0;
+    pInstance->VC_BalanceMix.MixerStream[1].pCallbackHandle    = pInstance;
+    pInstance->VC_BalanceMix.MixerStream[1].pCallBack          = LVM_VCCallBack;
+    LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[1],LVM_MAXINT_16,LVM_MAXINT_16);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
+    /*
+     * Set the default EQNB pre-gain and pointer to the band definitions
+     */
+    pInstance->pEQNB_BandDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                    (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+    pInstance->pEQNB_UserDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                   (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+
+
+    /*
+     * Initialise the Concert Sound module
+     */
+    {
+        LVCS_Handle_t           hCSInstance;                /* Instance handle */
+        LVCS_MemTab_t           CS_MemTab;                  /* Memory table */
+        LVCS_Capabilities_t     CS_Capabilities;            /* Initial capabilities */
+        LVCS_ReturnStatus_en    LVCS_Status;                /* Function call status */
+
+        /*
+         * Set default parameters
+         */
+        pInstance->Params.VirtualizerReverbLevel    = 100;
+        pInstance->Params.VirtualizerType           = LVM_CONCERTSOUND;
+        pInstance->Params.VirtualizerOperatingMode  = LVM_MODE_OFF;
+        pInstance->CS_Active                        = LVM_FALSE;
+
+        /*
+         * Set the initialisation capabilities
+         */
+        CS_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
+        CS_Capabilities.CallBack = pInstance->CallBack;
+        CS_Capabilities.pBundleInstance = (void*)pInstance;
+
+
+        /*
+         * Get the memory requirements and then set the address pointers, forcing alignment
+         */
+        LVCS_Status = LVCS_Memory(LVM_NULL,                /* Get the memory requirements */
+                                  &CS_MemTab,
+                                  &CS_Capabilities);
+        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = &pInstance->CS_Instance;
+        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                                                                         CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Size);
+        CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                                                                                                         CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Size);
+        CS_MemTab.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress       = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+                                                                                                         0);
+
+        /*
+         * Initialise the Concert Sound instance and save the instance handle
+         */
+        hCSInstance = LVM_NULL;                            /* Set to NULL to return handle */
+        LVCS_Status = LVCS_Init(&hCSInstance,              /* Initiailse */
+                                &CS_MemTab,
+                                &CS_Capabilities);
+        if (LVCS_Status != LVCS_SUCCESS) return((LVM_ReturnStatus_en)LVCS_Status);
+        pInstance->hCSInstance = hCSInstance;              /* Save the instance handle */
+
+    }
+
+    /*
+     * Initialise the Bass Enhancement module
+     */
+    {
+        LVDBE_Handle_t          hDBEInstance;               /* Instance handle */
+        LVDBE_MemTab_t          DBE_MemTab;                 /* Memory table */
+        LVDBE_Capabilities_t    DBE_Capabilities;           /* Initial capabilities */
+        LVDBE_ReturnStatus_en   LVDBE_Status;               /* Function call status */
+
+
+        /*
+         * Set the initialisation parameters
+         */
+        pInstance->Params.BE_OperatingMode = LVM_BE_OFF;
+        pInstance->Params.BE_CentreFreq    = LVM_BE_CENTRE_55Hz;
+        pInstance->Params.BE_EffectLevel   = 0;
+        pInstance->Params.BE_HPF           = LVM_BE_HPF_OFF;
+
+        pInstance->DBE_Active              = LVM_FALSE;
+
+
+
+        /*
+         * Set the initialisation capabilities
+         */
+        DBE_Capabilities.SampleRate      = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
+        DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
+        DBE_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
+
+
+        /*
+         * Get the memory requirements and then set the address pointers
+         */
+        LVDBE_Status = LVDBE_Memory(LVM_NULL,               /* Get the memory requirements */
+                                    &DBE_MemTab,
+                                    &DBE_Capabilities);
+        DBE_MemTab.Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress        = &pInstance->DBE_Instance;
+        DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                                                                      DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size);
+        DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                                                                                                      DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size);
+        DBE_MemTab.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress         = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+                                                                                                      0);
+
+
+        /*
+         * Initialise the Dynamic Bass Enhancement instance and save the instance handle
+         */
+        hDBEInstance = LVM_NULL;                            /* Set to NULL to return handle */
+        LVDBE_Status = LVDBE_Init(&hDBEInstance,            /* Initiailse */
+                                  &DBE_MemTab,
+                                  &DBE_Capabilities);
+        if (LVDBE_Status != LVDBE_SUCCESS) return((LVM_ReturnStatus_en)LVDBE_Status);
+        pInstance->hDBEInstance = hDBEInstance;             /* Save the instance handle */
+    }
+
+
+    /*
+     * Initialise the N-Band Equaliser module
+     */
+    {
+        LVEQNB_Handle_t          hEQNBInstance;             /* Instance handle */
+        LVEQNB_MemTab_t          EQNB_MemTab;               /* Memory table */
+        LVEQNB_Capabilities_t    EQNB_Capabilities;         /* Initial capabilities */
+        LVEQNB_ReturnStatus_en   LVEQNB_Status;             /* Function call status */
+
+
+        /*
+         * Set the initialisation parameters
+         */
+        pInstance->Params.EQNB_OperatingMode   = LVM_EQNB_OFF;
+        pInstance->Params.EQNB_NBands          = 0;
+        pInstance->Params.pEQNB_BandDefinition = LVM_NULL;
+        pInstance->EQNB_Active                 = LVM_FALSE;
+
+
+        /*
+         * Set the initialisation capabilities
+         */
+        EQNB_Capabilities.SampleRate      = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
+        EQNB_Capabilities.MaxBlockSize    = (LVM_UINT16)InternalBlockSize;
+        EQNB_Capabilities.MaxBands        = pInstParams->EQNB_NumBands;
+        EQNB_Capabilities.SourceFormat    = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
+        EQNB_Capabilities.CallBack        = pInstance->CallBack;
+        EQNB_Capabilities.pBundleInstance  = (void*)pInstance;
+
+
+        /*
+         * Get the memory requirements and then set the address pointers, forcing alignment
+         */
+        LVEQNB_Status = LVEQNB_Memory(LVM_NULL,             /* Get the memory requirements */
+                                      &EQNB_MemTab,
+                                      &EQNB_Capabilities);
+        EQNB_MemTab.Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress        = &pInstance->EQNB_Instance;
+        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                                                                        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size);
+        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                                                                                                        EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size);
+        EQNB_MemTab.Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress         = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+                                                                                                        0);
+
+
+        /*
+         * Initialise the Dynamic Bass Enhancement instance and save the instance handle
+         */
+        hEQNBInstance = LVM_NULL;                           /* Set to NULL to return handle */
+        LVEQNB_Status = LVEQNB_Init(&hEQNBInstance,         /* Initiailse */
+                                    &EQNB_MemTab,
+                                    &EQNB_Capabilities);
+        if (LVEQNB_Status != LVEQNB_SUCCESS) return((LVM_ReturnStatus_en)LVEQNB_Status);
+        pInstance->hEQNBInstance = hEQNBInstance;           /* Save the instance handle */
+    }
+
+    /*
+     * Headroom management memory allocation
+     */
+    {
+        pInstance->pHeadroom_BandDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                        (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+        pInstance->pHeadroom_UserDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                                                       (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+
+        /* Headroom management parameters initialisation */
+        pInstance->NewHeadroomParams.NHeadroomBands = 2;
+        pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Limit_Low          = 20;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Limit_High         = 4999;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[0].Headroom_Offset    = 3;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Limit_Low          = 5000;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Limit_High         = 24000;
+        pInstance->NewHeadroomParams.pHeadroomDefinition[1].Headroom_Offset    = 4;
+        pInstance->NewHeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
+
+        pInstance->Headroom =0;
+    }
+
+
+    /*
+     * Initialise the PSA module
+     */
+    {
+        pLVPSA_Handle_t     hPSAInstance = LVM_NULL;   /* Instance handle */
+        LVPSA_MemTab_t      PSA_MemTab;
+        LVPSA_RETURN        PSA_Status;                 /* Function call status */
+        LVPSA_FilterParam_t FiltersParams[9];
+
+        if(pInstParams->PSA_Included==LVM_PSA_ON)
+        {
+            pInstance->PSA_InitParams.SpectralDataBufferDuration   = (LVM_UINT16) 500;
+            pInstance->PSA_InitParams.MaxInputBlockSize            = (LVM_UINT16) 2048;
+            pInstance->PSA_InitParams.nBands                       = (LVM_UINT16) 9;
+            pInstance->PSA_InitParams.pFiltersParams               = &FiltersParams[0];
+            for(i = 0; i < pInstance->PSA_InitParams.nBands; i++)
+            {
+                FiltersParams[i].CenterFrequency    = (LVM_UINT16) 1000;
+                FiltersParams[i].QFactor            = (LVM_UINT16) 100;
+                FiltersParams[i].PostGain           = (LVM_INT16)  0;
+            }
+
+            /*Get the memory requirements and then set the address pointers*/
+            PSA_Status = LVPSA_Memory (hPSAInstance,
+                                          &PSA_MemTab,
+                                          &pInstance->PSA_InitParams);
+
+            if (PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+            }
+
+            /* Slow Data */
+            PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+                PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].Size);
+
+
+            /* Fast Data */
+            PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+                PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].Size);
+
+
+            /* Fast Coef */
+            PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+                PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
+
+            /* Fast Temporary */
+            pInstance->pPSAInput = InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
+                                                                     (LVM_UINT32) MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_INT16));
+
+            PSA_MemTab.Region[LVM_TEMPORARY_FAST].pBaseAddress       = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],0);
+
+
+            /*Initialise PSA instance and save the instance handle*/
+            pInstance->PSA_ControlParams.Fs = LVM_FS_48000;
+            pInstance->PSA_ControlParams.LevelDetectionSpeed  = LVPSA_SPEED_MEDIUM;
+            PSA_Status = LVPSA_Init (&hPSAInstance,
+                                    &pInstance->PSA_InitParams,
+                                    &pInstance->PSA_ControlParams,
+                                    &PSA_MemTab);
+
+            if (PSA_Status != LVPSA_OK)
+            {
+                return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+            }
+
+            pInstance->hPSAInstance = hPSAInstance;       /* Save the instance handle */
+            pInstance->PSA_GainOffset = 0;
+        }
+        else
+        {
+            pInstance->hPSAInstance = LVM_NULL;
+        }
+
+        /*
+         * Set the initialisation parameters.
+         */
+        pInstance->Params.PSA_PeakDecayRate   = LVM_PSA_SPEED_MEDIUM;
+        pInstance->Params.PSA_Enable          = LVM_PSA_OFF;
+    }
+
+    /*
+     * Copy the initial parameters to the new parameters for correct readback of
+     * the settings.
+     */
+    pInstance->NewParams = pInstance->Params;
+
+
+    /*
+     * Create configuration number
+     */
+    pInstance->ConfigurationNumber = 0x00000000;
+    pInstance->ConfigurationNumber += LVM_CS_MASK;
+    pInstance->ConfigurationNumber += LVM_EQNB_MASK;
+    pInstance->ConfigurationNumber += LVM_DBE_MASK;
+    pInstance->ConfigurationNumber += LVM_VC_MASK;
+    pInstance->ConfigurationNumber += LVM_PSA_MASK;
+
+    if(((pInstance->ConfigurationNumber  & LVM_CS_MASK)!=0)  ||
+        ((pInstance->ConfigurationNumber & LVM_DBE_MASK)!=0) ||
+        ((pInstance->ConfigurationNumber & LVM_EQNB_MASK)!=0)||
+        ((pInstance->ConfigurationNumber & LVM_TE_MASK)!=0)  ||
+        ((pInstance->ConfigurationNumber & LVM_VC_MASK)!=0))
+    {
+        pInstance->BlickSizeMultiple    = 4;
+    }
+    else
+    {
+        pInstance->BlickSizeMultiple    = 1;
+    }
+
+    return(Status);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_ClearAudioBuffers                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used to clear the internal audio buffers of the bundle.            */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS             Initialisation succeeded                                    */
+/*  LVM_NULLADDRESS         Instance or scratch memory has a NULL pointer               */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. This function must not be interrupted by the LVM_Process function                */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t  hInstance)
+{
+    LVM_MemTab_t            MemTab;                                     /* Memory table */
+    LVM_InstParams_t        InstParams;                                 /* Instance parameters */
+    LVM_ControlParams_t     Params;                                     /* Control Parameters */
+    LVM_Instance_t          *pInstance  = (LVM_Instance_t  *)hInstance; /* Pointer to Instance */
+
+
+    if(hInstance == LVM_NULL){
+        return LVM_NULLADDRESS;
+    }
+
+    /* Save the control parameters */ /* coverity[unchecked_value] */ /* Do not check return value internal function calls */
+    LVM_GetControlParameters(hInstance, &Params);
+
+    /*  Retrieve allocated buffers in memtab */
+    LVM_GetMemoryTable(hInstance, &MemTab,  LVM_NULL);
+
+    /*  Save the instance parameters */
+    InstParams = pInstance->InstParams;
+
+    /*  Call  LVM_GetInstanceHandle to re-initialise the bundle */
+    LVM_GetInstanceHandle( &hInstance,
+                           &MemTab,
+                           &InstParams);
+
+    /* Restore control parameters */ /* coverity[unchecked_value] */ /* Do not check return value internal function calls */
+    LVM_SetControlParameters(hInstance, &Params);
+
+    /* DC removal filter */
+    DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+
+
+    return LVM_SUCCESS;
+}
+
+
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
new file mode 100755
index 0000000..f70e473
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1082 $
+     $Date: 2010-07-05 12:44:39 +0200 (Mon, 05 Jul 2010) $
+
+***********************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Header file for the private layer interface of concert sound bundle             */
+/*                                                                                  */
+/*  This files includes all definitions, types, structures and function             */
+/*  prototypes required by the execution layer.                                     */
+/*                                                                                  */
+/************************************************************************************/
+
+#ifndef __LVM_PRIVATE_H__
+#define __LVM_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVM.h"                                /* LifeVibes */
+#include "LVM_Common.h"                         /* LifeVibes common */
+#include "BIQUAD.h"                             /* Biquad library */
+#include "LVC_Mixer.h"                          /* Mixer library */
+#include "LVCS_Private.h"                       /* Concert Sound */
+#include "LVDBE_Private.h"                      /* Dynamic Bass Enhancement */
+#include "LVEQNB_Private.h"                     /* N-Band equaliser */
+#include "LVPSA_Private.h"                      /* Parametric Spectrum Analyzer */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Defines                                                                         */
+/*                                                                                  */
+/************************************************************************************/
+
+/* General */
+#define LVM_INVALID                     0xFFFF    /* Invalid init parameter */
+
+/* Memory */
+#define LVM_INSTANCE_ALIGN              4         /* 32-bit for structures */
+#define LVM_FIRSTCALL                   0         /* First call to the buffer */
+#define LVM_MAXBLOCKCALL                1         /* Maximum block size calls to the buffer */
+#define LVM_LASTCALL                    2         /* Last call to the buffer */
+#define LVM_FIRSTLASTCALL               3         /* Single call for small number of samples */
+
+/* Block Size */
+#define LVM_MIN_MAXBLOCKSIZE            16        /* Minimum MaxBlockSize Limit*/
+#define LVM_MANAGED_MAX_MAXBLOCKSIZE    8191      /* Maximum MaxBlockSzie Limit for Managed Buffer Mode*/
+#define LVM_UNMANAGED_MAX_MAXBLOCKSIZE  4096      /* Maximum MaxBlockSzie Limit for Unmanaged Buffer Mode */
+
+#define MAX_INTERNAL_BLOCKSIZE          8128      /* Maximum multiple of 64  below 8191*/
+
+#define MIN_INTERNAL_BLOCKSIZE          16        /* Minimum internal block size */
+#define MIN_INTERNAL_BLOCKSHIFT         4         /* Minimum internal block size as a power of 2 */
+#define MIN_INTERNAL_BLOCKMASK          0xFFF0    /* Minimum internal block size mask */
+
+#define LVM_PSA_DYNAMICRANGE            60        /* Spectral Dynamic range: used for offseting output*/
+#define LVM_PSA_BARHEIGHT               127       /* Spectral Bar Height*/
+
+#define LVM_TE_MIN_EFFECTLEVEL          0         /*TE Minimum EffectLevel*/
+#define LVM_TE_MAX_EFFECTLEVEL          15        /*TE Maximum Effect level*/
+
+#define LVM_VC_MIN_EFFECTLEVEL          -96       /*VC Minimum EffectLevel*/
+#define LVM_VC_MAX_EFFECTLEVEL          0         /*VC Maximum Effect level*/
+
+#define LVM_BE_MIN_EFFECTLEVEL          0         /*BE Minimum EffectLevel*/
+#define LVM_BE_MAX_EFFECTLEVEL          15        /*BE Maximum Effect level*/
+
+#define LVM_EQNB_MIN_BAND_FREQ          20        /*EQNB Minimum Band Frequency*/
+#define LVM_EQNB_MAX_BAND_FREQ          24000     /*EQNB Maximum Band Frequency*/
+#define LVM_EQNB_MIN_BAND_GAIN          -15       /*EQNB Minimum Band Frequency*/
+#define LVM_EQNB_MAX_BAND_GAIN          15        /*EQNB Maximum Band Frequency*/
+#define LVM_EQNB_MIN_QFACTOR            25        /*EQNB Minimum Q Factor*/
+#define LVM_EQNB_MAX_QFACTOR            1200      /*EQNB Maximum Q Factor*/
+#define LVM_EQNB_MIN_LPF_FREQ           1000      /*EQNB Minimum Low Pass Corner frequency*/
+#define LVM_EQNB_MIN_HPF_FREQ           20        /*EQNB Minimum High Pass Corner frequency*/
+#define LVM_EQNB_MAX_HPF_FREQ           1000      /*EQNB Maximum High Pass Corner frequency*/
+
+#define LVM_CS_MIN_EFFECT_LEVEL         0         /*CS Minimum Effect Level*/
+#define LVM_CS_MAX_REVERB_LEVEL         100       /*CS Maximum Reverb Level*/
+#define LVM_VIRTUALIZER_MAX_REVERB_LEVEL 100      /*Vitrualizer Maximum Reverb Level*/
+
+#define LVM_VC_MIXER_TIME              100       /*VC mixer time*/
+#define LVM_VC_BALANCE_MAX             96        /*VC balance max value*/
+#define LVM_VC_BALANCE_MIN             -96       /*VC balance min value*/
+
+/* Algorithm masks */
+#define LVM_CS_MASK                     1
+#define LVM_EQNB_MASK                   2
+#define LVM_DBE_MASK                    4
+#define LVM_VC_MASK                     16
+#define LVM_TE_MASK                     32
+#define LVM_PSA_MASK                    2048
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Structures                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Memory region definition */
+typedef struct
+{
+    LVM_UINT32              Size;               /* Region size in bytes */
+    LVM_UINT16              Alignment;          /* Byte alignment */
+    LVM_MemoryTypes_en      Type;               /* Region type */
+    void                    *pBaseAddress;      /* Pointer to the region base address */
+} LVM_IntMemoryRegion_t;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+    LVM_IntMemoryRegion_t   Region[LVM_NR_MEMORY_REGIONS];  /* One definition for each region */
+} LVM_IntMemTab_t;
+
+
+/* Buffer Management */
+typedef struct
+{
+    LVM_INT16               *pScratch;          /* Bundle scratch buffer */
+
+    LVM_INT16               BufferState;        /* Buffer status */
+    LVM_INT16               InDelayBuffer[6*MIN_INTERNAL_BLOCKSIZE]; /* Input buffer delay line, left and right */
+    LVM_INT16               InDelaySamples;     /* Number of samples in the input delay buffer */
+
+    LVM_INT16               OutDelayBuffer[2*MIN_INTERNAL_BLOCKSIZE]; /* Output buffer delay line */
+    LVM_INT16               OutDelaySamples;    /* Number of samples in the output delay buffer, left and right */
+    LVM_INT16               SamplesToOutput;    /* Samples to write to the output */
+} LVM_Buffer_t;
+
+
+/* Filter taps */
+typedef struct
+{
+    Biquad_2I_Order1_Taps_t TrebleBoost_Taps;   /* Treble boost Taps */
+} LVM_TE_Data_t;
+
+
+/* Coefficients */
+typedef struct
+{
+    Biquad_Instance_t       TrebleBoost_State;  /* State for the treble boost filter */
+} LVM_TE_Coefs_t;
+
+
+typedef struct
+{
+    /* Public parameters */
+    LVM_MemTab_t            MemoryTable;        /* Instance memory allocation table */
+    LVM_ControlParams_t     Params;             /* Control parameters */
+    LVM_InstParams_t        InstParams;         /* Instance parameters */
+
+    /* Private parameters */
+    LVM_UINT16              ControlPending;     /* Control flag to indicate update pending */
+    LVM_ControlParams_t     NewParams;          /* New control parameters pending update */
+
+    /* Buffer control */
+    LVM_INT16               InternalBlockSize;  /* Maximum internal block size */
+    LVM_Buffer_t            *pBufferManagement; /* Buffer management variables */
+    LVM_INT16               SamplesToProcess;   /* Input samples left to process */
+    LVM_INT16               *pInputSamples;     /* External input sample pointer */
+    LVM_INT16               *pOutputSamples;    /* External output sample pointer */
+
+    /* Configuration number */
+    LVM_INT32               ConfigurationNumber;
+    LVM_INT32               BlickSizeMultiple;
+
+    /* DC removal */
+    Biquad_Instance_t       DC_RemovalInstance; /* DC removal filter instance */
+
+    /* Concert Sound */
+    LVCS_Handle_t           hCSInstance;        /* Concert Sound instance handle */
+    LVCS_Instance_t         CS_Instance;        /* Concert Sound instance */
+    LVM_INT16               CS_Active;          /* Control flag */
+
+    /* Equalizer */
+    LVEQNB_Handle_t         hEQNBInstance;      /* N-Band Equaliser instance handle */
+    LVEQNB_Instance_t       EQNB_Instance;      /* N-Band Equaliser instance */
+    LVM_EQNB_BandDef_t      *pEQNB_BandDefs;    /* Local storage for new definitions */
+    LVM_EQNB_BandDef_t      *pEQNB_UserDefs;    /* Local storage for the user's definitions */
+    LVM_INT16               EQNB_Active;        /* Control flag */
+
+    /* Dynamic Bass Enhancement */
+    LVDBE_Handle_t          hDBEInstance;       /* Dynamic Bass Enhancement instance handle */
+    LVDBE_Instance_t        DBE_Instance;       /* Dynamic Bass Enhancement instance */
+    LVM_INT16               DBE_Active;         /* Control flag */
+
+    /* Volume Control */
+    LVMixer3_1St_st         VC_Volume;          /* Volume scaler */
+    LVMixer3_2St_st         VC_BalanceMix;      /* VC balance mixer */
+    LVM_INT16               VC_VolumedB;        /* Gain in dB */
+    LVM_INT16               VC_Active;          /* Control flag */
+    LVM_INT16               VC_AVLFixedVolume;  /* AVL fixed volume */
+
+    /* Treble Enhancement */
+    LVM_TE_Data_t           *pTE_Taps;          /* Treble boost Taps */
+    LVM_TE_Coefs_t          *pTE_State;         /* State for the treble boost filter */
+    LVM_INT16               TE_Active;          /* Control flag */
+
+    /* Headroom */
+    LVM_HeadroomParams_t    NewHeadroomParams;   /* New headroom parameters pending update */
+    LVM_HeadroomParams_t    HeadroomParams;      /* Headroom parameters */
+    LVM_HeadroomBandDef_t   *pHeadroom_BandDefs; /* Local storage for new definitions */
+    LVM_HeadroomBandDef_t   *pHeadroom_UserDefs; /* Local storage for the user's definitions */
+    LVM_UINT16              Headroom;            /* Value of the current headroom */
+
+    /* Spectrum Analyzer */
+    pLVPSA_Handle_t         hPSAInstance;       /* Spectrum Analyzer instance handle */
+    LVPSA_InstancePr_t      PSA_Instance;       /* Spectrum Analyzer instance */
+    LVPSA_InitParams_t      PSA_InitParams;     /* Spectrum Analyzer initialization parameters */
+    LVPSA_ControlParams_t   PSA_ControlParams;  /* Spectrum Analyzer control parameters */
+    LVM_INT16               PSA_GainOffset;     /* Tone control flag */
+    LVM_Callback            CallBack;
+    LVM_INT16               *pPSAInput;         /* PSA input pointer */
+
+    LVM_INT16              NoSmoothVolume;      /* Enable or disable smooth volume changes*/
+
+} LVM_Instance_t;
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Function Prototypes                                                             */
+/*                                                                                  */
+/************************************************************************************/
+
+LVM_ReturnStatus_en LVM_ApplyNewSettings(LVM_Handle_t       hInstance);
+
+void    LVM_SetTrebleBoost( LVM_Instance_t         *pInstance,
+                            LVM_ControlParams_t    *pParams);
+
+void    LVM_SetVolume(  LVM_Instance_t         *pInstance,
+                        LVM_ControlParams_t    *pParams);
+
+LVM_INT32    LVM_VCCallBack(void*   pBundleHandle,
+                            void*   pGeneralPurpose,
+                            short   CallBackParam);
+
+void    LVM_SetHeadroom(    LVM_Instance_t         *pInstance,
+                            LVM_ControlParams_t    *pParams);
+
+void    LVM_BufferIn(   LVM_Handle_t      hInstance,
+                        const LVM_INT16   *pInData,
+                        LVM_INT16         **pToProcess,
+                        LVM_INT16         **pProcessed,
+                        LVM_UINT16        *pNumSamples);
+
+void    LVM_BufferOut(  LVM_Handle_t     hInstance,
+                        LVM_INT16        *pOutData,
+                        LVM_UINT16       *pNumSamples);
+
+LVM_INT32 LVM_AlgoCallBack(     void          *pBundleHandle,
+                                void          *pData,
+                                LVM_INT16     callbackId);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif      /* __LVM_PRIVATE_H__ */
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
new file mode 100755
index 0000000..bad9450
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1002 $
+     $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "VectorArithmetic.h"
+#include "LVM_Coeffs.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVM_Process                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the LifeVibes module.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*  AudioTime               Audio Time of the current input buffer in ms                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVM_SUCCESS            Succeeded                                                    */
+/*  LVM_INVALIDNUMSAMPLES  When the NumSamples is not a valied multiple in unmanaged    */
+/*                         buffer mode                                                  */
+/*  LVM_ALIGNMENTERROR     When either the input our output buffers are not 32-bit      */
+/*                         aligned in unmanaged mode                                    */
+/*  LVM_NULLADDRESS        When one of hInstance, pInData or pOutData is NULL           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_Process(LVM_Handle_t                hInstance,
+                                const LVM_INT16             *pInData,
+                                LVM_INT16                   *pOutData,
+                                LVM_UINT16                  NumSamples,
+                                LVM_UINT32                  AudioTime)
+{
+
+    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
+    LVM_UINT16          SampleCount = NumSamples;
+    LVM_INT16           *pInput     = (LVM_INT16 *)pInData;
+    LVM_INT16           *pToProcess = (LVM_INT16 *)pInData;
+    LVM_INT16           *pProcessed = pOutData;
+    LVM_ReturnStatus_en  Status;
+
+    /*
+     * Check if the number of samples is zero
+     */
+    if (NumSamples == 0)
+    {
+        return(LVM_SUCCESS);
+    }
+
+
+    /*
+     * Check valid points have been given
+     */
+    if ((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+    {
+        return (LVM_NULLADDRESS);
+    }
+
+    /*
+     * For unmanaged mode only
+     */
+    if(pInstance->InstParams.BufferMode == LVM_UNMANAGED_BUFFERS)
+    {
+         /*
+         * Check if the number of samples is a good multiple (unmanaged mode only)
+         */
+        if((NumSamples % pInstance->BlickSizeMultiple) != 0)
+        {
+            return(LVM_INVALIDNUMSAMPLES);
+        }
+
+        /*
+         * Check the buffer alignment
+         */
+        if((((LVM_UINT32)pInData % 4) != 0) || (((LVM_UINT32)pOutData % 4) != 0))
+        {
+            return(LVM_ALIGNMENTERROR);
+        }
+    }
+
+
+    /*
+     * Update new parameters if necessary
+     */
+    if (pInstance->ControlPending == LVM_TRUE)
+    {
+        Status = LVM_ApplyNewSettings(hInstance);
+
+        if(Status != LVM_SUCCESS)
+        {
+            return Status;
+        }
+    }
+
+
+    /*
+     * Convert from Mono if necessary
+     */
+    if (pInstance->Params.SourceFormat == LVM_MONO)
+    {
+        MonoTo2I_16(pInData,                                /* Source */
+                    pOutData,                               /* Destination */
+                    (LVM_INT16)NumSamples);                 /* Number of input samples */
+        pInput     = pOutData;
+        pToProcess = pOutData;
+    }
+
+
+    /*
+     * Process the data with managed buffers
+     */
+    while (SampleCount != 0)
+    {
+        /*
+         * Manage the input buffer and frame processing
+         */
+        LVM_BufferIn(hInstance,
+                     pInput,
+                     &pToProcess,
+                     &pProcessed,
+                     &SampleCount);
+
+        /*
+         * Only process data when SampleCount is none zero, a zero count can occur when
+         * the BufferIn routine is working in managed mode.
+         */
+        if (SampleCount != 0)
+        {
+
+            /*
+             * Apply ConcertSound if required
+             */
+            if (pInstance->CS_Active == LVM_TRUE)
+            {
+                (void)LVCS_Process(pInstance->hCSInstance,          /* Concert Sound instance handle */
+                                   pToProcess,
+                                   pProcessed,
+                                   SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Apply volume if required
+             */
+            if (pInstance->VC_Active!=0)
+            {
+                LVC_MixSoft_1St_D16C31_SAT(&pInstance->VC_Volume,
+                                       pToProcess,
+                                       pProcessed,
+                                       (LVM_INT16)(2*SampleCount));     /* Left and right*/
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Call N-Band equaliser if enabled
+             */
+            if (pInstance->EQNB_Active == LVM_TRUE)
+            {
+                LVEQNB_Process(pInstance->hEQNBInstance,        /* N-Band equaliser instance handle */
+                               pToProcess,
+                               pProcessed,
+                               SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Call bass enhancement if enabled
+             */
+            if (pInstance->DBE_Active == LVM_TRUE)
+            {
+                LVDBE_Process(pInstance->hDBEInstance,          /* Dynamic Bass Enhancement instance handle */
+                              pToProcess,
+                              pProcessed,
+                              SampleCount);
+                pToProcess = pProcessed;
+            }
+
+            /*
+             * Bypass mode or everything off, so copy the input to the output
+             */
+            if (pToProcess != pProcessed)
+            {
+                Copy_16(pToProcess,                             /* Source */
+                        pProcessed,                             /* Destination */
+                        (LVM_INT16)(2*SampleCount));            /* Left and right */
+            }
+
+            /*
+             * Apply treble boost if required
+             */
+            if (pInstance->TE_Active == LVM_TRUE)
+            {
+                /*
+                 * Apply the filter
+                 */
+                FO_2I_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
+                                           pProcessed,
+                                           pProcessed,
+                                           (LVM_INT16)SampleCount);
+
+            }
+
+            /*
+             * Volume balance
+             */
+            LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
+                                            pProcessed,
+                                            pProcessed,
+                                            SampleCount);
+
+            /*
+             * Perform Parametric Spectum Analysis
+             */
+            if ((pInstance->Params.PSA_Enable == LVM_PSA_ON)&&(pInstance->InstParams.PSA_Included==LVM_PSA_ON))
+            {
+                    From2iToMono_16(pProcessed,
+                             pInstance->pPSAInput,
+                            (LVM_INT16) (SampleCount));
+
+                    LVPSA_Process(pInstance->hPSAInstance,
+                            pInstance->pPSAInput,
+                            (LVM_UINT16) (SampleCount),
+                            AudioTime);
+            }
+
+
+            /*
+             * DC removal
+             */
+            DC_2I_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
+                                 pProcessed,
+                                 pProcessed,
+                                 (LVM_INT16)SampleCount);
+
+
+        }
+
+        /*
+         * Manage the output buffer
+         */
+        LVM_BufferOut(hInstance,
+                      pOutData,
+                      &SampleCount);
+
+    }
+
+    return(LVM_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
new file mode 100755
index 0000000..cb33541
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1002 $
+     $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVM_Tables.h"
+#include "LVM_Coeffs.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Treble Boost Filter Coefficients                                              */
+/*                                                                                  */
+/************************************************************************************/
+
+FO_C16_LShx_Coefs_t    LVM_TrebleBoostCoefs[] = {
+
+                    /* 22kHz sampling rate */
+                    {HPF_Fs22050_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs22050_Gain1_A0,
+                     -HPF_Fs22050_Gain1_B1,
+                    HPF_Fs22050_Gain1_Shift},
+                    {HPF_Fs22050_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs22050_Gain2_A0,
+                     -HPF_Fs22050_Gain2_B1,
+                    HPF_Fs22050_Gain2_Shift},
+                    {HPF_Fs22050_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs22050_Gain3_A0,
+                     -HPF_Fs22050_Gain3_B1,
+                    HPF_Fs22050_Gain3_Shift},
+                    {HPF_Fs22050_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs22050_Gain4_A0,
+                     -HPF_Fs22050_Gain4_B1,
+                    HPF_Fs22050_Gain4_Shift},
+                    {HPF_Fs22050_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs22050_Gain5_A0,
+                     -HPF_Fs22050_Gain5_B1,
+                    HPF_Fs22050_Gain5_Shift},
+                    {HPF_Fs22050_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs22050_Gain6_A0,
+                     -HPF_Fs22050_Gain6_B1,
+                    HPF_Fs22050_Gain6_Shift},
+                    {HPF_Fs22050_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs22050_Gain7_A0,
+                     -HPF_Fs22050_Gain7_B1,
+                    HPF_Fs22050_Gain7_Shift},
+                    {HPF_Fs22050_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs22050_Gain8_A0,
+                     -HPF_Fs22050_Gain8_B1,
+                    HPF_Fs22050_Gain8_Shift},
+                    {HPF_Fs22050_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs22050_Gain9_A0,
+                     -HPF_Fs22050_Gain9_B1,
+                    HPF_Fs22050_Gain9_Shift},
+                    {HPF_Fs22050_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs22050_Gain10_A0,
+                     -HPF_Fs22050_Gain10_B1,
+                    HPF_Fs22050_Gain10_Shift},
+                    {HPF_Fs22050_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs22050_Gain11_A0,
+                     -HPF_Fs22050_Gain11_B1,
+                    HPF_Fs22050_Gain11_Shift},
+                    {HPF_Fs22050_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs22050_Gain12_A0,
+                     -HPF_Fs22050_Gain12_B1,
+                    HPF_Fs22050_Gain12_Shift},
+                    {HPF_Fs22050_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs22050_Gain13_A0,
+                     -HPF_Fs22050_Gain13_B1,
+                    HPF_Fs22050_Gain13_Shift},
+                    {HPF_Fs22050_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs22050_Gain14_A0,
+                     -HPF_Fs22050_Gain14_B1,
+                    HPF_Fs22050_Gain14_Shift},
+                    {HPF_Fs22050_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs22050_Gain15_A0,
+                     -HPF_Fs22050_Gain15_B1,
+                    HPF_Fs22050_Gain15_Shift},
+
+                    /* 24kHz sampling rate */
+                    {HPF_Fs24000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs24000_Gain1_A0,
+                     -HPF_Fs24000_Gain1_B1,
+                     HPF_Fs24000_Gain1_Shift},
+                    {HPF_Fs24000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs24000_Gain2_A0,
+                     -HPF_Fs24000_Gain2_B1,
+                     HPF_Fs24000_Gain2_Shift},
+                    {HPF_Fs24000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs24000_Gain3_A0,
+                     -HPF_Fs24000_Gain3_B1,
+                     HPF_Fs24000_Gain3_Shift},
+                    {HPF_Fs24000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs24000_Gain4_A0,
+                     -HPF_Fs24000_Gain4_B1,
+                     HPF_Fs24000_Gain4_Shift},
+                    {HPF_Fs24000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs24000_Gain5_A0,
+                     -HPF_Fs24000_Gain5_B1,
+                     HPF_Fs24000_Gain5_Shift},
+                    {HPF_Fs24000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs24000_Gain6_A0,
+                     -HPF_Fs24000_Gain6_B1,
+                     HPF_Fs24000_Gain6_Shift},
+                    {HPF_Fs24000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs24000_Gain7_A0,
+                     -HPF_Fs24000_Gain7_B1,
+                     HPF_Fs24000_Gain7_Shift},
+                    {HPF_Fs24000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs24000_Gain8_A0,
+                     -HPF_Fs24000_Gain8_B1,
+                     HPF_Fs24000_Gain8_Shift},
+                    {HPF_Fs24000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs24000_Gain9_A0,
+                     -HPF_Fs24000_Gain9_B1,
+                     HPF_Fs24000_Gain9_Shift},
+                    {HPF_Fs24000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs24000_Gain10_A0,
+                     -HPF_Fs24000_Gain10_B1,
+                     HPF_Fs24000_Gain10_Shift},
+                    {HPF_Fs24000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs24000_Gain11_A0,
+                     -HPF_Fs24000_Gain11_B1,
+                     HPF_Fs24000_Gain11_Shift},
+                    {HPF_Fs24000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs24000_Gain12_A0,
+                     -HPF_Fs24000_Gain12_B1,
+                     HPF_Fs24000_Gain12_Shift},
+                    {HPF_Fs24000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs24000_Gain13_A0,
+                     -HPF_Fs24000_Gain13_B1,
+                     HPF_Fs24000_Gain13_Shift},
+                    {HPF_Fs24000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs24000_Gain14_A0,
+                     -HPF_Fs24000_Gain14_B1,
+                     HPF_Fs24000_Gain14_Shift},
+                    {HPF_Fs24000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs24000_Gain15_A0,
+                     -HPF_Fs24000_Gain15_B1,
+                     HPF_Fs24000_Gain15_Shift},
+
+                    /* 32kHz sampling rate */
+                    {HPF_Fs32000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs32000_Gain1_A0,
+                     -HPF_Fs32000_Gain1_B1,
+                    HPF_Fs32000_Gain1_Shift},
+                    {HPF_Fs32000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs32000_Gain2_A0,
+                     -HPF_Fs32000_Gain2_B1,
+                    HPF_Fs32000_Gain2_Shift},
+                    {HPF_Fs32000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs32000_Gain3_A0,
+                     -HPF_Fs32000_Gain3_B1,
+                    HPF_Fs32000_Gain3_Shift},
+                    {HPF_Fs32000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs32000_Gain4_A0,
+                     -HPF_Fs32000_Gain4_B1,
+                    HPF_Fs32000_Gain4_Shift},
+                    {HPF_Fs32000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs32000_Gain5_A0,
+                     -HPF_Fs32000_Gain5_B1,
+                    HPF_Fs32000_Gain5_Shift},
+                    {HPF_Fs32000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs32000_Gain6_A0,
+                     -HPF_Fs32000_Gain6_B1,
+                    HPF_Fs32000_Gain6_Shift},
+                    {HPF_Fs32000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs32000_Gain7_A0,
+                     -HPF_Fs32000_Gain7_B1,
+                    HPF_Fs32000_Gain7_Shift},
+                    {HPF_Fs32000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs32000_Gain8_A0,
+                     -HPF_Fs32000_Gain8_B1,
+                    HPF_Fs32000_Gain8_Shift},
+                    {HPF_Fs32000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs32000_Gain9_A0,
+                     -HPF_Fs32000_Gain9_B1,
+                    HPF_Fs32000_Gain9_Shift},
+                    {HPF_Fs32000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs32000_Gain10_A0,
+                     -HPF_Fs32000_Gain10_B1,
+                    HPF_Fs32000_Gain10_Shift},
+                    {HPF_Fs32000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs32000_Gain11_A0,
+                     -HPF_Fs32000_Gain11_B1,
+                    HPF_Fs32000_Gain11_Shift},
+                    {HPF_Fs32000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs32000_Gain12_A0,
+                     -HPF_Fs32000_Gain12_B1,
+                    HPF_Fs32000_Gain12_Shift},
+                    {HPF_Fs32000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs32000_Gain13_A0,
+                     -HPF_Fs32000_Gain13_B1,
+                    HPF_Fs32000_Gain13_Shift},
+                    {HPF_Fs32000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs32000_Gain14_A0,
+                     -HPF_Fs32000_Gain14_B1,
+                    HPF_Fs32000_Gain14_Shift},
+                    {HPF_Fs32000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs32000_Gain15_A0,
+                     -HPF_Fs32000_Gain15_B1,
+                    HPF_Fs32000_Gain15_Shift},
+
+                    /* 44kHz sampling rate */
+                    {HPF_Fs44100_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs44100_Gain1_A0,
+                     -HPF_Fs44100_Gain1_B1,
+                     HPF_Fs44100_Gain1_Shift},
+                    {HPF_Fs44100_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs44100_Gain2_A0,
+                     -HPF_Fs44100_Gain2_B1,
+                     HPF_Fs44100_Gain2_Shift},
+                    {HPF_Fs44100_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs44100_Gain3_A0,
+                     -HPF_Fs44100_Gain3_B1,
+                     HPF_Fs44100_Gain3_Shift},
+                    {HPF_Fs44100_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs44100_Gain4_A0,
+                     -HPF_Fs44100_Gain4_B1,
+                     HPF_Fs44100_Gain4_Shift},
+                    {HPF_Fs44100_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs44100_Gain5_A0,
+                     -HPF_Fs44100_Gain5_B1,
+                     HPF_Fs44100_Gain5_Shift},
+                    {HPF_Fs44100_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs44100_Gain6_A0,
+                     -HPF_Fs44100_Gain6_B1,
+                     HPF_Fs44100_Gain6_Shift},
+                    {HPF_Fs44100_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs44100_Gain7_A0,
+                     -HPF_Fs44100_Gain7_B1,
+                     HPF_Fs44100_Gain7_Shift},
+                    {HPF_Fs44100_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs44100_Gain8_A0,
+                     -HPF_Fs44100_Gain8_B1,
+                     HPF_Fs44100_Gain8_Shift},
+                    {HPF_Fs44100_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs44100_Gain9_A0,
+                     -HPF_Fs44100_Gain9_B1,
+                     HPF_Fs44100_Gain9_Shift},
+                    {HPF_Fs44100_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs44100_Gain10_A0,
+                     -HPF_Fs44100_Gain10_B1,
+                     HPF_Fs44100_Gain10_Shift},
+                    {HPF_Fs44100_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs44100_Gain11_A0,
+                     -HPF_Fs44100_Gain11_B1,
+                     HPF_Fs44100_Gain11_Shift},
+                    {HPF_Fs44100_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs44100_Gain12_A0,
+                     -HPF_Fs44100_Gain12_B1,
+                     HPF_Fs44100_Gain12_Shift},
+                    {HPF_Fs44100_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs44100_Gain13_A0,
+                     -HPF_Fs44100_Gain13_B1,
+                     HPF_Fs44100_Gain13_Shift},
+                    {HPF_Fs44100_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs44100_Gain14_A0,
+                     -HPF_Fs44100_Gain14_B1,
+                     HPF_Fs44100_Gain14_Shift},
+                    {HPF_Fs44100_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs44100_Gain15_A0,
+                     -HPF_Fs44100_Gain15_B1,
+                     HPF_Fs44100_Gain15_Shift},
+
+                    /* 48kHz sampling rate */
+                    {HPF_Fs48000_Gain1_A1,             /* Gain setting 1 */
+                     HPF_Fs48000_Gain1_A0,
+                     -HPF_Fs48000_Gain1_B1,
+                     HPF_Fs48000_Gain1_Shift},
+                    {HPF_Fs48000_Gain2_A1,             /* Gain setting 2 */
+                     HPF_Fs48000_Gain2_A0,
+                     -HPF_Fs48000_Gain2_B1,
+                     HPF_Fs48000_Gain2_Shift},
+                    {HPF_Fs48000_Gain3_A1,             /* Gain setting 3 */
+                     HPF_Fs48000_Gain3_A0,
+                     -HPF_Fs48000_Gain3_B1,
+                     HPF_Fs48000_Gain3_Shift},
+                    {HPF_Fs48000_Gain4_A1,             /* Gain setting 4 */
+                     HPF_Fs48000_Gain4_A0,
+                     -HPF_Fs48000_Gain4_B1,
+                     HPF_Fs48000_Gain4_Shift},
+                    {HPF_Fs48000_Gain5_A1,             /* Gain setting 5 */
+                     HPF_Fs48000_Gain5_A0,
+                     -HPF_Fs48000_Gain5_B1,
+                     HPF_Fs48000_Gain5_Shift},
+                    {HPF_Fs48000_Gain6_A1,             /* Gain setting 6 */
+                     HPF_Fs48000_Gain6_A0,
+                     -HPF_Fs48000_Gain6_B1,
+                     HPF_Fs48000_Gain6_Shift},
+                    {HPF_Fs48000_Gain7_A1,             /* Gain setting 7 */
+                     HPF_Fs48000_Gain7_A0,
+                     -HPF_Fs48000_Gain7_B1,
+                     HPF_Fs48000_Gain7_Shift},
+                    {HPF_Fs48000_Gain8_A1,             /* Gain setting 8 */
+                     HPF_Fs48000_Gain8_A0,
+                     -HPF_Fs48000_Gain8_B1,
+                     HPF_Fs48000_Gain8_Shift},
+                    {HPF_Fs48000_Gain9_A1,             /* Gain setting 9 */
+                     HPF_Fs48000_Gain9_A0,
+                     -HPF_Fs48000_Gain9_B1,
+                     HPF_Fs48000_Gain9_Shift},
+                    {HPF_Fs48000_Gain10_A1,             /* Gain setting 10 */
+                     HPF_Fs48000_Gain10_A0,
+                     -HPF_Fs48000_Gain10_B1,
+                     HPF_Fs48000_Gain10_Shift},
+                    {HPF_Fs48000_Gain11_A1,             /* Gain setting 11 */
+                     HPF_Fs48000_Gain11_A0,
+                     -HPF_Fs48000_Gain11_B1,
+                     HPF_Fs48000_Gain11_Shift},
+                    {HPF_Fs48000_Gain12_A1,             /* Gain setting 12 */
+                     HPF_Fs48000_Gain12_A0,
+                     -HPF_Fs48000_Gain12_B1,
+                     HPF_Fs48000_Gain12_Shift},
+                    {HPF_Fs48000_Gain13_A1,             /* Gain setting 13 */
+                     HPF_Fs48000_Gain13_A0,
+                     -HPF_Fs48000_Gain13_B1,
+                     HPF_Fs48000_Gain13_Shift},
+                    {HPF_Fs48000_Gain14_A1,             /* Gain setting 14 */
+                     HPF_Fs48000_Gain14_A0,
+                     -HPF_Fs48000_Gain14_B1,
+                     HPF_Fs48000_Gain14_Shift},
+                    {HPF_Fs48000_Gain15_A1,             /* Gain setting 15 */
+                     HPF_Fs48000_Gain15_A0,
+                     -HPF_Fs48000_Gain15_B1,
+                     HPF_Fs48000_Gain15_Shift}};
+
+
+/************************************************************************************/
+/*                                                                                    */
+/*    Volume control gain and time constant tables                                    */
+/*                                                                                    */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+const LVM_INT16 LVM_VolumeTable[] = {
+    0x7FFF,             /*  0dB */
+    0x7215,             /* -1dB */
+    0x65AD,             /* -2dB */
+    0x5A9E,             /* -3dB */
+    0x50C3,             /* -4dB */
+    0x47FB,             /* -5dB */
+    0x4000};            /* -6dB */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Volume mixer time constants (100ms)                                             */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVM_MIX_TC_Fs8000      32580         /* Floating point value 0.994262695 */
+#define LVM_MIX_TC_Fs11025     32632         /* Floating point value 0.995849609 */
+#define LVM_MIX_TC_Fs12000     32643         /* Floating point value 0.996185303 */
+#define LVM_MIX_TC_Fs16000     32674         /* Floating point value 0.997131348 */
+#define LVM_MIX_TC_Fs22050     32700         /* Floating point value 0.997924805 */
+#define LVM_MIX_TC_Fs24000     32705         /* Floating point value 0.998077393 */
+#define LVM_MIX_TC_Fs32000     32721         /* Floating point value 0.998565674 */
+#define LVM_MIX_TC_Fs44100     32734         /* Floating point value 0.998962402 */
+#define LVM_MIX_TC_Fs48000     32737         /* Floating point value 0.999053955 */
+
+
+const LVM_INT16 LVM_MixerTCTable[] = {
+    LVM_MIX_TC_Fs8000,
+    LVM_MIX_TC_Fs11025,
+    LVM_MIX_TC_Fs12000,
+    LVM_MIX_TC_Fs16000,
+    LVM_MIX_TC_Fs22050,
+    LVM_MIX_TC_Fs24000,
+    LVM_MIX_TC_Fs32000,
+    LVM_MIX_TC_Fs44100,
+    LVM_MIX_TC_Fs48000};
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
new file mode 100755
index 0000000..574f641
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1002 $
+     $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVM_TABLES_H__
+#define __LVM_TABLES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "BIQUAD.h"
+#include "LVM_Types.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Treble Boost Filter Coefficients                                              */
+/*                                                                                  */
+/************************************************************************************/
+
+extern FO_C16_LShx_Coefs_t     LVM_TrebleBoostCoefs[];
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Volume control gain and time constant tables                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+extern const LVM_INT16 LVM_VolumeTable[];
+extern const LVM_INT16 LVM_MixerTCTable[];
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVM_TABLES_H__ */
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/AGC.h b/media/libeffects/lvm/lib/Common/lib/AGC.h
new file mode 100755
index 0000000..980a8e3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __AGC_H__
+#define __AGC_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************/
+/*                                                                                */
+/*    Includes                                                                    */
+/*                                                                                */
+/**********************************************************************************/
+
+#include "LVM_Types.h"
+
+
+/**********************************************************************************/
+/*                                                                                */
+/*    Types                                                                       */
+/*                                                                                */
+/**********************************************************************************/
+
+typedef struct
+{
+    LVM_INT32  AGC_Gain;                        /* The current AGC gain */
+    LVM_INT32  AGC_MaxGain;                     /* The maximum AGC gain */
+    LVM_INT32  Volume;                          /* The current volume setting */
+    LVM_INT32  Target;                          /* The target volume setting */
+    LVM_INT32  AGC_Target;                      /* AGC target level */
+    LVM_INT16  AGC_Attack;                      /* AGC attack scaler */
+    LVM_INT16  AGC_Decay;                       /* AGC decay scaler */
+    LVM_INT16  AGC_GainShift;                   /* The gain shift */
+    LVM_INT16  VolumeShift;                     /* Volume shift scaling */
+    LVM_INT16  VolumeTC;                        /* Volume update time constant */
+
+} AGC_MIX_VOL_2St1Mon_D32_t;
+
+
+/**********************************************************************************/
+/*                                                                                */
+/*    Function Prototypes                                                              */
+/*                                                                                */
+/**********************************************************************************/
+
+void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t  *pInstance,     /* Instance pointer */
+                                 const LVM_INT32            *pStSrc,        /* Stereo source */
+                                 const LVM_INT32            *pMonoSrc,      /* Mono source */
+                                 LVM_INT32                  *pDst,          /* Stereo destination */
+                                 LVM_UINT16                 n);             /* Number of samples */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif  /* __AGC_H__ */
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
new file mode 100755
index 0000000..08e5a6f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 722 $
+     $Date: 2010-06-10 15:12:34 +0200 (Thu, 10 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _BIQUAD_H_
+#define _BIQUAD_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "LVM_Types.h"
+/**********************************************************************************
+   INSTANCE MEMORY TYPE DEFINITION
+***********************************************************************************/
+
+typedef struct
+{
+    LVM_INT32 Storage[6];
+
+} Biquad_Instance_t;
+
+
+/**********************************************************************************
+   COEFFICIENT TYPE DEFINITIONS
+***********************************************************************************/
+
+/*** Biquad coefficients **********************************************************/
+typedef struct
+{
+    LVM_INT16 A2;   /*  a2  */
+    LVM_INT16 A1;   /*  a1  */
+    LVM_INT16 A0;   /*  a0  */
+    LVM_INT16 B2;   /* -b2! */
+    LVM_INT16 B1;   /* -b1! */
+} BQ_C16_Coefs_t;
+
+typedef struct
+{
+    LVM_INT32  A2;   /*  a2  */
+    LVM_INT32  A1;   /*  a1  */
+    LVM_INT32  A0;   /*  a0  */
+    LVM_INT32  B2;   /* -b2! */
+    LVM_INT32  B1;   /* -b1! */
+} BQ_C32_Coefs_t;
+
+/*** First order coefficients *****************************************************/
+typedef struct
+{
+    LVM_INT16 A1;   /*  a1  */
+    LVM_INT16 A0;   /*  a0  */
+    LVM_INT16 B1;   /* -b1! */
+} FO_C16_Coefs_t;
+
+typedef struct
+{
+    LVM_INT32  A1;   /*  a1  */
+    LVM_INT32  A0;   /*  a0  */
+    LVM_INT32  B1;   /* -b1! */
+} FO_C32_Coefs_t;
+
+/*** First order coefficients with Shift*****************************************************/
+typedef struct
+{
+    LVM_INT16 A1;    /*  a1  */
+    LVM_INT16 A0;    /*  a0  */
+    LVM_INT16 B1;    /* -b1! */
+    LVM_INT16 Shift; /* Shift */
+} FO_C16_LShx_Coefs_t;
+
+/*** Band pass coefficients *******************************************************/
+typedef struct
+{
+    LVM_INT16 A0;   /*  a0  */
+    LVM_INT16 B2;   /* -b2! */
+    LVM_INT16 B1;   /* -b1! */
+} BP_C16_Coefs_t;
+
+typedef struct
+{
+    LVM_INT32  A0;   /*  a0  */
+    LVM_INT32  B2;   /* -b2! */
+    LVM_INT32  B1;   /* -b1! */
+} BP_C32_Coefs_t;
+
+/*** Peaking coefficients *********************************************************/
+typedef struct
+{
+    LVM_INT16 A0;   /*  a0  */
+    LVM_INT16 B2;   /* -b2! */
+    LVM_INT16 B1;   /* -b1! */
+    LVM_INT16  G;   /* Gain */
+} PK_C16_Coefs_t;
+
+typedef struct
+{
+    LVM_INT32  A0;   /*  a0  */
+    LVM_INT32  B2;   /* -b2! */
+    LVM_INT32  B1;   /* -b1! */
+    LVM_INT16  G;   /* Gain */
+} PK_C32_Coefs_t;
+
+
+/**********************************************************************************
+   TAPS TYPE DEFINITIONS
+***********************************************************************************/
+
+/*** Types used for first order and shelving filter *******************************/
+
+typedef struct
+{
+    LVM_INT32 Storage[ (1*2) ];  /* One channel, two taps of size LVM_INT32 */
+} Biquad_1I_Order1_Taps_t;
+
+typedef struct
+{
+    LVM_INT32 Storage[ (2*2) ];  /* Two channels, two taps of size LVM_INT32 */
+} Biquad_2I_Order1_Taps_t;
+
+
+/*** Types used for biquad, band pass and peaking filter **************************/
+
+typedef struct
+{
+    LVM_INT32 Storage[ (1*4) ];  /* One channel, four taps of size LVM_INT32 */
+} Biquad_1I_Order2_Taps_t;
+
+typedef struct
+{
+    LVM_INT32 Storage[ (2*4) ];  /* Two channels, four taps of size LVM_INT32 */
+} Biquad_2I_Order2_Taps_t;
+
+/* The names of the functions are changed to satisfy QAC rules: Name should be Unique withing 16 characters*/
+#define BQ_2I_D32F32Cll_TRC_WRA_01_Init  Init_BQ_2I_D32F32Cll_TRC_WRA_01
+#define BP_1I_D32F32C30_TRC_WRA_02       TWO_BP_1I_D32F32C30_TRC_WRA_02
+
+/**********************************************************************************
+   FUNCTION PROTOTYPES: BIQUAD FILTERS
+***********************************************************************************/
+
+/*** 16 bit data path *************************************************************/
+
+void BQ_2I_D16F32Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
+                                            Biquad_2I_Order2_Taps_t *pTaps,
+                                            BQ_C16_Coefs_t          *pCoef);
+
+void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+void BQ_2I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
+                                            Biquad_2I_Order2_Taps_t *pTaps,
+                                            BQ_C16_Coefs_t          *pCoef);
+
+void BQ_2I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                   *pDataIn,
+                                            LVM_INT16                   *pDataOut,
+                                            LVM_INT16                   NrSamples);
+
+void BQ_2I_D16F16C14_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                   *pDataIn,
+                                            LVM_INT16                   *pDataOut,
+                                            LVM_INT16                   NrSamples);
+
+void BQ_1I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
+                                            Biquad_1I_Order2_Taps_t *pTaps,
+                                            BQ_C16_Coefs_t          *pCoef);
+
+void BQ_1I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                   *pDataIn,
+                                            LVM_INT16                   *pDataOut,
+                                            LVM_INT16                   NrSamples);
+
+void BQ_1I_D16F32Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
+                                            Biquad_1I_Order2_Taps_t *pTaps,
+                                            BQ_C16_Coefs_t          *pCoef);
+
+void BQ_1I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+/*** 32 bit data path *************************************************************/
+
+void BQ_2I_D32F32Cll_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
+                                            Biquad_2I_Order2_Taps_t *pTaps,
+                                            BQ_C32_Coefs_t          *pCoef);
+
+void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT32                    *pDataIn,
+                                            LVM_INT32                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+/**********************************************************************************
+   FUNCTION PROTOTYPES: FIRST ORDER FILTERS
+***********************************************************************************/
+
+/*** 16 bit data path *************************************************************/
+
+void FO_1I_D16F16Css_TRC_WRA_01_Init(       Biquad_Instance_t       *pInstance,
+                                            Biquad_1I_Order1_Taps_t *pTaps,
+                                            FO_C16_Coefs_t          *pCoef);
+
+void FO_1I_D16F16C15_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                   *pDataIn,
+                                            LVM_INT16                   *pDataOut,
+                                            LVM_INT16                   NrSamples);
+
+void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_Instance_t       *pInstance,
+                                          Biquad_2I_Order1_Taps_t *pTaps,
+                                          FO_C16_LShx_Coefs_t     *pCoef);
+
+void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t       *pInstance,
+                                     LVM_INT16               *pDataIn,
+                                     LVM_INT16               *pDataOut,
+                                     LVM_INT16               NrSamples);
+
+/*** 32 bit data path *************************************************************/
+
+void FO_1I_D32F32Cll_TRC_WRA_01_Init(       Biquad_Instance_t       *pInstance,
+                                            Biquad_1I_Order1_Taps_t *pTaps,
+                                            FO_C32_Coefs_t          *pCoef);
+
+void FO_1I_D32F32C31_TRC_WRA_01(            Biquad_Instance_t       *pInstance,
+                                            LVM_INT32               *pDataIn,
+                                            LVM_INT32               *pDataOut,
+                                            LVM_INT16               NrSamples);
+
+/**********************************************************************************
+   FUNCTION PROTOTYPES: BAND PASS FILTERS
+***********************************************************************************/
+
+/*** 16 bit data path *************************************************************/
+
+void BP_1I_D16F16Css_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
+                                            Biquad_1I_Order2_Taps_t *pTaps,
+                                            BP_C16_Coefs_t          *pCoef);
+
+void BP_1I_D16F16C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+void BP_1I_D16F32Cll_TRC_WRA_01_Init (      Biquad_Instance_t       *pInstance,
+                                            Biquad_1I_Order2_Taps_t *pTaps,
+                                            BP_C32_Coefs_t          *pCoef);
+
+void BP_1I_D16F32C30_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+
+/*** 32 bit data path *************************************************************/
+
+void BP_1I_D32F32Cll_TRC_WRA_02_Init (      Biquad_Instance_t       *pInstance,
+                                            Biquad_1I_Order2_Taps_t *pTaps,
+                                            BP_C32_Coefs_t          *pCoef);
+
+void BP_1I_D32F32C30_TRC_WRA_02(            Biquad_Instance_t       *pInstance,
+                                            LVM_INT32                    *pDataIn,
+                                            LVM_INT32                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+
+/*** 32 bit data path STEREO ******************************************************/
+
+void PK_2I_D32F32CllGss_TRC_WRA_01_Init (   Biquad_Instance_t       *pInstance,
+                                            Biquad_2I_Order2_Taps_t *pTaps,
+                                            PK_C32_Coefs_t          *pCoef);
+
+void PK_2I_D32F32C30G11_TRC_WRA_01 (        Biquad_Instance_t       *pInstance,
+                                            LVM_INT32                    *pDataIn,
+                                            LVM_INT32                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+void PK_2I_D32F32CssGss_TRC_WRA_01_Init (   Biquad_Instance_t       *pInstance,
+                                            Biquad_2I_Order2_Taps_t *pTaps,
+                                            PK_C16_Coefs_t          *pCoef);
+
+void PK_2I_D32F32C14G11_TRC_WRA_01 (        Biquad_Instance_t       *pInstance,
+                                            LVM_INT32                    *pDataIn,
+                                            LVM_INT32                    *pDataOut,
+                                            LVM_INT16                    NrSamples);
+
+
+/**********************************************************************************
+   FUNCTION PROTOTYPES: DC REMOVAL FILTERS
+***********************************************************************************/
+
+/*** 16 bit data path STEREO ******************************************************/
+
+void DC_2I_D16_TRC_WRA_01_Init     (        Biquad_Instance_t       *pInstance);
+
+void DC_2I_D16_TRC_WRA_01          (        Biquad_Instance_t       *pInstance,
+                                            LVM_INT16               *pDataIn,
+                                            LVM_INT16               *pDataOut,
+                                            LVM_INT16               NrSamples);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+/**********************************************************************************/
+
+#endif  /** _BIQUAD_H_ **/
+
diff --git a/media/libeffects/lvm/lib/Common/lib/CompLim.h b/media/libeffects/lvm/lib/Common/lib/CompLim.h
new file mode 100755
index 0000000..df9b583
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/CompLim.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: nxp27078 $
+     $Revision: 672 $
+     $Date: 2010-06-08 19:39:38 +0200 (Tue, 08 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _COMP_LIM_H
+#define _COMP_LIM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVM_Types.h"
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Structures                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+typedef struct /* Compressor state */
+{
+    /* Normaliser */
+    LVM_INT16   Norm_Attack;        /* Attack time constant of the Normaliser integrator */
+    LVM_INT16   Norm_Decay;         /* Decay time constant of the Normaliser integrator */
+    LVM_INT32   NormInt;            /* Normaliser integrator current value */
+    LVM_INT16   Shift;              /* Shift gain */
+    LVM_INT16   Threshold;          /* Target threshold */
+
+    /* Compressor */
+    LVM_INT16   Comp_Atten;         /* Attenuation applied before soft knee compressor */
+    LVM_INT16   Comp_Attack_S;      /* Attack time constant of the slow integrator */
+    LVM_INT16   Comp_Decay_S;       /* Decay time constant of slow the integrator */
+    LVM_INT16   Comp_Attack_F;      /* Attack time constant of fast the integrator */
+    LVM_INT16   Comp_Decay_F;       /* Decay time constant of fast the integrator */
+    LVM_INT16   SoftClipGain;       /* Soft clip gain control */
+    LVM_INT32   CompIntSlow;        /* Compressor slow integrator current value */
+    LVM_INT32   CompIntFast;        /* Compressor fast integrator current value */
+
+
+} CompLim_Instance_t;
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Function Prototypes                                                             */
+/*                                                                                  */
+/************************************************************************************/
+
+void NonLinComp_D16(LVM_INT16        Gain,
+                    LVM_INT16        *pSterBfIn,
+                    LVM_INT16        *pSterBfOut,
+                    LVM_INT32        BlockLength);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* #ifndef _COMP_LIM_H */
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/Filter.h b/media/libeffects/lvm/lib/Common/lib/Filter.h
new file mode 100755
index 0000000..93ccbcb
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/Filter.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 771 $*/
+/*     $Date: 2010-06-14 10:41:36 +0200 (Mon, 14 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#ifndef _FILTER_H_
+#define _FILTER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************
+   INCLUDES
+***********************************************************************************/
+#include "LVM_Types.h"
+#include "BIQUAD.h"
+
+
+/**********************************************************************************
+   DEFINES
+***********************************************************************************/
+#define FILTER_LOSS     32730       /* -0.01dB loss to avoid wrapping due to band ripple */
+
+/**********************************************************************************
+   FUNCTION PROTOTYPES
+***********************************************************************************/
+
+LVM_INT32 LVM_Polynomial(LVM_UINT16 N,
+                         LVM_INT32  *pCoefficients,
+                         LVM_INT32  X);
+
+LVM_INT32 LVM_Power10(   LVM_INT32  X);
+
+LVM_INT32 LVM_FO_LPF(    LVM_INT32  w,
+                         FO_C32_Coefs_t  *pCoeffs);
+
+LVM_INT32 LVM_FO_HPF(    LVM_INT32  w,
+                         FO_C32_Coefs_t  *pCoeffs);
+
+LVM_INT32   LVM_GetOmega(LVM_UINT16  Fc,
+                         LVM_Fs_en   SampleRate);
+
+/**********************************************************************************/
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /** _FILTER_H_ **/
+
diff --git a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
new file mode 100755
index 0000000..31409bf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#ifndef __INSTALLOC_H__
+#define __INSTALLOC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "LVM_Types.h"
+/*######################################################################################*/
+/*  Type declarations                                                                   */
+/*######################################################################################*/
+typedef struct
+{
+    LVM_UINT32              TotalSize;      /*  Accumulative total memory size                      */
+    LVM_UINT32              pNextMember;    /*  Pointer to the next instance member to be allocated */
+}   INST_ALLOC;
+
+
+/*######################################################################################*/
+/*  Function prototypes                                                          */
+/*######################################################################################*/
+
+/****************************************************************************************
+ *  Name        : InstAlloc_Init()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+                  StartAddr - Base address of the instance memory
+ *  Returns     : Error code
+ *  Description : Initializes the instance distribution and memory size calculation function
+ *  Remarks     :
+ ****************************************************************************************/
+
+void   InstAlloc_Init( INST_ALLOC *pms, void *StartAddr );
+
+
+/****************************************************************************************
+ *  Name        : InstAlloc_AddMember()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+                  Size - The size in bytes of the new added member
+ *  Returns     : A pointer to the new added member
+ *  Description : Allocates space for a new member in the instance memory and returns
+                  a pointer to this new member.  The start address of all members will
+                  be 32 bit alligned.
+ *  Remarks     :
+ ****************************************************************************************/
+
+void* InstAlloc_AddMember( INST_ALLOC *pms, LVM_UINT32 Size );
+
+/****************************************************************************************
+ *  Name        : InstAlloc_GetTotal()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+ *  Returns     : The instance memory size
+ *  Description : This functions returns the calculated instance memory size
+ *  Remarks     :
+ ****************************************************************************************/
+
+LVM_UINT32 InstAlloc_GetTotal( INST_ALLOC *pms);
+
+void*   InstAlloc_AddMemberAllRet(     INST_ALLOC                 *pms,
+                                     LVM_UINT32               Size[],
+                                     void                    **ptr);
+
+void*   InstAlloc_AddMemberAll( INST_ALLOC                     *pms,
+                                 LVM_UINT32                   Size[],
+                                 LVM_MemoryTable_st           *pMemoryTable);
+
+void    InstAlloc_InitAll( INST_ALLOC                      *pms,
+                           LVM_MemoryTable_st             *pMemoryTable);
+
+void    InstAlloc_InitAll_NULL( INST_ALLOC              *pms);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __JBS_INSTALLOC_H__ */
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Common.h b/media/libeffects/lvm/lib/Common/lib/LVM_Common.h
new file mode 100755
index 0000000..f0f893d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Common.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*****************************************************************************************
+
+     $Author: nxp27078 $
+     $Revision: 672 $
+     $Date: 2010-06-08 19:39:38 +0200 (Tue, 08 Jun 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Header file for the common definitions used within the bundle and its algorithms.   */
+/*                                                                                      */
+/*  This files includes all definitions, types, structures and function prototypes.     */
+/*                                                                                      */
+/****************************************************************************************/
+
+
+#ifndef __LVM_COMMON_H__
+#define __LVM_COMMON_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+#include "LVM_Types.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Definitions                                                                         */
+/*                                                                                      */
+/****************************************************************************************/
+/* Algorithm identification */
+#define ALGORITHM_NONE_ID      0x0000
+#define ALGORITHM_CS_ID        0x0100
+#define ALGORITHM_EQNB_ID      0x0200
+#define ALGORITHM_DBE_ID       0x0300
+#define ALGORITHM_VC_ID        0x0500
+#define ALGORITHM_TE_ID        0x0600
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif      /* __LVM_COMMON_H__ */
+
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h b/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h
new file mode 100755
index 0000000..8bd363d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _LVM_MACROS_H_
+#define _LVM_MACROS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************
+   MUL32x32INTO32(A,B,C,ShiftR)
+        C = (A * B) >> ShiftR
+
+        A, B and C are all 32 bit SIGNED numbers and ShiftR can vary from 0 to 64
+
+        The user has to take care that C does not overflow.  The result in case
+        of overflow is undefined.
+
+***********************************************************************************/
+#ifndef MUL32x32INTO32
+#define MUL32x32INTO32(A,B,C,ShiftR)   \
+        {LVM_INT32 MUL32x32INTO32_temp,MUL32x32INTO32_temp2,MUL32x32INTO32_mask,MUL32x32INTO32_HH,MUL32x32INTO32_HL,MUL32x32INTO32_LH,MUL32x32INTO32_LL;\
+         LVM_INT32  shiftValue;\
+        shiftValue = (ShiftR);\
+        MUL32x32INTO32_mask=0x0000FFFF;\
+        MUL32x32INTO32_HH= ((LVM_INT32)((LVM_INT16)((A)>>16))*((LVM_INT16)((B)>>16)) );\
+        MUL32x32INTO32_HL= ((LVM_INT32)((B)&MUL32x32INTO32_mask)*((LVM_INT16)((A)>>16))) ;\
+        MUL32x32INTO32_LH= ((LVM_INT32)((A)&MUL32x32INTO32_mask)*((LVM_INT16)((B)>>16)));\
+        MUL32x32INTO32_LL= (LVM_INT32)((A)&MUL32x32INTO32_mask)*(LVM_INT32)((B)&MUL32x32INTO32_mask);\
+        MUL32x32INTO32_temp= (LVM_INT32)(MUL32x32INTO32_HL&MUL32x32INTO32_mask)+(LVM_INT32)(MUL32x32INTO32_LH&MUL32x32INTO32_mask)+(LVM_INT32)((MUL32x32INTO32_LL>>16)&MUL32x32INTO32_mask);\
+        MUL32x32INTO32_HH= MUL32x32INTO32_HH+(LVM_INT32)(MUL32x32INTO32_HL>>16)+(LVM_INT32)(MUL32x32INTO32_LH>>16)+(LVM_INT32)(MUL32x32INTO32_temp>>16);\
+        MUL32x32INTO32_LL=MUL32x32INTO32_LL+(LVM_INT32)(MUL32x32INTO32_HL<<16)+(LVM_INT32)(MUL32x32INTO32_LH<<16);\
+        if(shiftValue<32)\
+        {\
+        MUL32x32INTO32_HH=MUL32x32INTO32_HH<<(32-shiftValue);\
+        MUL32x32INTO32_mask=((LVM_INT32)1<<(32-shiftValue))-1;\
+        MUL32x32INTO32_LL=(MUL32x32INTO32_LL>>shiftValue)&MUL32x32INTO32_mask;\
+        MUL32x32INTO32_temp2=MUL32x32INTO32_HH|MUL32x32INTO32_LL;\
+        }\
+        else\
+       {\
+        MUL32x32INTO32_temp2=(LVM_INT32)MUL32x32INTO32_HH>>(shiftValue-32);\
+       }\
+       (C) = MUL32x32INTO32_temp2;\
+       }
+#endif
+
+/**********************************************************************************
+   MUL32x16INTO32(A,B,C,ShiftR)
+        C = (A * B) >> ShiftR
+
+        A and C are 32 bit SIGNED numbers.  B is a 16 bit SIGNED number.
+        ShiftR can vary from 0 to 48
+
+        The user has to take care that C does not overflow.  The result in case
+        of overflow is undefined.
+
+***********************************************************************************/
+#ifndef MUL32x16INTO32
+#define MUL32x16INTO32(A,B,C,ShiftR)   \
+        {LVM_INT32 MUL32x16INTO32_mask,MUL32x16INTO32_HH,MUL32x16INTO32_LL;\
+         LVM_INT32  shiftValue;\
+        shiftValue = (ShiftR);\
+        MUL32x16INTO32_mask=0x0000FFFF;\
+        MUL32x16INTO32_HH= ((LVM_INT32)(B)*((LVM_INT16)((A)>>16)));\
+        MUL32x16INTO32_LL= ((LVM_INT32)((A)&MUL32x16INTO32_mask)*(B));\
+        if(shiftValue<16)\
+        {\
+        MUL32x16INTO32_HH=(LVM_INT32)((LVM_UINT32)MUL32x16INTO32_HH<<(16-shiftValue));\
+        (C)=MUL32x16INTO32_HH+(LVM_INT32)(MUL32x16INTO32_LL>>shiftValue);\
+        }\
+        else if(shiftValue<32) {\
+        MUL32x16INTO32_HH=(LVM_INT32)(MUL32x16INTO32_HH>>(shiftValue-16));\
+        (C)=MUL32x16INTO32_HH+(LVM_INT32)(MUL32x16INTO32_LL>>shiftValue);\
+        }\
+        else {\
+        (C)=MUL32x16INTO32_HH>>(shiftValue-16);}\
+        }
+#endif
+
+/**********************************************************************************
+   ADD2_SAT_32x32(A,B,C)
+        C = SAT(A + B)
+
+        A,B and C are 32 bit SIGNED numbers.
+***********************************************************************************/
+#ifndef ADD2_SAT_32x32
+#define ADD2_SAT_32x32(A,B,C)   \
+        {(C)=(A)+(B);\
+         if ((((C) ^ (A)) & ((C) ^ (B))) >> 31)\
+            {\
+                if((A)<0)\
+                    (C)=0x80000000l;\
+                else\
+                    (C)=0x7FFFFFFFl;\
+            }\
+        }
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LVM_MACROS_H_ */
+
+/*** End of file ******************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
new file mode 100755
index 0000000..22a16d6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 __LVM_TIMER_H__
+#define __LVM_TIMER_H__
+/************************************************************************/
+/*                                                                      */
+/*     Project::   My Project                                           */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#include "LVM_Types.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Header file for the LVM_Timer library                                               */
+/*                                                                                      */
+/*  Functionality:                                                                      */
+/*  The timer will count down a number of ms, based on the number of samples it         */
+/*  sees and the curent sampling rate.  When the timer expires, a registered            */
+/*  callback function will be called.                                                   */
+/*  The maximal number of sampless that can be called by the timer is 2^32, which       */
+/*  corresponds to 24.8 hours at a sampling rate of 48 kHz                              */
+/*  The timer currently does not suport changes in sampling rate while timing.          */
+/****************************************************************************************/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/****************************************************************************************/
+/*  TYPE DEFINITIONS                                                                    */
+/****************************************************************************************/
+
+typedef struct
+{
+    LVM_INT32 Storage[6];
+
+} LVM_Timer_Instance_t;
+
+typedef struct
+{
+    LVM_INT32  SamplingRate;
+    LVM_INT16  TimeInMs;
+    LVM_INT32  CallBackParam;
+    void       *pCallBackParams;
+    void       *pCallbackInstance;
+    void       (*pCallBack)(void*,void*,LVM_INT32);
+
+} LVM_Timer_Params_t;
+
+/****************************************************************************************/
+/*  FUNCTION PROTOTYPES                                                                 */
+/****************************************************************************************/
+
+void LVM_Timer_Init (   LVM_Timer_Instance_t       *pInstance,
+                        LVM_Timer_Params_t         *pParams     );
+
+
+void LVM_Timer      (   LVM_Timer_Instance_t       *pInstance,
+                        LVM_INT16                       BlockSize );
+
+
+/****************************************************************************************/
+/*  END OF HEADER                                                                       */
+/****************************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* __LVM_TIMER_H__ */
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
new file mode 100755
index 0000000..e4649ba
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Header file defining the standard LifeVibes types for use in the application layer  */
+/*  interface of all LifeVibes modules                                                  */
+/*                                                                                      */
+/****************************************************************************************/
+
+#ifndef LVM_TYPES_H
+#define LVM_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  definitions                                                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define LVM_NULL                0                   /* NULL pointer */
+
+#define LVM_TRUE                1                   /* Booleans */
+#define LVM_FALSE               0
+
+#define LVM_MAXINT_8            127                 /* Maximum positive integer size */
+#define LVM_MAXINT_16           32767
+#define LVM_MAXINT_32           2147483647
+#define LVM_MAXENUM             2147483647
+
+#define LVM_MODULEID_MASK       0xFF00              /* Mask to extract the calling module ID from callbackId */
+#define LVM_EVENTID_MASK        0x00FF              /* Mask to extract the callback event from callbackId */
+
+/* Memory table*/
+#define LVM_MEMREGION_PERSISTENT_SLOW_DATA      0   /* Offset to the instance memory region */
+#define LVM_MEMREGION_PERSISTENT_FAST_DATA      1   /* Offset to the persistent data memory region */
+#define LVM_MEMREGION_PERSISTENT_FAST_COEF      2   /* Offset to the persistent coefficient memory region */
+#define LVM_MEMREGION_TEMPORARY_FAST            3   /* Offset to temporary memory region */
+
+#define LVM_NR_MEMORY_REGIONS                   4   /* Number of memory regions */
+
+/* Memory partition type */
+#define LVM_MEM_PARTITION0      0                   /* 1st memory partition */
+#define LVM_MEM_PARTITION1      1                   /* 2nd memory partition */
+#define LVM_MEM_PARTITION2      2                   /* 3rd memory partition */
+#define LVM_MEM_PARTITION3      3                   /* 4th memory partition */
+
+/* Use type */
+#define LVM_MEM_PERSISTENT      0                   /* Persistent memory type */
+#define LVM_MEM_SCRATCH         4                   /* Scratch  memory type */
+
+/* Access type */
+#define LVM_MEM_INTERNAL        0                   /* Internal (fast) access memory */
+#define LVM_MEM_EXTERNAL        8                   /* External (slow) access memory */
+
+/* Platform specific */
+#define LVM_PERSISTENT          LVM_MEM_PARTITION0+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
+#define LVM_PERSISTENT_DATA     LVM_MEM_PARTITION1+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
+#define LVM_PERSISTENT_COEF     LVM_MEM_PARTITION2+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
+#define LVM_SCRATCH             LVM_MEM_PARTITION3+LVM_MEM_SCRATCH+LVM_MEM_INTERNAL
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Basic types                                                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+typedef     char                LVM_CHAR;           /* ASCII character */
+
+typedef     char                LVM_INT8;           /* Signed 8-bit word */
+typedef     unsigned char       LVM_UINT8;          /* Unsigned 8-bit word */
+
+typedef     short               LVM_INT16;          /* Signed 16-bit word */
+typedef     unsigned short      LVM_UINT16;         /* Unsigned 16-bit word */
+
+typedef     long                LVM_INT32;          /* Signed 32-bit word */
+typedef     unsigned long       LVM_UINT32;         /* Unsigned 32-bit word */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Standard Enumerated types                                                           */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Operating mode */
+typedef enum
+{
+    LVM_MODE_OFF    = 0,
+    LVM_MODE_ON     = 1,
+    LVM_MODE_DUMMY  = LVM_MAXENUM
+} LVM_Mode_en;
+
+
+/* Format */
+typedef enum
+{
+    LVM_STEREO          = 0,
+    LVM_MONOINSTEREO    = 1,
+    LVM_MONO            = 2,
+    LVM_SOURCE_DUMMY    = LVM_MAXENUM
+} LVM_Format_en;
+
+
+/* LVM sampling rates */
+typedef enum
+{
+    LVM_FS_8000  = 0,
+    LVM_FS_11025 = 1,
+    LVM_FS_12000 = 2,
+    LVM_FS_16000 = 3,
+    LVM_FS_22050 = 4,
+    LVM_FS_24000 = 5,
+    LVM_FS_32000 = 6,
+    LVM_FS_44100 = 7,
+    LVM_FS_48000 = 8,
+    LVM_FS_INVALID = LVM_MAXENUM-1,
+    LVM_FS_DUMMY = LVM_MAXENUM
+} LVM_Fs_en;
+
+
+/* Memory Types */
+typedef enum
+{
+    LVM_PERSISTENT_SLOW_DATA    = LVM_MEMREGION_PERSISTENT_SLOW_DATA,
+    LVM_PERSISTENT_FAST_DATA    = LVM_MEMREGION_PERSISTENT_FAST_DATA,
+    LVM_PERSISTENT_FAST_COEF    = LVM_MEMREGION_PERSISTENT_FAST_COEF,
+    LVM_TEMPORARY_FAST          = LVM_MEMREGION_TEMPORARY_FAST,
+    LVM_MEMORYTYPE_DUMMY        = LVM_MAXENUM
+} LVM_MemoryTypes_en;
+
+
+/* Memory region definition */
+typedef struct
+{
+    LVM_UINT32                  Size;                   /* Region size in bytes */
+    LVM_MemoryTypes_en          Type;                   /* Region type */
+    void                        *pBaseAddress;          /* Pointer to the region base address */
+} LVM_MemoryRegion_st;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+    LVM_MemoryRegion_st         Region[LVM_NR_MEMORY_REGIONS];  /* One definition for each region */
+} LVM_MemoryTable_st;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Standard Function Prototypes                                                        */
+/*                                                                                      */
+/****************************************************************************************/
+typedef LVM_INT32 (*LVM_Callback)(void          *pCallbackData,     /* Pointer to the callback data structure */
+                                  void          *pGeneralPurpose,   /* General purpose pointer (e.g. to a data structure needed in the callback) */
+                                  LVM_INT16     GeneralPurpose );   /* General purpose variable (e.g. to be used as callback ID) */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  End of file                                                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* LVM_TYPES_H */
diff --git a/media/libeffects/lvm/lib/Common/lib/Mixer.h b/media/libeffects/lvm/lib/Common/lib/Mixer.h
new file mode 100755
index 0000000..d741980
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/Mixer.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __MIXER_H__
+#define __MIXER_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#include "LVM_Types.h"
+
+/**********************************************************************************
+   INSTANCE MEMORY TYPE DEFINITION
+***********************************************************************************/
+
+typedef struct
+{
+    LVM_INT32   Alpha;                    /* Time constant. Set by calling application.  Can be changed at any time */
+    LVM_INT32   Target;                   /* Target value.  Set by calling application.  Can be changed at any time */
+    LVM_INT32   Current;                  /* Current value.  Set by the mixer function. */
+    LVM_INT16   CallbackSet;              /* Boolean.  Should be set by calling application each time the target value is updated */
+    LVM_INT16   CallbackParam;            /* Parameter that will be used in the calback function */
+    void        *pCallbackHandle;         /* Pointer to the instance of the callback function */
+    void        *pGeneralPurpose;         /* Pointer for general purpose usage */
+    LVM_Callback pCallBack;               /* Pointer to the callback function */
+} Mix_1St_Cll_t;
+
+typedef struct
+{
+    LVM_INT32   Alpha1;
+    LVM_INT32   Target1;
+    LVM_INT32   Current1;
+    LVM_INT16   CallbackSet1;
+    LVM_INT16   CallbackParam1;
+    void        *pCallbackHandle1;
+    void        *pGeneralPurpose1;
+    LVM_Callback pCallBack1;
+
+    LVM_INT32   Alpha2;                   /* Warning the address of this location is passed as a pointer to Mix_1St_Cll_t in some functions */
+    LVM_INT32   Target2;
+    LVM_INT32   Current2;
+    LVM_INT16   CallbackSet2;
+    LVM_INT16   CallbackParam2;
+    void        *pCallbackHandle2;
+    void        *pGeneralPurpose2;
+    LVM_Callback pCallBack2;
+
+} Mix_2St_Cll_t;
+
+
+/*** General functions ************************************************************/
+
+LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32   tc,
+                                  LVM_UINT16   Fs,
+                                  LVM_UINT16   NumChannels);
+
+
+void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_t       *pInstance,
+                                const LVM_INT32     *src,
+                                      LVM_INT32     *dst,
+                                      LVM_INT16     n);
+
+void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_t       *pInstance,
+                                const LVM_INT32     *src1,
+                                const LVM_INT32     *src2,
+                                      LVM_INT32     *dst,
+                                      LVM_INT16     n);
+
+void MixInSoft_D32C31_SAT(      Mix_1St_Cll_t       *pInstance,
+                                const LVM_INT32     *src,
+                                      LVM_INT32     *dst,
+                                      LVM_INT16     n);
+
+/**********************************************************************************
+   FUNCTION PROTOTYPES (LOW LEVEL SUBFUNCTIONS)
+***********************************************************************************/
+
+void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_t       *pInstance,
+                                    const LVM_INT32     *src,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n);
+
+void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_t       *pInstance,
+                                    const LVM_INT32     *src1,
+                                    const LVM_INT32     *src2,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n);
+
+void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_t       *pInstance,
+                                    const LVM_INT32     *src,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+/**********************************************************************************/
+
+#endif /* __MIXER_H__ */
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
new file mode 100755
index 0000000..c66e201
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#ifndef __SCALARARITHMETIC_H__
+#define __SCALARARITHMETIC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*######################################################################################*/
+/*  Include files                                                                       */
+/*######################################################################################*/
+
+#include "LVM_Types.h"
+
+/*######################################################################################*/
+/*  Extern function prototypes                                                          */
+/*######################################################################################*/
+
+/* Absolute value including the corner case for the extreme negative value */
+LVM_INT32   Abs_32(LVM_INT32     input);
+
+/****************************************************************************************
+ *  Name        : dB_to_Lin32()
+ *  Input       : Signed 16-bit integer
+ *                  MSB (16) = sign bit
+ *                  (15->05) = integer part
+ *                  (04->01) = decimal part
+ *  Output      : Signed 32-bit integer
+ *                  MSB (32) = sign bit
+ *                  (31->16) = integer part
+ *                  (15->01) = decimal part
+ *  Returns     : Lin value format 1.16.15
+ ****************************************************************************************/
+
+LVM_INT32 dB_to_Lin32(LVM_INT16  db_fix);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* __SCALARARITHMETIC_H__ */
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
new file mode 100755
index 0000000..290a996
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 853 $
+     $Date: 2010-06-16 15:10:28 +0200 (Wed, 16 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _VECTOR_ARITHMETIC_H_
+#define _VECTOR_ARITHMETIC_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "LVM_Types.h"
+
+/**********************************************************************************
+    VARIOUS FUNCTIONS
+***********************************************************************************/
+
+void LoadConst_16(            const LVM_INT16 val,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n );
+
+void LoadConst_32(            const LVM_INT32 val,
+                                    LVM_INT32 *dst,
+                                    LVM_INT16 n );
+
+void Copy_16(                 const LVM_INT16 *src,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n );
+
+/*********************************************************************************
+ * note: In Mult3s_16x16() saturation of result is not taken care when           *
+ *       overflow occurs.                                                        *
+ *       For example when *src = 0x8000, val = *0x8000                           *
+ *       The function gives the output as 0x8000 instead of 0x7fff               *
+ *       This is the only case which will give wrong result.                     *
+ *       For more information refer to Vector_Arithmetic.doc in /doc folder      *
+ *********************************************************************************/
+void Mult3s_16x16(            const LVM_INT16 *src,
+                              const LVM_INT16 val,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n);
+
+/*********************************************************************************
+ * note: In Mult3s_32x16() saturation of result is not taken care when           *
+ *       overflow occurs.                                                        *
+ *       For example when *src = 0x8000000, val = *0x8000                        *
+ *       The function gives the output as 0x8000000 instead of 0x7fffffff        *
+ *       This is the only extreme condition which is giving unexpected result    *
+ *       For more information refer to Vector_Arithmetic.doc in /doc folder      *
+ *********************************************************************************/
+void Mult3s_32x16(            const LVM_INT32  *src,
+                              const LVM_INT16 val,
+                                    LVM_INT32  *dst,
+                                    LVM_INT16 n);
+
+void DelayMix_16x16(          const LVM_INT16 *src,
+                                    LVM_INT16 *delay,
+                                    LVM_INT16 size,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 *pOffset,
+                                    LVM_INT16 n);
+
+void DelayWrite_32(           const LVM_INT32  *src,               /* Source 1, to be delayed */
+                                    LVM_INT32  *delay,             /* Delay buffer */
+                                    LVM_UINT16 size,               /* Delay size */
+                                    LVM_UINT16 *pOffset,           /* Delay offset */
+                                    LVM_INT16 n);
+
+void Add2_Sat_16x16(          const LVM_INT16 *src,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n );
+
+void Add2_Sat_32x32(          const LVM_INT32  *src,
+                                    LVM_INT32  *dst,
+                                    LVM_INT16 n );
+
+void Mac3s_Sat_16x16(         const LVM_INT16 *src,
+                              const LVM_INT16 val,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n);
+
+void Mac3s_Sat_32x16(         const LVM_INT32  *src,
+                              const LVM_INT16 val,
+                                    LVM_INT32  *dst,
+                                    LVM_INT16 n);
+
+void DelayAllPass_Sat_32x16To32(    LVM_INT32  *delay,              /* Delay buffer */
+                                    LVM_UINT16 size,                /* Delay size */
+                                    LVM_INT16 coeff,                /* All pass filter coefficient */
+                                    LVM_UINT16 DelayOffset,         /* Simple delay offset */
+                                    LVM_UINT16 *pAllPassOffset,     /* All pass filter delay offset */
+                                    LVM_INT32  *dst,                /* Source/destination */
+                                    LVM_INT16 n);
+
+/**********************************************************************************
+    SHIFT FUNCTIONS
+***********************************************************************************/
+
+void Shift_Sat_v16xv16 (      const LVM_INT16 val,
+                              const LVM_INT16 *src,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n);
+
+void Shift_Sat_v32xv32 (      const LVM_INT16 val,
+                              const LVM_INT32 *src,
+                                    LVM_INT32 *dst,
+                                    LVM_INT16 n);
+
+/**********************************************************************************
+    AUDIO FORMAT CONVERSION FUNCTIONS
+***********************************************************************************/
+
+void MonoTo2I_16(             const LVM_INT16 *src,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n);
+
+void MonoTo2I_32(             const LVM_INT32  *src,
+                                    LVM_INT32  *dst,
+                                    LVM_INT16 n);
+
+void From2iToMono_32(         const LVM_INT32  *src,
+                                    LVM_INT32  *dst,
+                                    LVM_INT16 n);
+
+void MSTo2i_Sat_16x16(        const LVM_INT16 *srcM,
+                              const LVM_INT16 *srcS,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n );
+
+void From2iToMS_16x16(        const LVM_INT16 *src,
+                                    LVM_INT16 *dstM,
+                                    LVM_INT16 *dstS,
+                                    LVM_INT16 n );
+
+void From2iToMono_16(         const LVM_INT16 *src,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n);
+
+void JoinTo2i_32x32(          const LVM_INT32  *srcL,
+                              const LVM_INT32  *srcR,
+                                    LVM_INT32  *dst,
+                                    LVM_INT16 n );
+
+/**********************************************************************************
+    DATA TYPE CONVERSION FUNCTIONS
+***********************************************************************************/
+
+void Int16LShiftToInt32_16x32(const LVM_INT16 *src,
+                                    LVM_INT32  *dst,
+                                    LVM_INT16 n,
+                                    LVM_INT16 shift );
+
+void Int32RShiftToInt16_Sat_32x16(const  LVM_INT32  *src,
+                                    LVM_INT16 *dst,
+                                    LVM_INT16 n,
+                                    LVM_INT16 shift );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+/**********************************************************************************/
+
+#endif  /* _VECTOR_ARITHMETIC_H_ */
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
new file mode 100755
index 0000000..40e0dbf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1070 $
+     $Date: 2010-07-02 11:22:18 +0200 (Fri, 02 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "AGC.h"
+#include "ScalarArithmetic.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Defines                                                                           */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define VOL_TC_SHIFT                                        21          /* As a power of 2 */
+#define DECAY_SHIFT                                        10           /* As a power of 2 */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  AGC_MIX_VOL_2St1Mon_D32_WRA                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Apply AGC and mix signals                                                         */
+/*                                                                                      */
+/*                                                                                      */
+/*  StSrc   ------------------|                                                         */
+/*                            |                                                         */
+/*              ______       _|_        ________                                        */
+/*             |      |     |   |      |        |                                       */
+/*  MonoSrc -->| AGC  |---->| + |----->| Volume |------------------------------+--->    */
+/*             | Gain |     |___|      | Gain   |                              |        */
+/*             |______|                |________|                              |        */
+/*                /|\                               __________     ________    |        */
+/*                 |                               |          |   |        |   |        */
+/*                 |-------------------------------| AGC Gain |<--| Peak   |<--|        */
+/*                                                 | Update   |   | Detect |            */
+/*                                                 |__________|   |________|            */
+/*                                                                                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  pInstance               Instance pointer                                            */
+/*  pStereoIn               Stereo source                                               */
+/*  pMonoIn                 Mono band pass source                                       */
+/*  pStereoOut              Stereo destination                                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  Void                                                                                */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t  *pInstance,     /* Instance pointer */
+                                 const LVM_INT32            *pStSrc,        /* Stereo source */
+                                 const LVM_INT32            *pMonoSrc,      /* Mono source */
+                                 LVM_INT32                  *pDst,          /* Stereo destination */
+                                 LVM_UINT16                 NumSamples)     /* Number of samples */
+{
+
+    /*
+     * General variables
+     */
+    LVM_UINT16      i;                                          /* Sample index */
+    LVM_INT32       Left;                                       /* Left sample */
+    LVM_INT32       Right;                                      /* Right sample */
+    LVM_INT32       Mono;                                       /* Mono sample */
+    LVM_INT32       AbsPeak;                                    /* Absolute peak signal */
+    LVM_INT32       HighWord;                                   /* High word in intermediate calculations */
+    LVM_INT32       LowWord;                                    /* Low word in intermediate calculations */
+    LVM_INT16       AGC_Mult;                                   /* Short AGC gain */
+    LVM_INT16       Vol_Mult;                                   /* Short volume */
+
+
+    /*
+     * Instance control variables
+     */
+    LVM_INT32      AGC_Gain      = pInstance->AGC_Gain;         /* Get the current AGC gain */
+    LVM_INT32      AGC_MaxGain   = pInstance->AGC_MaxGain;      /* Get maximum AGC gain */
+    LVM_INT16      AGC_GainShift = pInstance->AGC_GainShift;    /* Get the AGC shift */
+    LVM_INT16      AGC_Attack    = pInstance->AGC_Attack;       /* Attack scaler */
+    LVM_INT16      AGC_Decay     = pInstance->AGC_Decay;        /* Decay scaler */
+    LVM_INT32      AGC_Target    = pInstance->AGC_Target;       /* Get the target level */
+    LVM_INT32      Vol_Current   = pInstance->Volume;           /* Actual volume setting */
+    LVM_INT32      Vol_Target    = pInstance->Target;           /* Target volume setting */
+    LVM_INT16      Vol_Shift     = pInstance->VolumeShift;      /* Volume shift scaling */
+    LVM_INT16      Vol_TC        = pInstance->VolumeTC;         /* Time constant */
+
+
+    /*
+     * Process on a sample by sample basis
+     */
+    for (i=0;i<NumSamples;i++)                                  /* For each sample */
+    {
+
+        /*
+         * Get the short scalers
+         */
+        AGC_Mult    = (LVM_INT16)(AGC_Gain >> 16);              /* Get the short AGC gain */
+        Vol_Mult    = (LVM_INT16)(Vol_Current >> 16);           /* Get the short volume gain */
+
+
+        /*
+         * Get the input samples
+         */
+        Left  = *pStSrc++;                                      /* Get the left sample */
+        Right = *pStSrc++;                                      /* Get the right sample */
+        Mono  = *pMonoSrc++;                                    /* Get the mono sample */
+
+
+        /*
+         * Apply the AGC gain to the mono input and mix with the stereo signal
+         */
+        HighWord = (AGC_Mult * (Mono >> 16));                   /* signed long (Mono) by unsigned short (AGC_Mult) multiply */
+        LowWord = (AGC_Mult * (Mono & 0xffff));
+        Mono = (HighWord + (LowWord >> 16)) << (AGC_GainShift);
+        Left  += Mono;                                          /* Mix in the mono signal */
+        Right += Mono;
+
+
+        /*
+         * Apply the volume and write to the output stream
+         */
+        HighWord = (Vol_Mult * (Left >> 16));                   /* signed long (Left) by unsigned short (Vol_Mult) multiply */
+        LowWord = (Vol_Mult * (Left & 0xffff));
+        Left = (HighWord + (LowWord >> 16)) << (Vol_Shift);
+        HighWord = (Vol_Mult * (Right >> 16));                  /* signed long (Right) by unsigned short (Vol_Mult) multiply */
+        LowWord = (Vol_Mult * (Right & 0xffff));
+        Right = (HighWord + (LowWord >> 16)) << (Vol_Shift);
+        *pDst++ = Left;                                         /* Save the results */
+        *pDst++ = Right;
+
+
+        /*
+         * Update the AGC gain
+         */
+        AbsPeak = (Abs_32(Left)>Abs_32(Right)) ? Abs_32(Left) : Abs_32(Right);  /* Get the absolute peak */
+        if (AbsPeak > AGC_Target)
+        {
+            /*
+             * The signal is too large so decrease the gain
+             */
+            HighWord = (AGC_Attack * (AGC_Gain >> 16));         /* signed long (AGC_Gain) by unsigned short (AGC_Attack) multiply */
+            LowWord = (AGC_Attack * (AGC_Gain & 0xffff));
+            AGC_Gain = (HighWord + (LowWord >> 16)) << 1;
+        }
+        else
+        {
+            /*
+             * The signal is too small so increase the gain
+             */
+            if (AGC_Gain > AGC_MaxGain)
+            {
+                AGC_Gain -= (AGC_Decay << DECAY_SHIFT);
+            }
+            else
+            {
+                AGC_Gain += (AGC_Decay << DECAY_SHIFT);
+            }
+        }
+
+        /*
+         * Update the gain
+         */
+        Vol_Current += Vol_TC * ((Vol_Target - Vol_Current) >> VOL_TC_SHIFT);
+    }
+
+
+    /*
+     * Update the parameters
+     */
+    pInstance->Volume = Vol_Current;                            /* Actual volume setting */
+    pInstance->AGC_Gain = AGC_Gain;
+
+    return;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/Abs_32.c b/media/libeffects/lvm/lib/Common/src/Abs_32.c
new file mode 100755
index 0000000..635315d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Abs_32.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/*######################################################################################*/
+/*  Include files                                                                       */
+/*######################################################################################*/
+
+#include    "ScalarArithmetic.h"
+
+/****************************************************************************************
+ *  Name        : Abs_32()
+ *  Input       : Signed 32-bit integer
+ *  Output      :
+ *  Returns     : Absolute value
+ *  Description : Absolute value with maximum negative value corner case
+ *  Remarks     :
+ ****************************************************************************************/
+
+LVM_INT32    Abs_32(LVM_INT32    input)
+{
+    if(input <  0)
+    {
+        if (input == (LVM_INT32)(0x80000000U))
+        {
+            /* The corner case, so set to the maximum positive value */
+            input=(LVM_INT32) 0x7fffffff;
+        }
+        else
+        {
+            /* Negative input, so invert */
+            input = (LVM_INT32)(-input);
+        }
+    }
+    return input;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c
new file mode 100755
index 0000000..18026c5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION ADD2_SAT_16X16
+***********************************************************************************/
+
+void Add2_Sat_16x16( const LVM_INT16 *src,
+                           LVM_INT16 *dst,
+                           LVM_INT16  n )
+{
+    LVM_INT32 Temp;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = ((LVM_INT32) *src) + ((LVM_INT32) *dst);
+        src++;
+
+        if (Temp > 0x00007FFF)
+        {
+            *dst = 0x7FFF;
+        }
+        else if (Temp < -0x00008000)
+        {
+            *dst = - 0x8000;
+        }
+        else
+        {
+            *dst = (LVM_INT16)Temp;
+        }
+        dst++;
+    }
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
new file mode 100755
index 0000000..96fc7e6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+
+/**********************************************************************************
+   FUNCTION ADD2_SAT_32X32
+***********************************************************************************/
+
+void Add2_Sat_32x32( const LVM_INT32  *src,
+                           LVM_INT32  *dst,
+                           LVM_INT16  n )
+{
+    LVM_INT32 a,b,c;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        a=*src;
+        src++;
+
+        b=*dst;
+        c=a+b;
+        if ((((c ^ a) & (c ^ b)) >> 31)!=0)     /* overflow / underflow */
+        {
+            if(a<0)
+            {
+                c=0x80000000l;
+            }
+            else
+            {
+                c=0x7FFFFFFFl;
+            }
+        }
+
+        *dst = c;
+        dst++;
+    }
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
new file mode 100755
index 0000000..76d8e42
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+
+void BP_1I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
+                                  LVM_INT16               *pDataIn,
+                                  LVM_INT16               *pDataOut,
+                                  LVM_INT16               NrSamples)
+
+
+    {
+        LVM_INT32 ynL;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL= (A0 (Q14) * (x(n)L (Q0) - x(n-2)L (Q0) ) )  in Q14
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* ((*pDataIn)-pBiquadState->pDelays[1]);
+
+            // ynL+= ((-B2 (Q14) * y(n-2)L (Q0) ) ) in Q14
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[3];
+
+            // ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) ) in Q14
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]*pBiquadState->pDelays[2];
+
+            ynL=(LVM_INT16)(ynL>>14); // ynL in Q0
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
+            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..9338eb2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BP_1I_D16F16Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_Taps_t   *pTaps,
+                                         BP_C16_Coefs_t            *pCoef)
+{
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays      =(LVM_INT32 *) pTaps;
+
+  pBiquadState->coefs[0]=pCoef->A0;
+  pBiquadState->coefs[1]=pCoef->B2;
+  pBiquadState->coefs[2]=pCoef->B1;
+  }
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D16F16Css_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..2a0d7d5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+#define _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT32         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
new file mode 100755
index 0000000..f52d3db
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q16 format
+***************************************************************************/
+
+void BP_1I_D16F32C30_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
+                                  LVM_INT16               *pDataIn,
+                                  LVM_INT16               *pDataOut,
+                                  LVM_INT16               NrSamples)
+
+
+    {
+        LVM_INT32 ynL,templ;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>14)  in Q16
+            templ= (LVM_INT32) *pDataIn-pBiquadState->pDelays[1];
+            MUL32x32INTO32(pBiquadState->coefs[0],templ,ynL,14)
+
+            // ynL+= ((-B2 (Q30) * y(n-2)L (Q16) ) >>30) in Q16
+            MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[3],templ,30)
+            ynL+=templ;
+
+            // ynL+= ((-B1 (Q30) * y(n-1)L (Q16) ) >>30) in Q16
+            MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[2],templ,30)
+            ynL+=templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q16
+            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=(LVM_INT16)(ynL>>16); // Write Left output in Q0
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..c560085
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                            */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                            */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BP_1I_D16F32Cll_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a Band pass filter (BIQUAD)               */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/*                                                                         */
+/*        The coefficients are modified in the init() function such that lower               */
+/*        half word is right shifted by one and most significant bit of the lower            */
+/*        word is made to be zero.                                                           */
+/*                                                                                           */
+/*       Reason: For MIPS effciency,we are using DSP 32*16 multiplication                    */
+/*       instruction. But we have 32*32 multiplication. This can be realized by two 32*16    */
+/*       multiplication. But 16th bit in the 32 bit word is not a sign bit. So this is done  */
+/*       by putting 16th bit to zero and lossing one bit precision by division of lower      */
+/*       half word by 2.                                                                     */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D16F32Cll_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_Taps_t   *pTaps,
+                                         BP_C32_Coefs_t            *pCoef)
+{
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays       =(LVM_INT32 *) pTaps;
+
+  pBiquadState->coefs[0] =  pCoef->A0;
+  pBiquadState->coefs[1] =  pCoef->B2;
+  pBiquadState->coefs[2] =  pCoef->B1;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D16F32Cll_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..76777f6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
+#define _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT32         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
new file mode 100755
index 0000000..2b3555f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+
+void BP_1I_D32F32C30_TRC_WRA_02 ( Biquad_Instance_t       *pInstance,
+                                  LVM_INT32               *pDataIn,
+                                  LVM_INT32               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_INT32 ynL,templ;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>30)  in Q0
+            templ=(*pDataIn)-pBiquadState->pDelays[1];
+            MUL32x32INTO32(pBiquadState->coefs[0],templ,ynL,30)
+
+            // ynL+= ((-B2 (Q30) * y(n-2)L (Q0) ) >>30) in Q0
+            MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[3],templ,30)
+            ynL+=templ;
+
+            // ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) >>30) in Q0
+            MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[2],templ,30)
+            ynL+=templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
+            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=ynL; // Write Left output in Q0
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
new file mode 100755
index 0000000..f3f4571
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                         */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BP_1I_D32F32Cll_TRC_WRA_02_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D32F32Cll_TRC_WRA_02_Init (   Biquad_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_Taps_t   *pTaps,
+                                         BP_C32_Coefs_t            *pCoef)
+{
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays       =(LVM_INT32 *) pTaps;
+
+  pBiquadState->coefs[0]=pCoef->A0;
+
+  pBiquadState->coefs[1]=pCoef->B2;
+
+  pBiquadState->coefs[2]=pCoef->B1;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D32F32Cll_TRC_WRA_02_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
new file mode 100755
index 0000000..8884537
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
+#define _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT32         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
new file mode 100755
index 0000000..00e3b52
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+
+void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
+                                  LVM_INT16               *pDataIn,
+                                  LVM_INT16               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_INT32  ynL;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2 (Q15) * x(n-2)L (Q0) in Q15
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[1];
+
+            // ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+            // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+            // ynL+=  (-B2 (Q15) * y(n-2)L (Q0) ) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[3];
+
+            // ynL+= (-B1 (Q15) * y(n-1)L (Q0) ) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[2];
+
+            ynL=ynL>>15; // ynL in Q0 format
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
+            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..3fedc45
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                                                                          */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                                                          */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_1I_D16F16Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_1I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_Taps_t   *pTaps,
+                                         BQ_C16_Coefs_t            *pCoef)
+{
+  LVM_INT16 temp;
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
+
+  temp=pCoef->A2;
+  pBiquadState->coefs[0]=temp;
+  temp=pCoef->A1;
+  pBiquadState->coefs[1]=temp;
+  temp=pCoef->A0;
+  pBiquadState->coefs[2]=temp;
+  temp=pCoef->B2;
+  pBiquadState->coefs[3]=temp;
+  temp=pCoef->B1;
+  pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_1I_D16F16Css_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..18dacd3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+#define _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT16         coefs[5];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
new file mode 100755
index 0000000..cdff1d9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q16 format
+***************************************************************************/
+
+void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
+                                  LVM_INT16               *pDataIn,
+                                  LVM_INT16               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_INT32  ynL,templ;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2 (Q14) * x(n-2)L (Q0) in Q14
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[1];
+
+            // ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+            // ynL+=A0 (Q14) * x(n)L (Q0) in Q14
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+            // ynL+= ( (-B2 (Q14) * y(n-2)L (Q16) )>>16) in Q14
+            MUL32x16INTO32(pBiquadState->pDelays[3],pBiquadState->coefs[3],templ,16)
+            ynL+=templ;
+
+            // ynL+= ( (-B1 (Q14) * y(n-1)L (Q16) )>>16) in Q14
+            MUL32x16INTO32(pBiquadState->pDelays[2],pBiquadState->coefs[4],templ,16)
+            ynL+=templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[2];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[1]=pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[2]=ynL<<2;                    // Update y(n-1)L in Q16
+            pBiquadState->pDelays[0]=(*pDataIn++);              // Update x(n-1)L in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=(LVM_INT16)(ynL>>14); // Write Left output in Q0
+
+        }
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..bc88847
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
+#define _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *   pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT16     coefs[5];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
new file mode 100755
index 0000000..520c969
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_1I_D16F32Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_1I_D16F32Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
+                                         Biquad_1I_Order2_Taps_t   *pTaps,
+                                         BQ_C16_Coefs_t            *pCoef)
+{
+  LVM_INT16 temp;
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
+
+  temp=pCoef->A2;
+  pBiquadState->coefs[0]=temp;
+  temp=pCoef->A1;
+  pBiquadState->coefs[1]=temp;
+  temp=pCoef->A0;
+  pBiquadState->coefs[2]=temp;
+  temp=pCoef->B2;
+  pBiquadState->coefs[3]=temp;
+  temp=pCoef->B1;
+  pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_1I_D16F32Css_TRC_WRA_01_Init                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
new file mode 100755
index 0000000..c267a90
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+
+void BQ_2I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
+                                  LVM_INT16               *pDataIn,
+                                  LVM_INT16               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_INT32  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2 (Q14) * x(n-2)L (Q0) in Q14
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+            // ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+            // ynL+=A0 (Q14) * x(n)L (Q0) in Q14
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+            // ynL+= ( -B2 (Q14) * y(n-2)L (Q0) ) in Q14
+            ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[6];
+
+            // ynL+=( -B1 (Q14) * y(n-1)L (Q0) ) in Q14
+            ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[4];
+
+            ynL=ynL>>14; // ynL in Q0 format
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            // ynR=A2 (Q14) * x(n-2)R (Q0) in Q14
+            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+            // ynR+=A1 (Q14) * x(n-1)R (Q0) in Q14
+            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+            // ynR+=A0 (Q14) * x(n)R (Q0) in Q14
+            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+            // ynR+= ( -B2 (Q14) * y(n-2)R (Q0) ) in Q14
+            ynR+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[7];
+
+            // ynR+=( -B1 (Q14) * y(n-1)R (Q0) ) in Q14
+            ynR+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[5];
+
+            ynR=ynR>>14; // ynL in Q0 format
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7]=pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
+            pBiquadState->pDelays[6]=pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
+            pBiquadState->pDelays[2]=pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[5]=ynR;                       // Update y(n-1)R in Q0
+            pBiquadState->pDelays[4]=ynL;                       // Update y(n-1)L in Q0
+            pBiquadState->pDelays[0]=(*pDataIn++);              // Update x(n-1)L in Q0
+            pBiquadState->pDelays[1]=(*pDataIn++);              // Update x(n-1)R in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+            *pDataOut++=(LVM_INT16)ynR; // Write Right ouput in Q0
+
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
new file mode 100755
index 0000000..ded2bb3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+
+void BQ_2I_D16F16C15_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
+                                  LVM_INT16               *pDataIn,
+                                  LVM_INT16               *pDataOut,
+                                  LVM_INT16               NrSamples)
+    {
+        LVM_INT32  ynL,ynR;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A2 (Q15) * x(n-2)L (Q0) in Q15
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+            // ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+            // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+            // ynL+= ( -B2 (Q15) * y(n-2)L (Q0) ) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[6];
+
+            // ynL+=( -B1 (Q15) * y(n-1)L (Q0) ) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[4];
+
+            ynL=ynL>>15; // ynL in Q0 format
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            // ynR=A2 (Q15) * x(n-2)R (Q0) in Q15
+            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+            // ynR+=A1 (Q15) * x(n-1)R (Q0) in Q15
+            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+            // ynR+=A0 (Q15) * x(n)R (Q0) in Q15
+            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+            // ynR+= ( -B2 (Q15) * y(n-2)R (Q0) ) in Q15
+            ynR+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[7];
+
+            // ynR+=( -B1 (Q15) * y(n-1)R (Q0) ) in Q15
+            ynR+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[5];
+
+            ynR=ynR>>15; // ynL in Q0 format
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7]=pBiquadState->pDelays[5];  // y(n-2)R=y(n-1)R
+            pBiquadState->pDelays[6]=pBiquadState->pDelays[4];  // y(n-2)L=y(n-1)L
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[1];  // x(n-2)R=x(n-1)R
+            pBiquadState->pDelays[2]=pBiquadState->pDelays[0];  // x(n-2)L=x(n-1)L
+            pBiquadState->pDelays[5]=ynR;                       // Update y(n-1)R in Q0
+            pBiquadState->pDelays[4]=ynL;                       // Update y(n-1)L in Q0
+            pBiquadState->pDelays[0]=(*pDataIn++);              // Update x(n-1)L in Q0
+            pBiquadState->pDelays[1]=(*pDataIn++);              // Update x(n-1)R in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+            *pDataOut++=(LVM_INT16)ynR; // Write Right ouput in Q0
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..b0cd1b9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                                                                          */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                                                          */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_2I_D16F16Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D16F16Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_Taps_t   *pTaps,
+                                         BQ_C16_Coefs_t            *pCoef)
+{
+  LVM_INT16 temp;
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
+
+  temp=pCoef->A2;
+  pBiquadState->coefs[0]=temp;
+  temp=pCoef->A1;
+  pBiquadState->coefs[1]=temp;
+  temp=pCoef->A0;
+  pBiquadState->coefs[2]=temp;
+  temp=pCoef->B2;
+  pBiquadState->coefs[3]=temp;
+  temp=pCoef->B1;
+  pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D16F16Css_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..bcb0093
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+#define _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *   pDelays;            /* pointer to the delayed samples (data of 32 bits) */
+  LVM_INT16     coefs[5];           /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
new file mode 100755
index 0000000..ae743f2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q13 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+
+void BQ_2I_D16F32C13_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_INT32  ynL,ynR,templ;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2 (Q13) * x(n-2)L (Q0) in Q13*/
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+            /* ynL+=A1 (Q13) * x(n-1)L (Q0) in Q13*/
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+            /* ynL+=A0 (Q13) * x(n)L (Q0) in Q13*/
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+            /* ynL+= ( (-B2 (Q13) * y(n-2)L (Q16) )>>16) in Q13 */
+            MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
+            ynL+=templ;
+
+            /* ynL+=( (-B1 (Q13) * y(n-1)L (Q16) )>>16) in Q13 */
+            MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
+            ynL+=templ;
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2 (Q13) * x(n-2)R (Q0) in Q13*/
+            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+            /* ynR+=A1 (Q13) * x(n-1)R (Q0) in Q13*/
+            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+            /* ynR+=A0 (Q13) * x(n)R (Q0) in Q13*/
+            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+            /* ynR+= ( (-B2 (Q13) * y(n-2)R (Q16) )>>16) in Q13*/
+            MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
+            ynR+=templ;
+
+            /* ynR+=( (-B1 (Q13) * y(n-1)R (Q16) )>>16) in Q13 */
+            MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
+            ynR+=templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7]=pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6]=pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2]=pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5]=ynR<<3;                    /* Update y(n-1)R in Q16*/
+            pBiquadState->pDelays[4]=ynL<<3;                    /* Update y(n-1)L in Q16*/
+            pBiquadState->pDelays[0]=(*pDataIn);                /* Update x(n-1)L in Q0*/
+            pDataIn++;
+            pBiquadState->pDelays[1]=(*pDataIn);                /* Update x(n-1)R in Q0*/
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut=(LVM_INT16)(ynL>>13); /* Write Left output in Q0*/
+            pDataOut++;
+            *pDataOut=(LVM_INT16)(ynR>>13); /* Write Right ouput in Q0*/
+            pDataOut++;
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
new file mode 100755
index 0000000..a0ca2cc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+
+void BQ_2I_D16F32C14_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_INT32  ynL,ynR,templ;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2 (Q14) * x(n-2)L (Q0) in Q14*/
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+            /* ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14*/
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+            /* ynL+=A0 (Q14) * x(n)L (Q0) in Q14*/
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+            /* ynL+= ( (-B2 (Q14) * y(n-2)L (Q16) )>>16) in Q14 */
+            MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
+            ynL+=templ;
+
+            /* ynL+=( (-B1 (Q14) * y(n-1)L (Q16) )>>16) in Q14 */
+            MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
+            ynL+=templ;
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2 (Q14) * x(n-2)R (Q0) in Q14*/
+            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+            /* ynR+=A1 (Q14) * x(n-1)R (Q0) in Q14*/
+            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+            /* ynR+=A0 (Q14) * x(n)R (Q0) in Q14*/
+            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+            /* ynR+= ( (-B2 (Q14) * y(n-2)R (Q16) )>>16) in Q14*/
+            MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
+            ynR+=templ;
+
+            /* ynR+=( (-B1 (Q14) * y(n-1)R (Q16) )>>16) in Q14 */
+            MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
+            ynR+=templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7]=pBiquadState->pDelays[5];  /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6]=pBiquadState->pDelays[4];  /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[1];  /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2]=pBiquadState->pDelays[0];  /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5]=ynR<<2;                    /* Update y(n-1)R in Q16*/
+            pBiquadState->pDelays[4]=ynL<<2;                    /* Update y(n-1)L in Q16*/
+            pBiquadState->pDelays[0]=(*pDataIn);                /* Update x(n-1)L in Q0*/
+            pDataIn++;
+            pBiquadState->pDelays[1]=(*pDataIn);                /* Update x(n-1)R in Q0*/
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut=(LVM_INT16)(ynL>>14); /* Write Left output in Q0*/
+            pDataOut++;
+            *pDataOut=(LVM_INT16)(ynR>>14); /* Write Right ouput in Q0*/
+            pDataOut++;
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
new file mode 100755
index 0000000..f1ab815
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+
+void BQ_2I_D16F32C15_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT16                    *pDataIn,
+                                            LVM_INT16                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+    {
+        LVM_INT32  ynL,ynR,templ;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL=A2 (Q15) * x(n-2)L (Q0) in Q15*/
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+            /* ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15*/
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+            /* ynL+=A0 (Q15) * x(n)L (Q0) in Q15*/
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+            /* ynL+= ( (-B2 (Q15) * y(n-2)L (Q16) )>>16) in Q15 */
+            MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
+            ynL+=templ;
+
+            /* ynL+=( (-B1 (Q15) * y(n-1)L (Q16) )>>16) in Q15 */
+            MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
+            ynL+=templ;
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR=A2 (Q15) * x(n-2)R (Q0) in Q15*/
+            ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+            /* ynR+=A1 (Q15) * x(n-1)R (Q0) in Q15*/
+            ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+            /* ynR+=A0 (Q15) * x(n)R (Q0) in Q15*/
+            ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+            /* ynR+= ( (-B2 (Q15) * y(n-2)R (Q16) )>>16) in Q15 */
+            MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
+            ynR+=templ;
+
+            /* ynR+=( (-B1 (Q15) * y(n-1)R (Q16) )>>16) in Q15 */
+            MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
+            ynR+=templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5]=ynR<<1; /* Update y(n-1)R in Q16*/
+            pBiquadState->pDelays[4]=ynL<<1; /* Update y(n-1)L in Q16*/
+            pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+            pDataIn++;
+            pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut=(LVM_INT16)(ynL>>15); /* Write Left output in Q0*/
+            pDataOut++;
+            *pDataOut=(LVM_INT16)(ynR>>15); /* Write Right ouput in Q0*/
+            pDataOut++;
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..3cbb58b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
+#define _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *                          pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT16                           coefs[5];         /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
new file mode 100755
index 0000000..0c6b33e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#include "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_2I_D16F32Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D16F32Css_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_Taps_t   *pTaps,
+                                         BQ_C16_Coefs_t            *pCoef)
+{
+  LVM_INT16 temp;
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
+
+  temp=pCoef->A2;
+  pBiquadState->coefs[0]=temp;
+  temp=pCoef->A1;
+  pBiquadState->coefs[1]=temp;
+  temp=pCoef->A0;
+  pBiquadState->coefs[2]=temp;
+  temp=pCoef->B2;
+  pBiquadState->coefs[3]=temp;
+  temp=pCoef->B1;
+  pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D16F32Css_TRC_WRA_01_Init                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
new file mode 100755
index 0000000..51278cf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+
+void BQ_2I_D32F32C30_TRC_WRA_01 (           Biquad_Instance_t       *pInstance,
+                                            LVM_INT32                    *pDataIn,
+                                            LVM_INT32                    *pDataOut,
+                                            LVM_INT16                    NrSamples)
+
+
+    {
+        LVM_INT32 ynL,ynR,templ,tempd;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL= ( A2 (Q30) * x(n-2)L (Q0) ) >>30 in Q0*/
+            MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[2],ynL,30)
+
+            /* ynL+= ( A1 (Q30) * x(n-1)L (Q0) ) >> 30 in Q0*/
+            MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[0],templ,30)
+            ynL+=templ;
+
+            /* ynL+= ( A0 (Q30) * x(n)L (Q0) ) >> 30 in Q0*/
+            MUL32x32INTO32(pBiquadState->coefs[2],*pDataIn,templ,30)
+            ynL+=templ;
+
+             /* ynL+= (-B2 (Q30) * y(n-2)L (Q0) ) >> 30 in Q0*/
+            MUL32x32INTO32(pBiquadState->coefs[3],pBiquadState->pDelays[6],templ,30)
+            ynL+=templ;
+
+            /* ynL+= (-B1 (Q30) * y(n-1)L (Q0) ) >> 30 in Q0 */
+            MUL32x32INTO32(pBiquadState->coefs[4],pBiquadState->pDelays[4],templ,30)
+            ynL+=templ;
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR= ( A2 (Q30) * x(n-2)R (Q0) ) >> 30 in Q0*/
+            MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[3],ynR,30)
+
+            /* ynR+= ( A1 (Q30) * x(n-1)R (Q0) ) >> 30  in Q0*/
+            MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[1],templ,30)
+            ynR+=templ;
+
+            /* ynR+= ( A0 (Q30) * x(n)R (Q0) ) >> 30 in Q0*/
+            tempd=*(pDataIn+1);
+            MUL32x32INTO32(pBiquadState->coefs[2],tempd,templ,30)
+            ynR+=templ;
+
+            /* ynR+= (-B2 (Q30) * y(n-2)R (Q0) ) >> 30 in Q0*/
+            MUL32x32INTO32(pBiquadState->coefs[3],pBiquadState->pDelays[7],templ,30)
+            ynR+=templ;
+
+            /* ynR+= (-B1 (Q30) * y(n-1)R (Q0) ) >> 30 in Q0 */
+            MUL32x32INTO32(pBiquadState->coefs[4],pBiquadState->pDelays[5],templ,30)
+            ynR+=templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5]=(LVM_INT32)ynR; /* Update y(n-1)R in Q0*/
+            pBiquadState->pDelays[4]=(LVM_INT32)ynL; /* Update y(n-1)L in Q0*/
+            pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+            pDataIn++;
+            pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut=(LVM_INT32)ynL; /* Write Left output in Q0*/
+            pDataOut++;
+            *pDataOut=(LVM_INT32)ynR; /* Write Right ouput in Q0*/
+            pDataOut++;
+
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..7c460d3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                                                                          */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                                                          */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   BQ_2I_D32F32Cll_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D32F32Cll_TRC_WRA_01_Init (   Biquad_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_Taps_t   *pTaps,
+                                         BQ_C32_Coefs_t            *pCoef)
+{
+  LVM_INT32 temp;
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
+
+  temp=pCoef->A2;
+  pBiquadState->coefs[0]=temp;
+  temp=pCoef->A1;
+  pBiquadState->coefs[1]=temp;
+  temp=pCoef->A0;
+  pBiquadState->coefs[2]=temp;
+  temp=pCoef->B2;
+  pBiquadState->coefs[3]=temp;
+  temp=pCoef->B1;
+  pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D32F32C32_TRC_WRA_01_Init.c                              */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..fb4f2dd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
+#define _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
+
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *                          pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT32                            coefs[5];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/CompLim_private.h b/media/libeffects/lvm/lib/Common/src/CompLim_private.h
new file mode 100755
index 0000000..07a8833
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/CompLim_private.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _COMP_LIM_PRIVATE_
+#define _COMP_LIM_PRIVATE_
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "CompLim.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define FS_48K      48000
+
+#define INTEGER_16  0xFFFF /*   65535*/
+#define INTEGER_15  0x7FFF /*   32767*/
+
+#define GAIN_6DB    1
+#define GAIN_12DB   2
+#define GAIN_18DB   3
+#define GAIN_24DB   4
+
+#endif /* #ifndef _COMP_LIM_PRIVATE_ */
+
+/*** End of file ******************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.c b/media/libeffects/lvm/lib/Common/src/Copy_16.c
new file mode 100755
index 0000000..6ee1ff6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION COPY_16
+***********************************************************************************/
+
+void Copy_16( const LVM_INT16 *src,
+                    LVM_INT16 *dst,
+                    LVM_INT16  n )
+{
+    LVM_INT16 ii;
+
+    if (src > dst)
+    {
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = *src;
+            dst++;
+            src++;
+        }
+    }
+    else
+    {
+        src += n - 1;
+        dst += n - 1;
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = *src;
+            dst--;
+            src--;
+        }
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
new file mode 100755
index 0000000..adac24f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION CORE_MIXHARD_2ST_D32C31_SAT
+***********************************************************************************/
+
+void Core_MixHard_2St_D32C31_SAT(   Mix_2St_Cll_t       *pInstance,
+                                    const LVM_INT32     *src1,
+                                    const LVM_INT32     *src2,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_INT32  Temp1,Temp2,Temp3;
+    LVM_INT16 ii;
+    LVM_INT16 Current1Short;
+    LVM_INT16 Current2Short;
+
+    Current1Short = (LVM_INT16)(pInstance->Current1 >> 16);
+    Current2Short = (LVM_INT16)(pInstance->Current2 >> 16);
+
+    for (ii = n; ii != 0; ii--){
+        Temp1=*src1++;
+        MUL32x16INTO32(Temp1,Current1Short,Temp3,15)
+        Temp2=*src2++;
+        MUL32x16INTO32(Temp2,Current2Short,Temp1,15)
+        Temp2=(Temp1>>1)+(Temp3>>1);
+        if (Temp2 > 0x3FFFFFFF)
+            Temp2 = 0x7FFFFFFF;
+        else if (Temp2 < - 0x40000000)
+            Temp2 =  0x80000000;
+        else
+            Temp2=(Temp2<<1);
+            *dst++ = Temp2;
+    }
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
new file mode 100755
index 0000000..d557f6e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+
+void Core_MixInSoft_D32C31_SAT(     Mix_1St_Cll_t       *pInstance,
+                                    const LVM_INT32     *src,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_INT32    Temp1,Temp2,Temp3;
+    LVM_INT16     OutLoop;
+    LVM_INT16     InLoop;
+    LVM_INT32    TargetTimesOneMinAlpha;
+    LVM_INT32    CurrentTimesAlpha;
+    LVM_INT16     ii,jj;
+    LVM_INT16   CurrentShort;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    MUL32x32INTO32((0x7FFFFFFF-pInstance->Alpha),pInstance->Target,TargetTimesOneMinAlpha,31); /* Q31 * Q0 in Q0 */
+    if (pInstance->Target >= pInstance->Current){
+         TargetTimesOneMinAlpha +=2; /* Ceil*/
+    }
+
+    if (OutLoop){
+        MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31);       /* Q0 * Q31 in Q0 */
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;                /* Q0 + Q0 into Q0*/
+        CurrentShort = (LVM_INT16)(pInstance->Current>>16);                             /* From Q31 to Q15*/
+
+        for (ii = OutLoop; ii != 0; ii--){
+        Temp1=*src++;
+        Temp2=*dst;
+        MUL32x16INTO32(Temp1,CurrentShort,Temp3,15)
+        Temp1=(Temp2>>1)+(Temp3>>1);
+
+        if (Temp1 > 0x3FFFFFFF)
+            Temp1 = 0x7FFFFFFF;
+        else if (Temp1 < - 0x40000000)
+            Temp1 =  0x80000000;
+        else
+            Temp1=(Temp1<<1);
+            *dst++ = Temp1;
+        }
+    }
+
+    for (ii = InLoop; ii != 0; ii--){
+        MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31);       /* Q0 * Q31 in Q0 */
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;                /* Q0 + Q0 into Q0*/
+        CurrentShort = (LVM_INT16)(pInstance->Current>>16);                             /* From Q31 to Q15*/
+
+        for (jj = 4; jj!=0 ; jj--){
+        Temp1=*src++;
+        Temp2=*dst;
+        MUL32x16INTO32(Temp1,CurrentShort,Temp3,15)
+        Temp1=(Temp2>>1)+(Temp3>>1);
+
+        if (Temp1 > 0x3FFFFFFF)
+            Temp1 = 0x7FFFFFFF;
+        else if (Temp1 < - 0x40000000)
+            Temp1 =  0x80000000;
+        else
+            Temp1=(Temp1<<1);
+            *dst++ = Temp1;
+        }
+    }
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
new file mode 100755
index 0000000..7b4e66d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+
+void Core_MixSoft_1St_D32C31_WRA(   Mix_1St_Cll_t       *pInstance,
+                                    const LVM_INT32     *src,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_INT32  Temp1,Temp2;
+    LVM_INT16 OutLoop;
+    LVM_INT16 InLoop;
+    LVM_INT32  TargetTimesOneMinAlpha;
+    LVM_INT32  CurrentTimesAlpha;
+    LVM_INT16 CurrentShort;
+    LVM_INT16 ii;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    MUL32x32INTO32((0x7FFFFFFF-pInstance->Alpha),pInstance->Target,TargetTimesOneMinAlpha,31) /* Q31 * Q31 in Q31 */
+    if (pInstance->Target >= pInstance->Current)
+    {
+         TargetTimesOneMinAlpha +=2; /* Ceil*/
+    }
+
+    if (OutLoop!=0)
+    {
+        MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31)  /* Q31 * Q31 in Q31 */
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;          /* Q31 + Q31 into Q31*/
+        CurrentShort = (LVM_INT16)(pInstance->Current>>16);                       /* From Q31 to Q15*/
+
+        for (ii = OutLoop; ii != 0; ii--)
+        {
+            Temp1=*src;
+            src++;
+
+            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+            *dst = Temp2;
+            dst++;
+        }
+    }
+
+    for (ii = InLoop; ii != 0; ii--)
+    {
+        MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31)  /* Q31 * Q31 in Q31 */
+        pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha;          /* Q31 + Q31 into Q31*/
+        CurrentShort = (LVM_INT16)(pInstance->Current>>16);                       /* From Q31 to Q15*/
+            Temp1=*src;
+            src++;
+
+            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+            *dst = Temp2;
+            dst++;
+
+            Temp1=*src;
+            src++;
+
+            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+            *dst = Temp2;
+            dst++;
+
+            Temp1=*src;
+            src++;
+
+            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+            *dst = Temp2;
+            dst++;
+
+            Temp1=*src;
+            src++;
+            MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+            *dst = Temp2;
+            dst++;
+    }
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
new file mode 100755
index 0000000..187fe68
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "DC_2I_D16_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+void DC_2I_D16_TRC_WRA_01( Biquad_Instance_t       *pInstance,
+                           LVM_INT16               *pDataIn,
+                           LVM_INT16               *pDataOut,
+                           LVM_INT16               NrSamples)
+    {
+        LVM_INT32 LeftDC,RightDC;
+        LVM_INT32 Diff;
+        LVM_INT32 j;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+        LeftDC  =   pBiquadState->LeftDC;
+        RightDC =   pBiquadState->RightDC;
+        for(j=NrSamples-1;j>=0;j--)
+        {
+            /* Subtract DC an saturate */
+            Diff=*(pDataIn++)-(LeftDC>>16);
+            if (Diff > 32767) {
+                Diff = 32767; }
+            else if (Diff < -32768) {
+                Diff = -32768; }
+            *(pDataOut++)=(LVM_INT16)Diff;
+            if (Diff < 0) {
+                LeftDC -= DC_D16_STEP; }
+            else {
+                LeftDC += DC_D16_STEP; }
+
+
+            /* Subtract DC an saturate */
+            Diff=*(pDataIn++)-(RightDC>>16);
+            if (Diff > 32767) {
+                Diff = 32767; }
+            else if (Diff < -32768) {
+                Diff = -32768; }
+            *(pDataOut++)=(LVM_INT16)Diff;
+            if (Diff < 0) {
+                RightDC -= DC_D16_STEP; }
+            else {
+                RightDC += DC_D16_STEP; }
+
+        }
+        pBiquadState->LeftDC    =   LeftDC;
+        pBiquadState->RightDC   =   RightDC;
+
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..292641b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "DC_2I_D16_TRC_WRA_01_Private.h"
+
+void  DC_2I_D16_TRC_WRA_01_Init(Biquad_Instance_t   *pInstance)
+{
+    PFilter_State pBiquadState  = (PFilter_State) pInstance;
+    pBiquadState->LeftDC        = 0;
+    pBiquadState->RightDC       = 0;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..2514a77
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
+#define _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
+
+#define DC_D16_STEP     0x200;
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.*/
+typedef struct _Filter_State_
+{
+  LVM_INT32  LeftDC;     /* LeftDC  */
+  LVM_INT32  RightDC;    /* RightDC  */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _DC_2I_D16_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
new file mode 100755
index 0000000..cda72ac
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION DelayAllPass_32x32
+***********************************************************************************/
+
+void DelayAllPass_Sat_32x16To32(  LVM_INT32  *delay,                    /* Delay buffer */
+                                  LVM_UINT16 size,                      /* Delay size */
+                                  LVM_INT16 coeff,                      /* All pass filter coefficient */
+                                  LVM_UINT16 DelayOffset,               /* Simple delay offset */
+                                  LVM_UINT16 *pAllPassOffset,           /* All pass filter delay offset */
+                                  LVM_INT32  *dst,                      /* Source/destination */
+                                  LVM_INT16 n)                          /* Number of  samples */
+{
+    LVM_INT16   i;
+    LVM_UINT16   AllPassOffset = *pAllPassOffset;
+    LVM_INT32    temp;
+    LVM_INT32    a,b,c;
+
+    for (i = 0; i < n; i++)
+    {
+
+        MUL32x16INTO32(delay[AllPassOffset], coeff, temp, 15)
+        a = temp;
+        b = delay[DelayOffset];
+        DelayOffset++;
+
+        c = a + b;
+        if ((((c ^ a) & (c ^ b)) >> 31) != 0)  /* overflow / underflow */
+        {
+            if(a < 0)
+            {
+                c = 0x80000000l;
+            }
+            else
+            {
+                c = 0x7FFFFFFFl;
+            }
+        }
+        *dst = c;
+        dst++;
+
+
+        MUL32x16INTO32(c, -coeff, temp, 15)
+        a = temp;
+        b = delay[AllPassOffset];
+        c = a + b;
+        if ((((c ^ a) & (c ^ b)) >> 31)!=0)  /* overflow / underflow */
+        {
+            if(a < 0)
+            {
+                c = 0x80000000l;
+            }
+            else
+            {
+                c = 0x7FFFFFFFl;
+            }
+        }
+        delay[AllPassOffset] = c;
+        AllPassOffset++;
+
+        /* Make the delay buffer a circular buffer */
+        if (DelayOffset >= size)
+        {
+            DelayOffset = 0;
+        }
+
+        if (AllPassOffset >= size)
+        {
+            AllPassOffset = 0;
+        }
+    }
+
+    /* Update the offset */
+    *pAllPassOffset = AllPassOffset;
+
+    return;
+}
+
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
new file mode 100755
index 0000000..ee41701
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION DelayMix_16x16
+***********************************************************************************/
+
+void DelayMix_16x16(const LVM_INT16 *src,           /* Source 1, to be delayed */
+                          LVM_INT16 *delay,         /* Delay buffer */
+                          LVM_INT16 size,           /* Delay size */
+                          LVM_INT16 *dst,           /* Source/destination */
+                          LVM_INT16 *pOffset,       /* Delay offset */
+                          LVM_INT16 n)              /* Number of stereo samples */
+{
+    LVM_INT16   i;
+    LVM_INT16   Offset  = *pOffset;
+    LVM_INT16   temp;
+
+    for (i=0; i<n; i++)
+    {
+        /* Left channel */
+        temp            = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
+        *dst            = temp;
+        dst++;
+
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+
+        /* Right channel */
+        temp            = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
+        *dst            = temp;
+        dst++;
+
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+        /* Make the reverb delay buffer a circular buffer */
+        if (Offset >= size)
+        {
+            Offset = 0;
+        }
+    }
+
+    /* Update the offset */
+    *pOffset = Offset;
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.c b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.c
new file mode 100755
index 0000000..0ae4c42
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION DelayMix_16x16
+***********************************************************************************/
+
+void DelayWrite_32(const LVM_INT32  *src,               /* Source 1, to be delayed */
+                         LVM_INT32  *delay,             /* Delay buffer */
+                         LVM_UINT16 size,               /* Delay size */
+                         LVM_UINT16 *pOffset,           /* Delay offset */
+                         LVM_INT16  n)                  /* Number of samples */
+{
+    LVM_INT16   i;
+    LVM_INT16   Offset  = (LVM_INT16)*pOffset;
+
+    for (i=0; i<n; i++)
+    {
+        delay[Offset] = *src;
+        Offset++;
+        src++;
+
+        /* Make the delay buffer a circular buffer */
+        if (Offset >= size)
+        {
+            Offset = 0;
+        }
+    }
+
+    /* Update the offset */
+    *pOffset = (LVM_UINT16)Offset;
+
+    return;
+}
+
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
new file mode 100755
index 0000000..831a115
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A1,
+ pBiquadState->coefs[1] is A0,
+ pBiquadState->coefs[2] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is y(n-1)L in Q0 format
+***************************************************************************/
+
+void FO_1I_D16F16C15_TRC_WRA_01( Biquad_Instance_t       *pInstance,
+                                 LVM_INT16               *pDataIn,
+                                 LVM_INT16               *pDataOut,
+                                 LVM_INT16               NrSamples)
+    {
+        LVM_INT32  ynL;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A1 (Q15) * x(n-1)L (Q0) in Q15
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[0];
+
+            // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* (*pDataIn);
+
+            // ynL+=  (-B1 (Q15) * y(n-1)L (Q0) ) in Q15
+            ynL+=(LVM_INT32)pBiquadState->coefs[2]*pBiquadState->pDelays[1];
+
+
+            ynL=(LVM_INT16)(ynL>>15); // ynL in Q0 format
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q0
+            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..4675084
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   FO_1I_D16F16Css_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void FO_1I_D16F16Css_TRC_WRA_01_Init(    Biquad_Instance_t         *pInstance,
+                                         Biquad_1I_Order1_Taps_t   *pTaps,
+                                         FO_C16_Coefs_t            *pCoef)
+{
+  LVM_INT16 temp;
+  PFilter_State pBiquadState = (PFilter_State)  pInstance;
+  pBiquadState->pDelays      =(LVM_INT32 *)     pTaps;
+
+  temp=pCoef->A1;
+  pBiquadState->coefs[0]=temp;
+  temp=pCoef->A0;
+  pBiquadState->coefs[1]=temp;
+  temp=pCoef->B1;
+  pBiquadState->coefs[2]=temp;
+}
+/*------------------------------------------------*/
+/* End Of File: FO_1I_D16F16Css_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..e1a818c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+#define _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $             */
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32*        pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT16         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
new file mode 100755
index 0000000..9bdc5b4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A1,
+ pBiquadState->coefs[1] is A0,
+ pBiquadState->coefs[2] is -B1, these are in Q31 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is y(n-1)L in Q0 format
+***************************************************************************/
+
+void FO_1I_D32F32C31_TRC_WRA_01( Biquad_Instance_t       *pInstance,
+                                 LVM_INT32               *pDataIn,
+                                 LVM_INT32               *pDataOut,
+                                 LVM_INT16               NrSamples)
+    {
+        LVM_INT32  ynL,templ;
+        LVM_INT16  ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            // ynL=A1 (Q31) * x(n-1)L (Q0) >>31 in Q0
+            MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[0],ynL,31)
+
+            // ynL+=A0 (Q31) * x(n)L (Q0) >> 31 in Q0
+            MUL32x32INTO32(pBiquadState->coefs[1],*pDataIn,templ,31)
+            ynL+=templ;
+
+            // ynL+=  (-B1 (Q31) * y(n-1)L (Q0) ) >> 31 in Q0
+            MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[1],templ,31)
+            ynL+=templ;
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q0
+            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut++=(LVM_INT32)ynL; // Write Left output in Q0
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..eea0b64
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   FO_1I_D32F32Cll_TRC_WRA_01_Init                                       */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_Instance_t         *pInstance,
+                                      Biquad_1I_Order1_Taps_t   *pTaps,
+                                      FO_C32_Coefs_t            *pCoef)
+{
+  LVM_INT32 temp;
+  PFilter_State pBiquadState = (PFilter_State)  pInstance;
+  pBiquadState->pDelays      = (LVM_INT32 *)    pTaps;
+
+  temp=pCoef->A1;
+  pBiquadState->coefs[0]=temp;
+  temp=pCoef->A0;
+  pBiquadState->coefs[1]=temp;
+  temp=pCoef->B1;
+  pBiquadState->coefs[2]=temp;
+}
+/*------------------------------------------------*/
+/* End Of File: FO_1I_D32F32Cll_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..9329150
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#ifndef _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
+#define _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
+
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT32         coefs[3];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
new file mode 100755
index 0000000..4b219a2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ASSUMPTIONS:
+COEFS-
+pBiquadState->coefs[0] is A1,
+pBiquadState->coefs[1] is A0,
+pBiquadState->coefs[2] is -B1, these are in Q15 format
+pBiquadState->Shift    is Shift value
+DELAYS-
+pBiquadState->pDelays[0] is x(n-1)L in Q15 format
+pBiquadState->pDelays[1] is y(n-1)L in Q30 format
+pBiquadState->pDelays[2] is x(n-1)R in Q15 format
+pBiquadState->pDelays[3] is y(n-1)R in Q30 format
+***************************************************************************/
+
+void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t       *pInstance,
+                                     LVM_INT16               *pDataIn,
+                                     LVM_INT16               *pDataOut,
+                                     LVM_INT16               NrSamples)
+    {
+        LVM_INT32   ynL,ynR;
+        LVM_INT32   Temp;
+        LVM_INT32   NegSatValue;
+        LVM_INT16   ii;
+        LVM_INT16   Shift;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+        NegSatValue = LVM_MAXINT_16 +1;
+        NegSatValue = -NegSatValue;
+
+        Shift = pBiquadState->Shift;
+
+
+        for (ii = NrSamples; ii != 0; ii--)
+        {
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+
+            // ynL =A1 (Q15) * x(n-1)L (Q15) in Q30
+            ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[0];
+            // ynR =A1 (Q15) * x(n-1)R (Q15) in Q30
+            ynR=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+
+            // ynL+=A0 (Q15) * x(n)L (Q15) in Q30
+            ynL+=(LVM_INT32)pBiquadState->coefs[1]* (*pDataIn);
+            // ynR+=A0 (Q15) * x(n)L (Q15) in Q30
+            ynR+=(LVM_INT32)pBiquadState->coefs[1]* (*(pDataIn+1));
+
+
+            // ynL +=  (-B1 (Q15) * y(n-1)L (Q30) ) in Q30
+            MUL32x16INTO32(pBiquadState->pDelays[1],pBiquadState->coefs[2],Temp,15);
+            ynL +=Temp;
+            // ynR +=  (-B1 (Q15) * y(n-1)R (Q30) ) in Q30
+            MUL32x16INTO32(pBiquadState->pDelays[3],pBiquadState->coefs[2],Temp,15);
+            ynR +=Temp;
+
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q30
+            pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q15
+
+            pBiquadState->pDelays[3]=ynR; // Update y(n-1)R in Q30
+            pBiquadState->pDelays[2]=(*pDataIn++); // Update x(n-1)R in Q15
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            /*Apply shift: Instead of left shift on 16-bit result, right shift of (15-shift) is applied
+              for better SNR*/
+            ynL = ynL>>(15-Shift);
+            ynR = ynR>>(15-Shift);
+
+            /*Saturate results*/
+            if(ynL > LVM_MAXINT_16)
+            {
+                ynL = LVM_MAXINT_16;
+            }
+            else
+            {
+                if(ynL < NegSatValue)
+                {
+                    ynL = NegSatValue;
+                }
+            }
+
+            if(ynR > LVM_MAXINT_16)
+            {
+                ynR = LVM_MAXINT_16;
+            }
+            else
+            {
+                if(ynR < NegSatValue)
+                {
+                    ynR = NegSatValue;
+                }
+            }
+
+            *pDataOut++=(LVM_INT16)ynL;
+            *pDataOut++=(LVM_INT16)ynR;
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..7f212f5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   FO_2I_D16F32Css_LShx_TRC_WRA_01_Init                                  */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   These functions initializes a BIQUAD filter defined as a cascade of   */
+/*   biquadratic Filter Sections.                                          */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*   pInstance    - output, returns the pointer to the State Variable      */
+/*                   This state pointer must be passed to any subsequent   */
+/*                   call to "Biquad" functions.                           */
+/*   pTaps         - input, pointer to the taps memory                     */
+/*   pCoef         - input, pointer to the coefficient structure           */
+/*   N             - M coefficient factor of QM.N                          */
+/* RETURNS:                                                                */
+/*   void return code                                                      */
+/*-------------------------------------------------------------------------*/
+void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
+                                          Biquad_2I_Order1_Taps_t   *pTaps,
+                                          FO_C16_LShx_Coefs_t        *pCoef)
+{
+  LVM_INT16 temp;
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays      =(LVM_INT32 *) pTaps            ;
+
+  temp=pCoef->A1;
+  pBiquadState->coefs[0]=temp;
+  temp=pCoef->A0;
+  pBiquadState->coefs[1]=temp;
+  temp=pCoef->B1;
+  pBiquadState->coefs[2]=temp;
+
+  temp=pCoef->Shift;
+  pBiquadState->Shift = temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c                     */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..6a4564a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
+#define _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32     *pDelays;       /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT16     coefs[3];       /* pointer to the filter coefficients */
+  LVM_INT16     Shift;          /* Shift value*/
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/Filters.h b/media/libeffects/lvm/lib/Common/src/Filters.h
new file mode 100755
index 0000000..a274f32
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Filters.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1001 $
+     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef FILTERS_H
+#define FILTERS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "LVM_Types.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Structures                                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Biquad with coefficients A0, A1, A2, B1 and B2 coefficients
+ */
+/* Single precision (16-bit) Biquad section coefficients */
+typedef struct
+{
+        LVM_INT16   A0;
+        LVM_INT16   A1;
+        LVM_INT16   A2;
+        LVM_INT16   B1;
+        LVM_INT16   B2;
+        LVM_UINT16  Scale;
+} BiquadA012B12CoefsSP_t;
+
+
+/*
+ * Biquad with coefficients A0, A1 and B1 coefficients
+ */
+/* Single precision (16-bit) Biquad section coefficients */
+typedef struct
+{
+        LVM_INT16   A0;
+        LVM_INT16   A1;
+        LVM_INT16   B1;
+        LVM_UINT16  Scale;
+} BiquadA01B1CoefsSP_t;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif      /* FILTERS_H */
+
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
new file mode 100755
index 0000000..fb00768
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION  From2iToMS_16x16
+***********************************************************************************/
+
+void From2iToMS_16x16( const LVM_INT16  *src,
+                             LVM_INT16  *dstM,
+                             LVM_INT16  *dstS,
+                             LVM_INT16  n )
+{
+    LVM_INT32 temp1,left,right;
+    LVM_INT16 ii;
+    for (ii = n; ii != 0; ii--)
+    {
+        left = (LVM_INT32)*src;
+        src++;
+
+        right = (LVM_INT32)*src;
+        src++;
+
+        /* Compute M signal*/
+        temp1 =  (left+right)>>1;
+        *dstM = (LVM_INT16)temp1;
+        dstM++;
+
+        /* Compute S signal*/
+        temp1 =  (left-right)>>1;
+        *dstS = (LVM_INT16)temp1;
+        dstS++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.c b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.c
new file mode 100755
index 0000000..0ebb4ae
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION From2iToMono_16
+***********************************************************************************/
+
+void From2iToMono_16( const LVM_INT16 *src,
+                            LVM_INT16 *dst,
+                            LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT32 Temp;
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = (LVM_INT32)*src;
+        src++;
+
+        Temp += (LVM_INT32)*src;
+        src++;
+
+        *dst  = (LVM_INT16)(Temp >>1);
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
new file mode 100755
index 0000000..5181368
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION From2iToMono_32
+***********************************************************************************/
+
+void From2iToMono_32( const LVM_INT32 *src,
+                            LVM_INT32 *dst,
+                            LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT32 Temp;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = (*src>>1);
+        src++;
+
+        Temp +=(*src>>1);
+        src++;
+
+        *dst = Temp;
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/InstAlloc.c b/media/libeffects/lvm/lib/Common/src/InstAlloc.c
new file mode 100755
index 0000000..ff900e0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/InstAlloc.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "InstAlloc.h"
+
+/****************************************************************************************
+ *  Name        : InstAlloc_Init()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+                  StartAddr - Base address of the instance memory
+ *  Returns     : Error code
+ *  Description : Initializes the instance distribution and memory size calculation function
+ *  Remarks     :
+ ****************************************************************************************/
+
+void    InstAlloc_Init( INST_ALLOC      *pms,
+                        void            *StartAddr )
+{
+    pms->TotalSize = 3;
+    pms->pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);/* This code will fail if the platform address space is more than 32-bits*/
+}
+
+
+/****************************************************************************************
+ *  Name        : InstAlloc_AddMember()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+                  Size - The size in bytes of the new added member
+ *  Returns     : A pointer to the new added member
+ *  Description : Allocates space for a new member in the instance memory and returns
+                  a pointer to this new member.  The start address of all members will
+                  be 32 bit alligned.
+ *  Remarks     :
+ ****************************************************************************************/
+
+void*   InstAlloc_AddMember( INST_ALLOC         *pms,
+                             LVM_UINT32           Size )
+{
+    void *NewMemberAddress; /* Variable to temporarily store the return value */
+    NewMemberAddress = (void*)pms->pNextMember;
+
+    Size = ((Size + 3) & 0xFFFFFFFC); /* Ceil the size to a multiple of four */
+
+    pms->TotalSize += Size;
+    pms->pNextMember += Size;
+
+    return(NewMemberAddress);
+}
+
+
+/****************************************************************************************
+ *  Name        : InstAlloc_GetTotal()
+ *  Input       : pms  - Pointer to the INST_ALLOC instance
+ *  Returns     : The instance memory size
+ *  Description : This functions returns the calculated instance memory size
+ *  Remarks     :
+ ****************************************************************************************/
+
+LVM_UINT32 InstAlloc_GetTotal( INST_ALLOC *pms)
+{
+    if (pms->TotalSize > 3)
+    {
+        return(pms->TotalSize);
+    }
+    else
+    {
+        return 0;           /* No memory added */
+    }
+}
+
+
+void    InstAlloc_InitAll( INST_ALLOC                      *pms,
+                           LVM_MemoryTable_st             *pMemoryTable)
+{
+    LVM_UINT32 StartAddr;
+
+    StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress;
+
+    pms[0].TotalSize = 3;
+    pms[0].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+
+
+    StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress;
+
+    pms[1].TotalSize = 3;
+    pms[1].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+
+
+    StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress;
+
+    pms[2].TotalSize = 3;
+    pms[2].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+
+
+    StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress;
+
+    pms[3].TotalSize = 3;
+    pms[3].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+
+}
+
+/****************************************************************************************
+ *  Name        : InstAlloc_InitAll_NULL()
+ *  Input       : pms  - Pointer to array of four INST_ALLOC instances
+ *  Returns     : Nothing
+ *  Description : This function reserves Size of 3 bytes for all memory regions and
+ *                intializes pNextMember for all regions to 0
+ *  Remarks     :
+ ****************************************************************************************/
+
+void    InstAlloc_InitAll_NULL( INST_ALLOC  *pms)
+{
+    pms[0].TotalSize = 3;
+    pms[0].pNextMember = 0;
+
+
+    pms[1].TotalSize = 3;
+    pms[1].pNextMember = 0;
+
+    pms[2].TotalSize = 3;
+    pms[2].pNextMember = 0;
+
+    pms[3].TotalSize = 3;
+    pms[3].pNextMember = 0;
+
+}
+
+
+void*   InstAlloc_AddMemberAll( INST_ALLOC                     *pms,
+                                 LVM_UINT32                   Size[],
+                                 LVM_MemoryTable_st           *pMemoryTable)
+{
+    void *NewMemberAddress; /* Variable to temporarily store the return value */
+
+    /* coverity[returned_pointer] Ignore coverity warning that ptr is not used */
+    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
+
+    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_SLOW_DATA]);
+    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type         = LVM_PERSISTENT_SLOW_DATA;
+    pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
+
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_DATA]);
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type         = LVM_PERSISTENT_FAST_DATA;
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
+
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size         = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_COEF]);
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type         = LVM_PERSISTENT_FAST_COEF;
+    pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+    NewMemberAddress = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
+
+    pMemoryTable->Region[LVM_TEMPORARY_FAST].Size                 = InstAlloc_GetTotal(&pms[LVM_TEMPORARY_FAST]);
+    pMemoryTable->Region[LVM_TEMPORARY_FAST].Type                 = LVM_TEMPORARY_FAST;
+    pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress         = LVM_NULL;
+
+    return(NewMemberAddress);
+}
+
+
+void*   InstAlloc_AddMemberAllRet(     INST_ALLOC                 *pms,
+                                     LVM_UINT32               Size[],
+                                     void                    **ptr)
+{
+    ptr[0] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
+    ptr[1] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
+    ptr[2] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
+    ptr[3] = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
+
+    return (ptr[0]);
+}
diff --git a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c
new file mode 100755
index 0000000..e6be756
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION INT16LSHIFTTOINT32_16X32
+***********************************************************************************/
+
+void Int16LShiftToInt32_16x32(const LVM_INT16   *src,
+                              LVM_INT32         *dst,
+                              LVM_INT16         n,
+                              LVM_INT16         shift )
+{
+    LVM_INT16 ii;
+
+    src += n-1;
+    dst += n-1;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = ( ((LVM_INT32)*src) << shift);
+        src--;
+        dst--;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c
new file mode 100755
index 0000000..b21eef5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION INT32RSHIFTTOINT16_SAT_32X16
+***********************************************************************************/
+
+void Int32RShiftToInt16_Sat_32x16(const LVM_INT32  *src,
+                                  LVM_INT16 *dst,
+                                  LVM_INT16 n,
+                                  LVM_INT16 shift )
+{
+    LVM_INT32 temp;
+    LVM_INT16 ii;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        temp = *src >> shift;
+        src++;
+
+        if (temp > 0x00007FFF)
+        {
+            *dst = 0x7FFF;
+        }
+        else if (temp < -0x00008000)
+        {
+            *dst = - 0x8000;
+        }
+        else
+        {
+            *dst = (LVM_INT16)temp;
+        }
+
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
new file mode 100755
index 0000000..e04f1c3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION JoinTo2i_32x32
+***********************************************************************************/
+
+void JoinTo2i_32x32( const LVM_INT32    *srcL,
+                     const LVM_INT32    *srcR,
+                           LVM_INT32    *dst,
+                           LVM_INT16    n )
+{
+    LVM_INT16 ii;
+
+    srcL += n-1;
+    srcR += n-1;
+    dst  += ((2*n)-1);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *srcR;
+        dst--;
+        srcR--;
+
+        *dst = *srcL;
+        dst--;
+        srcL--;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
new file mode 100755
index 0000000..c1d2b2c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+
+/**********************************************************************************
+   FUNCTION LVC_Core_MixHard_1St_2i_D16C31_SAT
+***********************************************************************************/
+
+void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st        *ptrInstance1,
+                                         LVMixer3_st        *ptrInstance2,
+                                         const LVM_INT16    *src,
+                                         LVM_INT16          *dst,
+                                         LVM_INT16          n)
+{
+    LVM_INT32  Temp;
+    LVM_INT16 ii;
+    LVM_INT16 Current1Short;
+    LVM_INT16 Current2Short;
+    Mix_Private_st  *pInstance1=(Mix_Private_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_st  *pInstance2=(Mix_Private_st *)(ptrInstance2->PrivateParams);
+
+
+    Current1Short = (LVM_INT16)(pInstance1->Current >> 16);
+    Current2Short = (LVM_INT16)(pInstance2->Current >> 16);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        Temp = ((LVM_INT32)*(src++) * (LVM_INT32)Current1Short)>>15;
+        if (Temp > 0x00007FFF)
+            *dst++ = 0x7FFF;
+        else if (Temp < -0x00008000)
+            *dst++ = - 0x8000;
+        else
+            *dst++ = (LVM_INT16)Temp;
+
+        Temp = ((LVM_INT32)*(src++) * (LVM_INT32)Current2Short)>>15;
+        if (Temp > 0x00007FFF)
+            *dst++ = 0x7FFF;
+        else if (Temp < -0x00008000)
+            *dst++ = - 0x8000;
+        else
+            *dst++ = (LVM_INT16)Temp;
+    }
+
+
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
new file mode 100755
index 0000000..2bb212c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+
+/**********************************************************************************
+   FUNCTION LVCore_MIXHARD_2ST_D16C31_SAT
+***********************************************************************************/
+
+void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_st *ptrInstance1,
+                                    LVMixer3_st         *ptrInstance2,
+                                    const LVM_INT16     *src1,
+                                    const LVM_INT16     *src2,
+                                          LVM_INT16     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_INT32  Temp;
+    LVM_INT16 ii;
+    LVM_INT16 Current1Short;
+    LVM_INT16 Current2Short;
+    Mix_Private_st  *pInstance1=(Mix_Private_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_st  *pInstance2=(Mix_Private_st *)(ptrInstance2->PrivateParams);
+
+
+    Current1Short = (LVM_INT16)(pInstance1->Current >> 16);
+    Current2Short = (LVM_INT16)(pInstance2->Current >> 16);
+
+    for (ii = n; ii != 0; ii--){
+        Temp = (((LVM_INT32)*(src1++) * (LVM_INT32)Current1Short)>>15) +
+               (((LVM_INT32)*(src2++) * (LVM_INT32)Current2Short)>>15);
+        if (Temp > 0x00007FFF)
+            *dst++ = 0x7FFF;
+        else if (Temp < -0x00008000)
+            *dst++ = - 0x8000;
+        else
+            *dst++ = (LVM_INT16)Temp;
+    }
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
new file mode 100755
index 0000000..0408f42
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
+***********************************************************************************/
+
+void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *ptrInstance,
+                                    const LVM_INT16     *src,
+                                          LVM_INT16     *dst,
+                                          LVM_INT16     n)
+{
+
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT16   CurrentShort;
+    LVM_INT32   ii,jj;
+    Mix_Private_st  *pInstance=(Mix_Private_st *)(ptrInstance->PrivateParams);
+    LVM_INT32   Delta=pInstance->Delta;
+    LVM_INT32   Current=pInstance->Current;
+    LVM_INT32   Target=pInstance->Target;
+    LVM_INT32   Temp;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if(Current<Target){
+        if (OutLoop){
+            ADD2_SAT_32x32(Current,Delta,Temp);                                      /* Q31 + Q31 into Q31*/
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
+
+            for (ii = OutLoop; ii != 0; ii--){
+                Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15);      /* Q15 + Q15*Q15>>15 into Q15 */
+                if (Temp > 0x00007FFF)
+                    *dst++ = 0x7FFF;
+                else if (Temp < -0x00008000)
+                    *dst++ = - 0x8000;
+                else
+                    *dst++ = (LVM_INT16)Temp;
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            ADD2_SAT_32x32(Current,Delta,Temp);                                      /* Q31 + Q31 into Q31*/
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
+
+            for (jj = 4; jj!=0 ; jj--){
+                Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15);      /* Q15 + Q15*Q15>>15 into Q15 */
+                if (Temp > 0x00007FFF)
+                    *dst++ = 0x7FFF;
+                else if (Temp < -0x00008000)
+                    *dst++ = - 0x8000;
+                else
+                    *dst++ = (LVM_INT16)Temp;
+            }
+        }
+    }
+    else{
+        if (OutLoop){
+            Current -= Delta;                                                        /* Q31 + Q31 into Q31*/
+            if (Current < Target)
+                Current = Target;
+
+            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
+
+            for (ii = OutLoop; ii != 0; ii--){
+                Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15);      /* Q15 + Q15*Q15>>15 into Q15 */
+                if (Temp > 0x00007FFF)
+                    *dst++ = 0x7FFF;
+                else if (Temp < -0x00008000)
+                    *dst++ = - 0x8000;
+                else
+                    *dst++ = (LVM_INT16)Temp;
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            Current -= Delta;                                                        /* Q31 + Q31 into Q31*/
+            if (Current < Target)
+                Current = Target;
+
+            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
+
+            for (jj = 4; jj!=0 ; jj--){
+                Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15);      /* Q15 + Q15*Q15>>15 into Q15 */
+                if (Temp > 0x00007FFF)
+                    *dst++ = 0x7FFF;
+                else if (Temp < -0x00008000)
+                    *dst++ = - 0x8000;
+                else
+                    *dst++ = (LVM_INT16)Temp;
+            }
+        }
+    }
+    pInstance->Current=Current;
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
new file mode 100755
index 0000000..2847d47
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "ScalarArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION LVC_Core_MixSoft_1St_2i_D16C31_WRA
+***********************************************************************************/
+
+void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st        *ptrInstance1,
+                                         LVMixer3_st        *ptrInstance2,
+                                         const LVM_INT16    *src,
+                                         LVM_INT16          *dst,
+                                         LVM_INT16          n)
+{
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT16   CurrentShortL;
+    LVM_INT16   CurrentShortR;
+    LVM_INT32   ii;
+    Mix_Private_st  *pInstanceL=(Mix_Private_st *)(ptrInstance1->PrivateParams);
+    Mix_Private_st  *pInstanceR=(Mix_Private_st *)(ptrInstance2->PrivateParams);
+
+    LVM_INT32   DeltaL=pInstanceL->Delta;
+    LVM_INT32   CurrentL=pInstanceL->Current;
+    LVM_INT32   TargetL=pInstanceL->Target;
+
+    LVM_INT32   DeltaR=pInstanceR->Delta;
+    LVM_INT32   CurrentR=pInstanceR->Current;
+    LVM_INT32   TargetR=pInstanceR->Target;
+
+    LVM_INT32   Temp;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if (OutLoop)
+    {
+        if(CurrentL<TargetL)
+        {
+            ADD2_SAT_32x32(CurrentL,DeltaL,Temp);                                      /* Q31 + Q31 into Q31*/
+            CurrentL=Temp;
+            if (CurrentL > TargetL)
+                CurrentL = TargetL;
+        }
+        else
+        {
+            CurrentL -= DeltaL;                                                        /* Q31 + Q31 into Q31*/
+            if (CurrentL < TargetL)
+                CurrentL = TargetL;
+        }
+
+        if(CurrentR<TargetR)
+        {
+            ADD2_SAT_32x32(CurrentR,DeltaR,Temp);                                      /* Q31 + Q31 into Q31*/
+            CurrentR=Temp;
+            if (CurrentR > TargetR)
+                CurrentR = TargetR;
+        }
+        else
+        {
+            CurrentR -= DeltaR;                                                        /* Q31 + Q31 into Q31*/
+            if (CurrentR < TargetR)
+                CurrentR = TargetR;
+        }
+
+        CurrentShortL = (LVM_INT16)(CurrentL>>16);                                 /* From Q31 to Q15*/
+        CurrentShortR = (LVM_INT16)(CurrentR>>16);                                 /* From Q31 to Q15*/
+
+        for (ii = OutLoop*2; ii != 0; ii-=2)
+        {
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);    /* Q15*Q15>>15 into Q15 */
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);    /* Q15*Q15>>15 into Q15 */
+        }
+    }
+
+    for (ii = InLoop*2; ii != 0; ii-=2)
+    {
+        if(CurrentL<TargetL)
+        {
+            ADD2_SAT_32x32(CurrentL,DeltaL,Temp);                                      /* Q31 + Q31 into Q31*/
+            CurrentL=Temp;
+            if (CurrentL > TargetL)
+                CurrentL = TargetL;
+        }
+        else
+        {
+            CurrentL -= DeltaL;                                                        /* Q31 + Q31 into Q31*/
+            if (CurrentL < TargetL)
+                CurrentL = TargetL;
+        }
+
+        if(CurrentR<TargetR)
+        {
+            ADD2_SAT_32x32(CurrentR,DeltaR,Temp);                                      /* Q31 + Q31 into Q31*/
+            CurrentR=Temp;
+            if (CurrentR > TargetR)
+                CurrentR = TargetR;
+        }
+        else
+        {
+            CurrentR -= DeltaR;                                                        /* Q31 + Q31 into Q31*/
+            if (CurrentR < TargetR)
+                CurrentR = TargetR;
+        }
+
+        CurrentShortL = (LVM_INT16)(CurrentL>>16);                                 /* From Q31 to Q15*/
+        CurrentShortR = (LVM_INT16)(CurrentR>>16);                                 /* From Q31 to Q15*/
+
+        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);    /* Q15*Q15>>15 into Q15 */
+        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);    /* Q15*Q15>>15 into Q15 */
+        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
+        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
+        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
+        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
+        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
+        *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
+    }
+    pInstanceL->Current=CurrentL;
+    pInstanceR->Current=CurrentR;
+
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
new file mode 100755
index 0000000..78f0122
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
+***********************************************************************************/
+
+void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *ptrInstance,
+                                    const LVM_INT16     *src,
+                                          LVM_INT16     *dst,
+                                          LVM_INT16     n)
+{
+    LVM_INT16   OutLoop;
+    LVM_INT16   InLoop;
+    LVM_INT16   CurrentShort;
+    LVM_INT32   ii;
+    Mix_Private_st  *pInstance=(Mix_Private_st *)(ptrInstance->PrivateParams);
+    LVM_INT32   Delta=pInstance->Delta;
+    LVM_INT32   Current=pInstance->Current;
+    LVM_INT32   Target=pInstance->Target;
+    LVM_INT32   Temp;
+
+    InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+    OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+    if(Current<Target){
+        if (OutLoop){
+            ADD2_SAT_32x32(Current,Delta,Temp);                                      /* Q31 + Q31 into Q31*/
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
+
+            for (ii = OutLoop; ii != 0; ii--){
+                *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);    /* Q15*Q15>>15 into Q15 */
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            ADD2_SAT_32x32(Current,Delta,Temp);                                      /* Q31 + Q31 into Q31*/
+            Current=Temp;
+            if (Current > Target)
+                Current = Target;
+
+            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
+
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);    /* Q15*Q15>>15 into Q15 */
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+        }
+    }
+    else{
+        if (OutLoop){
+            Current -= Delta;                                                        /* Q31 + Q31 into Q31*/
+            if (Current < Target)
+                Current = Target;
+
+            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
+
+            for (ii = OutLoop; ii != 0; ii--){
+                *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);    /* Q15*Q15>>15 into Q15 */
+            }
+        }
+
+        for (ii = InLoop; ii != 0; ii--){
+            Current -= Delta;                                                        /* Q31 + Q31 into Q31*/
+            if (Current < Target)
+                Current = Target;
+
+            CurrentShort = (LVM_INT16)(Current>>16);                                 /* From Q31 to Q15*/
+
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);    /* Q15*Q15>>15 into Q15 */
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+            *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+        }
+    }
+    pInstance->Current=Current;
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
new file mode 100755
index 0000000..52be129
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+/**********************************************************************************
+   FUNCTION MIXINSOFT_D16C31_SAT
+***********************************************************************************/
+
+void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
+                                    LVM_INT16             *src,
+                                    LVM_INT16             *dst,
+                                    LVM_INT16             n)
+{
+    char        HardMixing = TRUE;
+    LVM_INT32   TargetGain;
+    Mix_Private_st  *pInstance=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+    if(n<=0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Delta == 0x7FFFFFFF){
+            pInstance->Current = pInstance->Target;
+            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+        }else if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
+            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            if(pInstance->Shift!=0){
+                Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
+                LVC_Core_MixInSoft_D16C31_SAT( &(ptrInstance->MixerStream[0]), src, dst, n);
+            }
+            else
+                LVC_Core_MixInSoft_D16C31_SAT( &(ptrInstance->MixerStream[0]), src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
+            if ((pInstance->Target>>16) == 0x7FFF){
+                if(pInstance->Shift!=0)
+                    Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
+                Add2_Sat_16x16( src, dst, n );
+            }
+            else{
+                if(pInstance->Shift!=0)
+                    Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
+                Mac3s_Sat_16x16(src,(LVM_INT16)(pInstance->Target>>16),dst,n);
+                pInstance->Current = pInstance->Target; /* In case the LVCore function would have changed the Current value */
+            }
+        }
+    }
+
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet){
+        if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
+            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
+            LVC_Mixer_SetTarget(ptrInstance->MixerStream,TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0){
+                (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
new file mode 100755
index 0000000..d832e06
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+/**********************************************************************************
+   FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
+***********************************************************************************/
+
+void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
+                                  const LVM_INT16             *src,
+                                        LVM_INT16             *dst,
+                                        LVM_INT16             n)
+{
+    char        HardMixing = TRUE;
+    LVM_INT32   TargetGain;
+    Mix_Private_st  *pInstance1=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
+    Mix_Private_st  *pInstance2=(Mix_Private_st *)(ptrInstance->MixerStream[1].PrivateParams);
+
+    if(n<=0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance1->Current != pInstance1->Target)||(pInstance2->Current != pInstance2->Target))
+    {
+        if(pInstance1->Delta == 0x7FFFFFFF)
+        {
+            pInstance1->Current = pInstance1->Target;
+            TargetGain=pInstance1->Target>>16;  // TargetGain in Q16.15 format, no integer part
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+        }
+        else if (Abs_32(pInstance1->Current-pInstance1->Target) < pInstance1->Delta)
+        {
+            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore.  Make them equal. */
+            TargetGain=pInstance1->Target>>16;  // TargetGain in Q16.15 format, no integer part
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+        }
+        else
+        {
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+        }
+
+        if(HardMixing == TRUE)
+        {
+            if(pInstance2->Delta == 0x7FFFFFFF)
+            {
+                pInstance2->Current = pInstance2->Target;
+                TargetGain=pInstance2->Target>>16;  // TargetGain in Q16.15 format, no integer part
+                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]),TargetGain);
+            }
+            else if (Abs_32(pInstance2->Current-pInstance2->Target) < pInstance2->Delta)
+            {
+                pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.  Make them equal. */
+                TargetGain=pInstance2->Target>>16;  // TargetGain in Q16.15 format, no integer part
+                LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]),TargetGain);
+            }
+            else
+            {
+                /* Soft mixing has to be applied */
+                HardMixing = FALSE;
+            }
+        }
+
+        if(HardMixing == FALSE)
+        {
+             LVC_Core_MixSoft_1St_2i_D16C31_WRA( &(ptrInstance->MixerStream[0]),&(ptrInstance->MixerStream[1]), src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing)
+    {
+        if (((pInstance1->Target>>16) == 0x7FFF)&&((pInstance2->Target>>16) == 0x7FFF))
+        {
+            if(src!=dst)
+            {
+                Copy_16(src, dst, n);
+            }
+        }
+        else
+        {
+            LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),&(ptrInstance->MixerStream[1]), src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet)
+    {
+        if (Abs_32(pInstance1->Current-pInstance1->Target) < pInstance1->Delta)
+        {
+            pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore.  Make them equal. */
+            TargetGain=pInstance1->Target>>(16-pInstance1->Shift);  // TargetGain in Q16.15 format
+            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0],TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0)
+            {
+                (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+    if (ptrInstance->MixerStream[1].CallbackSet)
+    {
+        if (Abs_32(pInstance2->Current-pInstance2->Target) < pInstance2->Delta)
+        {
+            pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore.  Make them equal. */
+            TargetGain=pInstance2->Target>>(16-pInstance2->Shift);  // TargetGain in Q16.15 format
+            LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1],TargetGain);
+            ptrInstance->MixerStream[1].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[1].pCallBack != 0)
+            {
+                (*ptrInstance->MixerStream[1].pCallBack) ( ptrInstance->MixerStream[1].pCallbackHandle, ptrInstance->MixerStream[1].pGeneralPurpose,ptrInstance->MixerStream[1].CallbackParam );
+            }
+        }
+    }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
new file mode 100755
index 0000000..cfb1239
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+/**********************************************************************************
+   FUNCTION LVMixer3_MIXSOFT_1ST_D16C31_SAT
+***********************************************************************************/
+
+void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
+                                  const LVM_INT16             *src,
+                                        LVM_INT16             *dst,
+                                        LVM_INT16             n)
+{
+    char        HardMixing = TRUE;
+    LVM_INT32   TargetGain;
+    Mix_Private_st  *pInstance=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+    if(n<=0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Delta == 0x7FFFFFFF){
+            pInstance->Current = pInstance->Target;
+            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+        }else if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
+            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
+            LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            if(pInstance->Shift!=0){
+                Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,dst,n);
+                LVC_Core_MixSoft_1St_D16C31_WRA( &(ptrInstance->MixerStream[0]), dst, dst, n);
+            }
+            else
+                LVC_Core_MixSoft_1St_D16C31_WRA( &(ptrInstance->MixerStream[0]), src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target == 0)
+            LoadConst_16(0, dst, n);
+        else if(pInstance->Shift!=0){
+            Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,dst,n);
+            if ((pInstance->Target>>16) != 0x7FFF)
+                Mult3s_16x16( dst, (LVM_INT16)(pInstance->Target>>16), dst, n );
+        }
+        else {
+            if ((pInstance->Target>>16) != 0x7FFF)
+                Mult3s_16x16( src, (LVM_INT16)(pInstance->Target>>16), dst, n );
+            else if(src!=dst)
+                Copy_16(src, dst, n);
+        }
+
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (ptrInstance->MixerStream[0].CallbackSet){
+        if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
+            TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
+            LVC_Mixer_SetTarget(ptrInstance->MixerStream,TargetGain);
+            ptrInstance->MixerStream[0].CallbackSet = FALSE;
+            if (ptrInstance->MixerStream[0].pCallBack != 0){
+                (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
+            }
+        }
+    }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
new file mode 100755
index 0000000..6184736
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION LVC_MixSoft_2St_D16C31_SAT.c
+***********************************************************************************/
+
+void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
+                                    const   LVM_INT16       *src1,
+                                            LVM_INT16       *src2,
+                                            LVM_INT16       *dst,
+                                            LVM_INT16       n)
+{
+    Mix_Private_st  *pInstance1=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
+    Mix_Private_st  *pInstance2=(Mix_Private_st *)(ptrInstance->MixerStream[1].PrivateParams);
+
+    if(n<=0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance1->Current == pInstance1->Target)&&(pInstance1->Current == 0)){
+        LVC_MixSoft_1St_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[1]), src2, dst, n);
+    }
+    else if ((pInstance2->Current == pInstance2->Target)&&(pInstance2->Current == 0)){
+        LVC_MixSoft_1St_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[0]), src1, dst, n);
+    }
+    else if ((pInstance1->Current != pInstance1->Target) || (pInstance2->Current != pInstance2->Target))
+    {
+        LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_st *)(&ptrInstance->MixerStream[0]), src1, dst, n);
+        LVC_MixInSoft_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[1]), src2, dst, n);
+    }
+    else{
+        /******************************************************************************
+           HARD MIXING
+        *******************************************************************************/
+        if(pInstance2->Shift!=0)
+            Shift_Sat_v16xv16 ((LVM_INT16)pInstance2->Shift,src2,src2,n);
+        if(pInstance1->Shift!=0)
+        {
+            Shift_Sat_v16xv16 ((LVM_INT16)pInstance1->Shift,src1,dst,n);
+            LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0], &ptrInstance->MixerStream[1], dst, src2, dst, n);
+        }
+        else
+            LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0], &ptrInstance->MixerStream[1], src1, src2, dst, n);
+    }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
new file mode 100755
index 0000000..3b32e21
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __LVC_MIXER_H__
+#define __LVC_MIXER_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#include "LVM_Types.h"
+
+/**********************************************************************************
+   INSTANCE MEMORY TYPE DEFINITION
+***********************************************************************************/
+
+/* LVMixer3_st structure stores Instance parameters for one audio stream */
+typedef struct
+{
+    LVM_INT32       PrivateParams[4];   /* Private Instance params for Audio Stream */
+    LVM_INT16       CallbackSet;        /* Boolean.  Should be set by calling application each time the target value is updated */
+    LVM_INT16       CallbackParam;      /* Parameter that will be used in the calback function */
+    void            *pCallbackHandle;   /* Pointer to the instance of the callback function */
+    void            *pGeneralPurpose;   /* Pointer for general purpose usage */
+    LVM_Callback    pCallBack;          /* Pointer to the callback function */
+} LVMixer3_st;
+
+typedef struct
+{
+    LVMixer3_st     MixerStream[1];    /* Instance Params for one Audio Stream */
+} LVMixer3_1St_st;
+
+typedef struct
+{
+    LVMixer3_st     MixerStream[2];    /* Instance Params for two Audio Streams */
+} LVMixer3_2St_st;
+
+typedef struct
+{
+    LVMixer3_st     MixerStream[3];    /* Instance Params for three Audio Streams */
+} LVMixer3_3St_st;
+
+/**********************************************************************************
+   FUNCTION PROTOTYPES (HIGH LEVEL FUNCTIONS)
+***********************************************************************************/
+
+/* Function names should be unique within first 16 characters  */
+#define    LVMixer3_MixSoft_1St_D16C31_SAT   LVMixer3_1St_D16C31_SAT_MixSoft
+#define    LVMixer3_MixInSoft_D16C31_SAT     LVMixer3_D16C31_SAT_MixInSoft
+#define    LVMixer3_MixSoft_2St_D16C31_SAT   LVMixer3_2St_D16C31_SAT_MixSoft
+#define    LVMixer3_MixSoft_3St_D16C31_SAT   LVMixer3_3St_D16C31_SAT_MixSoft
+
+
+/*** General functions ************************************************************/
+
+/**********************************************************************************/
+/* This time constant calculation function assumes the mixer will be called with  */
+/* large block sizes. When the block size is small, especially if less than 4,    */
+/* then the calculation will give an incorrect value for alpha, see the mixer     */
+/* documentation for further details.                                             */
+/* ********************************************************************************/
+void LVC_Mixer_SetTarget( LVMixer3_st *pStream,
+                                LVM_INT32           TargetGain);
+
+LVM_INT32 LVC_Mixer_GetTarget( LVMixer3_st *pStream);
+
+LVM_INT32 LVC_Mixer_GetCurrent( LVMixer3_st *pStream);
+
+void LVC_Mixer_Init( LVMixer3_st *pStream,
+                                LVM_INT32           TargetGain,
+                                LVM_INT32           CurrentGain);
+
+void LVC_Mixer_SetTimeConstant( LVMixer3_st *pStream,
+                                LVM_INT32           Tc_millisec,
+                                LVM_Fs_en           Fs,
+                                LVM_INT16           NumChannels);
+
+void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_st *pStream,
+                                        LVM_INT32           Tc_millisec,
+                                        LVM_Fs_en           Fs,
+                                        LVM_INT16           NumChannels);
+
+/*** 16 bit functions *************************************************************/
+
+void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *pInstance,
+                                  const LVM_INT16           *src,
+                                        LVM_INT16           *dst,
+                                        LVM_INT16           n);
+
+void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *pInstance,
+                                        LVM_INT16           *src,
+                                        LVM_INT16           *dst,
+                                        LVM_INT16           n);
+
+void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *pInstance,
+                                const LVM_INT16             *src1,
+                                      LVM_INT16             *src2,
+                                      LVM_INT16             *dst,  /* dst cannot be equal to src2 */
+                                      LVM_INT16             n);
+
+/**********************************************************************************/
+/* For applying different gains to Left and right chennals                        */
+/* MixerStream[0] applies to Left channel                                         */
+/* MixerStream[1] applies to Right channel                                        */
+/* Gain values should not be more that 1.0                                        */
+/**********************************************************************************/
+void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st         *pInstance,
+                                const   LVM_INT16           *src,
+                                        LVM_INT16           *dst,   /* dst can be equal to src */
+                                        LVM_INT16           n);     /* Number of stereo samples */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/**********************************************************************************/
+
+#endif //#ifndef __LVC_MIXER_H__
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
new file mode 100755
index 0000000..09658ba
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 839 $*/
+/*     $Date: 2010-06-16 14:15:52 +0200 (Wed, 16 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_GetCurrent                                                */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function returns the CurrentGain in Q16.15 format              */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  CurrentGain      - CurrentGain value in Q 16.15 format              */
+/*                                                                      */
+/************************************************************************/
+
+LVM_INT32 LVC_Mixer_GetCurrent( LVMixer3_st *pStream)
+{
+    LVM_INT32       CurrentGain;
+    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+    CurrentGain=pInstance->Current>>(16-pInstance->Shift);  // CurrentGain in Q16.15 format
+    return CurrentGain;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
new file mode 100755
index 0000000..ed2cf94
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 839 $*/
+/*     $Date: 2010-06-16 14:15:52 +0200 (Wed, 16 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_GetTarget                                                 */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function returns the TargetGain in Q16.15 format               */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  TargetGain      - TargetGain value in Q 16.15 format                */
+/*                                                                      */
+/************************************************************************/
+
+LVM_INT32 LVC_Mixer_GetTarget( LVMixer3_st *pStream)
+{
+    LVM_INT32       TargetGain;
+    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+
+    TargetGain=pInstance->Target>>(16-pInstance->Shift);  // TargetGain in Q16.15 format
+
+    return TargetGain;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
new file mode 100755
index 0000000..c61e468
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_Init                                                      */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This intialization function intializes the private instance         */
+/*  paramters for a given Audio Stream based on TargetGain and          */
+/*  CurrentGain                                                         */
+/*  This function caclulates the "Shift" required to provide the        */
+/*  integer part of TargetGain and fractional gain values "Target" and  */
+/*  "Current" based on maximum(TargetGain,CurrentGain)                  */
+/*  E.g. CurrentGain=1.9 and TargetGain=2.5 then based on               */
+/*  MaxGain of 2.5, Shift = 2, Current=1.9/4=0.475, Target=2.5/4=0.625  */
+/*  Therefore integer gain of 4 is provided by Left Shift of 2 and      */
+/*  fraction gain is provided through Current=0.475 and Target=0.625    */
+/* PARAMETERS:                                                          */
+/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/*                Audio Stream                                          */
+/*  TargetGain  - TargetGain value in Q 16.15 format                    */
+/*  CurrentGain - CurrentGain value in Q 16.15 format                   */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  void                                                                */
+/*                                                                      */
+/************************************************************************/
+
+void LVC_Mixer_Init( LVMixer3_st *pStream,
+                    LVM_INT32           TargetGain,
+                    LVM_INT32           CurrentGain)
+{
+    LVM_INT16       Shift=0;
+    LVM_INT32       MaxGain=TargetGain;         // MaxGain is in Q16.15 format
+    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+    if(CurrentGain>MaxGain)
+        MaxGain=CurrentGain;                    // MaxGain=max(CurrentGain,TargetGain)
+
+    MaxGain=MaxGain>>15;                        // MaxGain in Q31.0 format i.e Integer part only
+    while(MaxGain>0){                           // Update Shift required to provide integer gain
+        Shift++;
+        MaxGain=MaxGain>>1;
+    }
+    pInstance->Target=TargetGain<<(16-Shift);   // Update fractional gain Target
+    pInstance->Current=CurrentGain<<(16-Shift); // Update fractional gain Current
+    pInstance->Shift=Shift;                     // Update Shift
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
new file mode 100755
index 0000000..d61d670
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __LVC_MIXER_PRIVATE_H__
+#define __LVC_MIXER_PRIVATE_H__
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer.h"
+#include "VectorArithmetic.h"
+
+/* Instance parameter structure */
+typedef struct
+{
+    /* General */
+    LVM_INT32                       Target;                 /* 32 bit number specifying fractional value of Target Gain */
+    LVM_INT32                       Current;                /* 32 bit number specifying fractional valude of Current Gain */
+    LVM_INT32                       Shift;                  /* Left Shift for Integer part of Gain */
+    LVM_INT32                       Delta;                  /* 32 bit number specifying the fractional value of Delta Gain */
+} Mix_Private_st;
+
+
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+#define LVCore_MixInSoft_D32C31_SAT    LVCore_InSoft_D32C31_SAT
+#define LVCore_MixSoft_1St_D32C31_WRA  LVCore_Soft_1St_D32C31_WRA
+#define LVCore_MixHard_2St_D32C31_SAT  LVCore_Hard_2St_D32C31_SAT
+
+/**********************************************************************************
+   FUNCTION PROTOTYPES (LOW LEVEL SUBFUNCTIONS)
+***********************************************************************************/
+
+/*** 16 bit functions *************************************************************/
+
+void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *pInstance,
+                                    const LVM_INT16     *src,
+                                          LVM_INT16     *dst,
+                                          LVM_INT16     n);
+
+void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *pInstance,
+                                    const LVM_INT16     *src,
+                                          LVM_INT16     *dst,
+                                          LVM_INT16     n);
+
+void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_st *pInstance1,
+                                    LVMixer3_st         *pInstance2,
+                                    const LVM_INT16     *src1,
+                                    const LVM_INT16     *src2,
+                                          LVM_INT16     *dst,
+                                          LVM_INT16     n);
+
+/**********************************************************************************/
+/* For applying different gains to Left and right chennals                        */
+/* ptrInstance1 applies to Left channel                                           */
+/* ptrInstance2 applies to Right channel                                          */
+/* Gain values should not be more that 1.0                                        */
+/**********************************************************************************/
+
+void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st        *ptrInstance1,
+                                         LVMixer3_st        *ptrInstance2,
+                                         const LVM_INT16    *src,
+                                         LVM_INT16          *dst,   /* dst can be equal to src */
+                                         LVM_INT16          n);     /* Number of stereo samples */
+
+/**********************************************************************************/
+/* For applying different gains to Left and right chennals                        */
+/* ptrInstance1 applies to Left channel                                           */
+/* ptrInstance2 applies to Right channel                                          */
+/* Gain values should not be more that 1.0                                        */
+/**********************************************************************************/
+void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st        *ptrInstance1,
+                                         LVMixer3_st        *ptrInstance2,
+                                         const LVM_INT16    *src,
+                                         LVM_INT16          *dst,    /* dst can be equal to src */
+                                         LVM_INT16          n);      /* Number of stereo samples */
+
+
+
+/*** 32 bit functions *************************************************************/
+
+void LVC_Core_MixInSoft_D32C31_SAT( LVMixer3_st *pInstance,
+                                    const LVM_INT32     *src,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n);
+
+void LVC_Core_MixSoft_1St_D32C31_WRA( LVMixer3_st *pInstance,
+                                    const LVM_INT32     *src,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n);
+
+void LVC_Core_MixHard_2St_D32C31_SAT( LVMixer3_st *pInstance1,
+                                    LVMixer3_st         *pInstance2,
+                                    const LVM_INT32     *src1,
+                                    const LVM_INT32     *src2,
+                                          LVM_INT32     *dst,
+                                          LVM_INT16     n);
+
+/**********************************************************************************/
+
+#endif //#ifndef __LVC_MIXER_PRIVATE_H__
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
new file mode 100755
index 0000000..4d3fe0c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_SetTarget                                                 */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function updates the private instance parameters: Shift,Target,*/
+/*  Current for a given Audio Stream based on new value of TargetGain   */
+/*                                                                      */
+/*  This function caclulates the "Shift" required to provide the        */
+/*  integer part of TargetGain and fractional gain values "Target" and  */
+/*  "Current" based on maximum(TargetGain,CurrentGain)                  */
+/*  E.g. CurrentGain=1.9 and TargetGain=2.5 then based on               */
+/*  MaxGain of 2.5, Shift = 2, Current=1.9/4=0.475, Target=2.5/4=0.625  */
+/*  Therefore integer gain of 4 is provided by Left Shift of 2 and      */
+/*  fraction gain is provided through Current=0.475 and Target=0.625    */
+/* PARAMETERS:                                                          */
+/*  pStream         - ptr to Instance Parameter Structure LVMixer3_st   */
+/*                    for an Audio Stream                               */
+/*  TargetGain      - TargetGain value in Q 16.15 format                */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  void                                                                */
+/*                                                                      */
+/************************************************************************/
+
+void LVC_Mixer_SetTarget(LVMixer3_st *pStream,
+                        LVM_INT32           TargetGain)
+{
+    LVM_INT32       Shift=0;
+    LVM_INT32       CurrentGain;
+    LVM_INT32       MaxGain=TargetGain;                     // MaxGain is in Q16.15 format
+    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+    CurrentGain=pInstance->Current>>(16-pInstance->Shift);  // CurrentGain in Q16.15 format
+    if(CurrentGain>MaxGain)
+        MaxGain=CurrentGain;                                // MaxGain=max(CurrentGain,TargetGain)
+
+    MaxGain=MaxGain>>15;                                    // MaxGain in Q31.0 format i.e Integer part only
+    while(MaxGain>0){                                       // Update Shift required to provide integer gain
+        Shift++;
+        MaxGain=MaxGain>>1;
+    }
+    pInstance->Target=TargetGain<<(16-Shift);               // Update fractional gain Target
+    pInstance->Current=CurrentGain<<(16-Shift);             // Update fractional gain Current
+    pInstance->Shift=Shift;                                 // Update Shift
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
new file mode 100755
index 0000000..df0fd37
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_SetTimeConstant                                           */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function calculates the step change for fractional gain for a  */
+/*  given time constant, sample rate and num channels                   */
+/*  Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)      */
+/*  in Q 0.31 format                                                    */
+/*                                                                      */
+/* PARAMETERS:                                                          */
+/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/*                Audio Stream                                          */
+/*  Tc_millisec - TimeConstant i.e time required in milli second to     */
+/*                go from linear fractional gain of 0 to 0.99999999     */
+/*  Fs          - LVM_Fs_en enumerator for Sampling Frequency           */
+/*  NumChannels - Number of channels in Audio Stream 1=Mono, 2=Stereo   */
+/*                                                                      */
+/* UPDATES:                                                             */
+/*  Delta       - the step change for fractional gain per 4 samples     */
+/*                in Q0.31 format for a given Time Constant,            */
+/*                Sample Rate and NumChannels                           */
+/* RETURNS:                                                             */
+/*  void                                                                */
+/************************************************************************/
+
+void LVC_Mixer_SetTimeConstant(LVMixer3_st *pStream,
+                            LVM_INT32           Tc_millisec,
+                            LVM_Fs_en           Fs,
+                            LVM_INT16           NumChannels)
+{
+    LVM_INT32   DeltaTable[9]={1073741824,
+                               779132389,
+                               715827882,
+                               536870912,
+                               389566194,
+                               357913941,
+                               268435456,
+                               194783097,
+                               178956971};
+    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+    LVM_INT32   Delta=DeltaTable[Fs];
+    Delta=Delta>>(NumChannels-1);
+
+    if(Tc_millisec==0)
+        Delta=0x7FFFFFFF;
+    else
+        Delta=Delta/Tc_millisec;
+
+    if(Delta==0)
+        Delta=1;                // If Time Constant is so large that Delta is 0, assign minimum value to Delta
+
+    pInstance->Delta=Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) in Q 0.31 format
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
new file mode 100755
index 0000000..420af9a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVMixer3_VarSlope_SetTimeConstant                                  */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function calculates the step change for fractional gain for a  */
+/*  given time constant, sample rate and num channels                   */
+/*  Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec)      */
+/*  in Q 0.31 format                                                    */
+/*                                                                      */
+/* PARAMETERS:                                                          */
+/*  pStream     - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/*                Audio Stream                                          */
+/*  Tc_millisec - TimeConstant i.e time required in milli second to     */
+/*                go from linear fractional gain of 0 to 0.99999999     */
+/*  Fs          - LVM_Fs_en enumerator for Sampling Frequency           */
+/*  NumChannels - Number of channels in Audio Stream 1=Mono, 2=Stereo   */
+/*                                                                      */
+/* UPDATES:                                                             */
+/*  Delta       - the step change for fractional gain per 4 samples     */
+/*                in Q0.31 format for a given Time Constant,            */
+/*                Sample Rate and NumChannels                           */
+/* RETURNS:                                                             */
+/*  void                                                                */
+/************************************************************************/
+
+void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_st *pStream,
+                                        LVM_INT32           Tc_millisec,
+                                        LVM_Fs_en           Fs,
+                                        LVM_INT16           NumChannels)
+{
+    LVM_INT32   DeltaTable[9]={1073741824,
+                               779132389,
+                               715827882,
+                               536870912,
+                               389566194,
+                               357913941,
+                               268435456,
+                               194783097,
+                               178956971};
+    Mix_Private_st  *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+    LVM_INT32   Delta=DeltaTable[Fs];
+
+    LVM_INT32   Current;
+    LVM_INT32   Target;
+
+    Delta=Delta>>(NumChannels-1);
+
+    /*  Get gain values  */
+    Current = LVC_Mixer_GetCurrent( pStream );
+    Target = LVC_Mixer_GetTarget( pStream );
+
+    if (Current != Target)
+    {
+        Tc_millisec = Tc_millisec * 32767 / (Current - Target);
+        if (Tc_millisec<0) Tc_millisec = -Tc_millisec;
+
+        if(Tc_millisec==0)
+            Delta=0x7FFFFFFF;
+        else
+            Delta=Delta/Tc_millisec;
+
+        if(Delta==0)
+            Delta=1;            // If Time Constant is so large that Delta is 0, assign minimum value to Delta
+    }
+    else
+    {
+        Delta =1;               // Minimum value for proper call-backs (setting it to zero has some problems, to be corrected)
+    }
+
+
+    pInstance->Delta=Delta;     // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) in Q 0.31 format
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
new file mode 100755
index 0000000..37c199e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: nxp27078 $*/
+/*     $Revision: 762 $*/
+/*     $Date: 2010-06-11 14:50:33 +0200 (vr, 11 jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "BIQUAD.h"
+#include "Filter.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   void LVM_FO_LPF(   LVM_INT32       w ,                                */
+/*                      FO_C32_Coefs_t  *pCoeffs);                         */
+/*                                                                         */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*    This function calculates the coefficient of first order low pass     */
+/*    filter. It uses the equations:                                       */
+/*                                                                         */
+/*    B1    = (tan(w/2) - 1 )  /  (tan(w/2) + 1 )                          */
+/*    A0    = (1 - B1) / 2                                                 */
+/*    A1    = A0                                                           */
+/*                                                                         */
+/*    The value of B1 is then calculated directly from the value w by a    */
+/*    polynomial expansion using a 9th order polynomial. It uses the       */
+/*    following table of 32-bit integer polynomial coefficients:           */
+/*                                                                         */
+/*   Coefficient    Value                                                  */
+/*   A0             -8388571                                               */
+/*   A1             33547744                                               */
+/*   A2             -66816791                                              */
+/*   A3             173375308                                              */
+/*   A4             -388437573                                             */
+/*   A5             752975383                                              */
+/*   A6             -1103016663                                            */
+/*   A7             1121848567                                             */
+/*   A8             -688078159                                             */
+/*   A9             194669577                                              */
+/*   A10            8                                                      */
+/*                                                                         */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + Â….. + AN*xN) << AN+1                  */
+/*                                                                         */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  w               Sample rate in radians,  where:                        */
+/*                  w = 2 * Pi * Fc / Fs                                   */
+/*                  Fc   is the corner frequency in Hz                     */
+/*                  Fs   is the sample rate in Hz                          */
+/*                  w is in Q2.29 format and data range is [0 Pi]          */
+/*  pCoeffs         Points to the filter coefficients calculated here      */
+/*                  in Q1.30 format                                        */
+/* RETURNS:                                                                */
+/*                                                                         */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_FO_HPF(   LVM_INT32       w,
+                        FO_C32_Coefs_t  *pCoeffs)
+{
+    LVM_INT32 Y,Coefficients[13]={  -8388571,
+                                    33547744,
+                                    -66816791,
+                                    173375308,
+                                    -388437573,
+                                    752975383,
+                                    -1103016663,
+                                    1121848567,
+                                    -688078159,
+                                    194669577,
+                                    8,
+                                    0,
+                                    0};
+    Y=LVM_Polynomial(           (LVM_UINT16)9,
+                                 Coefficients,
+                                 w);
+    pCoeffs->B1=-Y;         /* Store -B1 in filter structure instead of B1!*/
+                            /* A0=(1-B1)/2= B1/2 - 0.5*/
+    Y=Y>>1;                 /* A0=Y=B1/2*/
+    Y=Y-0x40000000;         /* A0=Y=(B1/2 - 0.5)*/
+    MUL32x16INTO32(Y, FILTER_LOSS ,pCoeffs->A0 ,15)     /* Apply loss to avoid overflow*/
+    pCoeffs->A1=-pCoeffs->A0;                           /* Store A1=-A0*/
+
+    return 1;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
new file mode 100755
index 0000000..6c73d59
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: nxp27078 $*/
+/*     $Revision: 762 $*/
+/*     $Date: 2010-06-11 14:50:33 +0200 (vr, 11 jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "BIQUAD.h"
+#include "Filter.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   void LVM_FO_LPF(   LVM_INT32       w ,                                */
+/*                      FO_C32_Coefs_t  *pCoeffs);                         */
+/*                                                                         */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*    This function calculates the coefficient of first order low pass     */
+/*    filter. It uses the equations:                                       */
+/*                                                                         */
+/*    B1    = (tan(w/2) - 1 )  /  (tan(w/2) + 1 )                          */
+/*    A0    = (1 + B1) / 2                                                 */
+/*    A1    = A0                                                           */
+/*                                                                         */
+/*    The value of B1 is then calculated directly from the value w by a    */
+/*    polynomial expansion using a 9th order polynomial. It uses the       */
+/*    following table of 32-bit integer polynomial coefficients:           */
+/*                                                                         */
+/*   Coefficient    Value                                                  */
+/*   A0             -8388571                                               */
+/*   A1             33547744                                               */
+/*   A2             -66816791                                              */
+/*   A3             173375308                                              */
+/*   A4             -388437573                                             */
+/*   A5             752975383                                              */
+/*   A6             -1103016663                                            */
+/*   A7             1121848567                                             */
+/*   A8             -688078159                                             */
+/*   A9             194669577                                              */
+/*   A10            8                                                      */
+/*                                                                         */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + Â….. + AN*xN) << AN+1                  */
+/*                                                                         */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  w               Sample rate in radians,  where:                        */
+/*                  w = 2 * Pi * Fc / Fs                                   */
+/*                  Fc   is the corner frequency in Hz                     */
+/*                  Fs   is the sample rate in Hz                          */
+/*                  w is in Q2.29 format and data range is [0 Pi]          */
+/*  pCoeffs         Points to the filter coefficients calculated here      */
+/*                  in Q1.30 format                                        */
+/* RETURNS:                                                                */
+/*                                                                         */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_FO_LPF(   LVM_INT32       w,
+                        FO_C32_Coefs_t  *pCoeffs)
+{
+    LVM_INT32 Y,Coefficients[13]={  -8388571,
+                                    33547744,
+                                    -66816791,
+                                    173375308,
+                                    -388437573,
+                                    752975383,
+                                    -1103016663,
+                                    1121848567,
+                                    -688078159,
+                                    194669577,
+                                    8};
+    Y=LVM_Polynomial(           (LVM_UINT16)9,
+                                 Coefficients,
+                                 w);
+    pCoeffs->B1=-Y;     // Store -B1 in filter structure instead of B1!
+                        // A0=(1+B1)/2= B1/2 + 0.5
+    Y=Y>>1;             // A0=Y=B1/2
+    Y=Y+0x40000000;     // A0=Y=(B1/2 + 0.5)
+    MUL32x16INTO32(Y, FILTER_LOSS ,pCoeffs->A0 ,15)    // Apply loss to avoid overflow
+    pCoeffs->A1=pCoeffs->A0;
+    return 1;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
new file mode 100755
index 0000000..1cc10db
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: nxp27078 $*/
+/*     $Revision: 762 $*/
+/*     $Date: 2010-06-11 14:50:33 +0200 (vr, 11 jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "Filter.h"
+#include "LVM_Macros.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* Defines and Tables for 2*Pi/Fs                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVVDL_2PiBy_8000        1727108826  /* In Q41 format */
+#define LVVDL_2PiBy_11025       1253230894  /* In Q41 format */
+#define LVVDL_2PiBy_12000       1151405884  /* In Q41 format */
+
+#define LVVDL_2PiByFs_SHIFT1    12          /* Qformat shift for 8kHz, 11.025kHz and 12kHz i.e. 12=41-29 */
+#define LVVDL_2PiByFs_SHIFT2    13          /* Qformat shift for 16kHz, 22.050kHz and 24kHz i.e. 13=42-29 */
+#define LVVDL_2PiByFs_SHIFT3    14          /* Qformat shift for 32kHz, 44.1kHz and 48kHz i.e. 14=43-29 */
+
+const LVM_INT32     LVVDL_2PiOnFsTable[] =  {LVVDL_2PiBy_8000 , /* 8kHz in Q41, 16kHz in Q42, 32kHz in Q43 */
+                                            LVVDL_2PiBy_11025,  /* 11025 Hz in Q41, 22050Hz in Q42, 44100 Hz in Q43*/
+                                            LVVDL_2PiBy_12000}; /* 12kHz in Q41, 24kHz in Q42, 48kHz in Q43 */
+
+
+const LVM_INT32     LVVDL_2PiOnFsShiftTable[]={LVVDL_2PiByFs_SHIFT1 ,         /* 8kHz, 11025Hz, 12kHz */
+                                               LVVDL_2PiByFs_SHIFT2,          /* 16kHz, 22050Hz, 24kHz*/
+                                               LVVDL_2PiByFs_SHIFT3};         /* 32kHz, 44100Hz, 48kHz */
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   LVM_GetOmega                                                          */
+/*                                                                         */
+/* LVM_INT32 LVM_GetOmega(LVM_UINT16                  Fc,                  */
+/*                        LVM_Fs_en                   Fs)                  */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   This function calculates the value of w using Fc and Fs               */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  LVM_UINT16          Fc     The corner frequency in Hz Q16.0 format     */
+/*  LVM_Fs_en           Fs     The SampleRate                              */
+/* RETURNS:                                                                */
+/*   w=2*pi*Fc/Fs in Q2.29 format                                          */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_GetOmega(LVM_UINT16                  Fc,
+                       LVM_Fs_en                   Fs)
+{
+    LVM_INT32   w;
+    MUL32x32INTO32((LVM_INT32)Fc,LVVDL_2PiOnFsTable[Fs%3],w,LVVDL_2PiOnFsShiftTable[Fs/3])
+    return w;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
new file mode 100755
index 0000000..00235e0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/* Mixer library tables                                                             */
+/*                                                                                  */
+/* Coefficients and table values for the mixer library, generated by the Matlab     */
+/* Script: Mixer_GenerateCoeffs.m                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+#ifndef __LVM_MIXER_FILTER_COEFFS_H__
+#define __LVM_MIXER_FILTER_COEFFS_H__
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* Alpha Time Constant table                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#define Alpha_TableSize                        50      /* The number of table entires */
+#define ALPHA_0                        2147480769      /* Floating point Alpha = 0.999999 */
+#define ALPHA_1                        2147479577      /* Floating point Alpha = 0.999998 */
+#define ALPHA_2                        2147477892      /* Floating point Alpha = 0.999997 */
+#define ALPHA_3                        2147475510      /* Floating point Alpha = 0.999996 */
+#define ALPHA_4                        2147472141      /* Floating point Alpha = 0.999995 */
+#define ALPHA_5                        2147467377      /* Floating point Alpha = 0.999992 */
+#define ALPHA_6                        2147460642      /* Floating point Alpha = 0.999989 */
+#define ALPHA_7                        2147451118      /* Floating point Alpha = 0.999985 */
+#define ALPHA_8                        2147437651      /* Floating point Alpha = 0.999979 */
+#define ALPHA_9                        2147418608      /* Floating point Alpha = 0.999970 */
+#define ALPHA_10                       2147391683      /* Floating point Alpha = 0.999957 */
+#define ALPHA_11                       2147353611      /* Floating point Alpha = 0.999939 */
+#define ALPHA_12                       2147299779      /* Floating point Alpha = 0.999914 */
+#define ALPHA_13                       2147223662      /* Floating point Alpha = 0.999879 */
+#define ALPHA_14                       2147116037      /* Floating point Alpha = 0.999829 */
+#define ALPHA_15                       2146963865      /* Floating point Alpha = 0.999758 */
+#define ALPHA_16                       2146748712      /* Floating point Alpha = 0.999658 */
+#define ALPHA_17                       2146444522      /* Floating point Alpha = 0.999516 */
+#define ALPHA_18                       2146014472      /* Floating point Alpha = 0.999316 */
+#define ALPHA_19                       2145406527      /* Floating point Alpha = 0.999033 */
+#define ALPHA_20                       2144547188      /* Floating point Alpha = 0.998633 */
+#define ALPHA_21                       2143332669      /* Floating point Alpha = 0.998067 */
+#define ALPHA_22                       2141616514      /* Floating point Alpha = 0.997268 */
+#define ALPHA_23                       2139192215      /* Floating point Alpha = 0.996139 */
+#define ALPHA_24                       2135768939      /* Floating point Alpha = 0.994545 */
+#define ALPHA_25                       2130937774      /* Floating point Alpha = 0.992295 */
+#define ALPHA_26                       2124125153      /* Floating point Alpha = 0.989123 */
+#define ALPHA_27                       2114529263      /* Floating point Alpha = 0.984654 */
+#define ALPHA_28                       2101034612      /* Floating point Alpha = 0.978370 */
+#define ALPHA_29                       2082100030      /* Floating point Alpha = 0.969553 */
+#define ALPHA_30                       2055617398      /* Floating point Alpha = 0.957221 */
+#define ALPHA_31                       2018744824      /* Floating point Alpha = 0.940051 */
+#define ALPHA_32                       1967733015      /* Floating point Alpha = 0.916297 */
+#define ALPHA_33                       1897794587      /* Floating point Alpha = 0.883729 */
+#define ALPHA_34                       1803123234      /* Floating point Alpha = 0.839645 */
+#define ALPHA_35                       1677262220      /* Floating point Alpha = 0.781036 */
+#define ALPHA_36                       1514142675      /* Floating point Alpha = 0.705078 */
+#define ALPHA_37                       1310197875      /* Floating point Alpha = 0.610108 */
+#define ALPHA_38                       1067813480      /* Floating point Alpha = 0.497239 */
+#define ALPHA_39                        799601371      /* Floating point Alpha = 0.372343 */
+#define ALPHA_40                        531183049      /* Floating point Alpha = 0.247351 */
+#define ALPHA_41                        297904007      /* Floating point Alpha = 0.138722 */
+#define ALPHA_42                        131499768      /* Floating point Alpha = 0.061234 */
+#define ALPHA_43                         41375282      /* Floating point Alpha = 0.019267 */
+#define ALPHA_44                          8065899      /* Floating point Alpha = 0.003756 */
+#define ALPHA_45                           799076      /* Floating point Alpha = 0.000372 */
+#define ALPHA_46                            30398      /* Floating point Alpha = 0.000014 */
+#define ALPHA_47                              299      /* Floating point Alpha = 0.000000 */
+#define ALPHA_48                                0      /* Floating point Alpha = 0.000000 */
+#define ALPHA_49                                0      /* Floating point Alpha = 0.000000 */
+#define ALPHA_50                                0      /* Floating point Alpha = 0.000000 */
+
+
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
new file mode 100755
index 0000000..db6975a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "Mixer.h"
+#include "LVM_Mixer_FilterCoeffs.h"
+
+
+/************************************************************************/
+/* FUNCTION:                                                            */
+/*   LVM_Mix_GetTimeConstant                                            */
+/*                                                                      */
+/* DESCRIPTION:                                                         */
+/*  This function calculates the filter coefficient using the following */
+/*  equation:                                                           */
+/*       Alpha = exp(ln(0.1)/ (tc * Update + 1.0))                      */
+/*                                                                      */
+/*  This is to be used with the follow first order filter, called at a  */
+/*  rate of Update times a second. tc is the required time constant in  */
+/*  units of 100us.                                                     */
+/*                                                                      */
+/*       Output(n) = Alpha * Output(n-1) + (1 - Alpha) * Target(n)      */
+/*                                                                      */
+/*  The function assumes the block size is large, i.e. the update rate  */
+/*  is approximately a fixed, and correct factor of the value of Fs     */
+/*  given in the call. This is especially not true when the block size  */
+/*  is very small, see the mixer documentation for further details.     */
+/*                                                                      */
+/*  The function does not support all possible combinations of input    */
+/*  values:                                                             */
+/*                                                                      */
+/*  1. NumChannels is limited to the values 1 (Mono) and 2 (Stereo)     */
+/*  2. The product tc * Fs is limited approximately to the range        */
+/*      8 < (tc * Fs) < 2^35                                            */
+/*                                                                      */
+/* PARAMETERS:                                                          */
+/*  tc              - the time constant in 100us steps, i.e. 10 = 1ms   */
+/*  Fs              - the filter update rate in Hz                      */
+/*  NumChannels     - Number of channels 1=Mono, 2=Stereo               */
+/*                                                                      */
+/* RETURNS:                                                             */
+/*  Alpha   - the filter coefficient Q31 format                         */
+/*                                                                      */
+/************************************************************************/
+
+LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32   tc,
+                                  LVM_UINT16   Fs,
+                                  LVM_UINT16   NumChannels)
+{
+
+    LVM_UINT32  Product;
+    LVM_INT16   Interpolate;
+    LVM_UINT16  Shift;
+    LVM_INT32   Diff;
+    LVM_UINT32  Table[] = {ALPHA_0,             /* Log spaced look-up table */
+                           ALPHA_1,
+                           ALPHA_2,
+                           ALPHA_3,
+                           ALPHA_4,
+                           ALPHA_5,
+                           ALPHA_6,
+                           ALPHA_7,
+                           ALPHA_8,
+                           ALPHA_9,
+                           ALPHA_10,
+                           ALPHA_11,
+                           ALPHA_12,
+                           ALPHA_13,
+                           ALPHA_14,
+                           ALPHA_15,
+                           ALPHA_16,
+                           ALPHA_17,
+                           ALPHA_18,
+                           ALPHA_19,
+                           ALPHA_20,
+                           ALPHA_21,
+                           ALPHA_22,
+                           ALPHA_23,
+                           ALPHA_24,
+                           ALPHA_25,
+                           ALPHA_26,
+                           ALPHA_27,
+                           ALPHA_28,
+                           ALPHA_29,
+                           ALPHA_30,
+                           ALPHA_31,
+                           ALPHA_32,
+                           ALPHA_33,
+                           ALPHA_34,
+                           ALPHA_35,
+                           ALPHA_36,
+                           ALPHA_37,
+                           ALPHA_38,
+                           ALPHA_39,
+                           ALPHA_40,
+                           ALPHA_41,
+                           ALPHA_42,
+                           ALPHA_43,
+                           ALPHA_44,
+                           ALPHA_45,
+                           ALPHA_46,
+                           ALPHA_47,
+                           ALPHA_48,
+                           ALPHA_49,
+                           ALPHA_50};
+
+
+    /* Calculate the product of the time constant and the sample rate */
+    Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13;  /* Stereo value */
+    Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3);
+
+    if (NumChannels == 1)
+    {
+        Product = Product >> 1;   /* Mono value */
+    }
+
+    /* Normalize to get the table index and interpolation factor */
+    for (Shift=0; Shift<((Alpha_TableSize-1)/2); Shift++)
+    {
+        if ((Product & 0x80000000)!=0)
+        {
+            break;
+        }
+
+        Product = Product << 1;
+    }
+    Shift = (LVM_UINT16)((Shift << 1));
+
+    if ((Product & 0x40000000)==0)
+    {
+        Shift++;
+    }
+
+    Interpolate = (LVM_INT16)((Product >> 15) & 0x00007FFF);
+
+    Diff = (LVM_INT32)(Table[Shift] - Table[Shift+1]);
+    MUL32x16INTO32(Diff,Interpolate,Diff,15)
+        Product = Table[Shift+1] + (LVM_UINT32)Diff;
+
+    return Product;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
new file mode 100755
index 0000000..b8cf4b4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   LVM_Polynomial                                                        */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   This function performs polynomial expansion                           */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + Â….. + AN*xN) << AN+1                  */
+/*                                                                         */
+/*  LVM_INT32 LVM_Polynomial(LVM_UINT16    N,                              */
+/*                           LVM_INT32    *pCoefficients,                  */
+/*                           LVM_INT32    X)                               */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  N                is the polynomial order                               */
+/*  pCoefficients    is the ptr to polynomial coefficients A0,A1.. in Q.31 */
+/*  X                is the input variable                                 */
+/*                                                                         */
+/* RETURNS:                                                                */
+/*   The result of the polynomial expansion in Q1.31 format                */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_Polynomial(LVM_UINT16    N,
+                         LVM_INT32    *pCoefficients,
+                         LVM_INT32    X)
+{
+    LVM_INT32 i;
+    LVM_INT32 Y,A,XTemp,Temp,sign;
+
+    Y=*pCoefficients; /* Y=A0*/
+    pCoefficients++;
+
+    if((LVM_UINT32)X==0x80000000)
+    {
+        Temp=-1;
+        sign=Temp;
+        for(i=1;i<=N;i++)
+        {
+            Y+=((*pCoefficients)*sign);
+            pCoefficients++;
+            sign*=Temp;
+        }
+
+
+    }
+    else
+    {
+        XTemp=X;
+        for(i=N-1;i>=0;i--)
+        {
+            A=*pCoefficients;
+            pCoefficients++;
+
+            MUL32x32INTO32(A,XTemp,Temp,31)
+            Y+=Temp;
+
+            MUL32x32INTO32(XTemp,X,Temp,31)
+            XTemp=Temp;
+        }
+    }
+    A=*pCoefficients;
+    pCoefficients++;
+
+    if(A<0)
+    {
+        A=Abs_32(A);
+        Y=Y>>A;
+    }
+    else
+    {
+        Y = Y<<A;
+    }
+    return Y;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Power10.c b/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
new file mode 100755
index 0000000..9a3f632
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "Filter.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION:                                                               */
+/*   LVM_Power10                                                           */
+/*                                                                         */
+/* DESCRIPTION:                                                            */
+/*   This function calculates 10X using an 11th order polynomial. It uses  */
+/*   the following table of 32-bit integer polynomial coefficients:        */
+/*                                                                         */
+/*   Coefficient    Value                                                  */
+/*   A0             67102543                                               */
+/*   A1             309032995                                              */
+/*   A2             712096127                                              */
+/*   A3             1092797331                                             */
+/*   A4             1251625137                                             */
+/*   A5             1154649460                                             */
+/*   A6             915654800                                              */
+/*   A7             597883683                                              */
+/*   A8             284378230                                              */
+/*   A9             150262097                                              */
+/*   A10            124894471                                              */
+/*   A11            50477244                                               */
+/*   A12            -2                                                     */
+/*                                                                         */
+/*  Y = (A0 + A1*X + A2*X2 + A3*X3 + Â….. + AN*xN) << AN+1                  */
+/*                                                                         */
+/*                                                                         */
+/* PARAMETERS:                                                             */
+/*                                                                         */
+/*  X               is the input variable in Q2.30 format                  */
+/*                                                                         */
+/* RETURNS:                                                                */
+/*   The result of the 10x expansion in Q8.24 format                       */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_Power10(LVM_INT32     X)
+{
+    LVM_INT32 Y,Coefficients[13]={  16775636,
+                                        77258249,
+                                       178024032,
+                                       273199333,
+                                       312906284,
+                                       288662365,
+                                       228913700,
+                                       149470921,
+                                        71094558,
+                                        37565524,
+                                        31223618,
+                                        12619311,
+                                     0};
+    Y=LVM_Polynomial((LVM_UINT16)11,
+                        Coefficients,
+                        X);
+    return Y;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer.c b/media/libeffects/lvm/lib/Common/src/LVM_Timer.c
new file mode 100755
index 0000000..d49aadc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   My Project                                           */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/****************************************************************************************/
+/*  INCLUDE FILES                                                                       */
+/****************************************************************************************/
+
+#include "LVM_Timer.h"
+#include "LVM_Timer_Private.h"
+
+/****************************************************************************************/
+/*  TIMER FUNCTION                                                                      */
+/****************************************************************************************/
+
+void LVM_Timer      (   LVM_Timer_Instance_t       *pInstance,
+                        LVM_INT16                  BlockSize ){
+
+    LVM_Timer_Instance_Private_t *pInstancePr;
+    pInstancePr = (LVM_Timer_Instance_Private_t *)pInstance;
+
+    if (pInstancePr->TimerArmed){
+        pInstancePr->RemainingTimeInSamples -= BlockSize;
+        if (pInstancePr->RemainingTimeInSamples <= 0){
+            pInstancePr->TimerArmed = 0;
+            (*pInstancePr->pCallBack) ( pInstancePr->pCallbackInstance,
+                                        pInstancePr->pCallBackParams,
+                                        pInstancePr->CallBackParam );
+        }
+    }
+}
+
+/****************************************************************************************/
+/*  END OF FILE                                                                         */
+/****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c
new file mode 100755
index 0000000..e473038
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   My Project                                           */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/****************************************************************************************/
+/*  INCLUDE FILES                                                                       */
+/****************************************************************************************/
+
+#include "LVM_Timer.h"
+#include "LVM_Timer_Private.h"
+#include "LVM_Macros.h"
+
+/****************************************************************************************/
+/*  DEFINITIONS                                                                         */
+/****************************************************************************************/
+
+#define OneOverThousandInQ24 16777
+
+/****************************************************************************************/
+/*  INIT FUNCTION                                                                       */
+/****************************************************************************************/
+
+void LVM_Timer_Init (   LVM_Timer_Instance_t       *pInstance,
+                        LVM_Timer_Params_t         *pParams     ){
+
+    LVM_Timer_Instance_Private_t *pInstancePr;
+    pInstancePr = (LVM_Timer_Instance_Private_t *)pInstance;
+
+    pInstancePr->CallBackParam     = pParams->CallBackParam;
+    pInstancePr->pCallBackParams   = pParams->pCallBackParams;
+    pInstancePr->pCallbackInstance = pParams->pCallbackInstance;
+    pInstancePr->pCallBack         = pParams->pCallBack;
+    pInstancePr->TimerArmed        = 1;
+
+    MUL32x16INTO32(pParams->SamplingRate,OneOverThousandInQ24,pInstancePr->RemainingTimeInSamples,16);  /* (Q0 * Q24) >>16 into Q8*/
+    MUL32x16INTO32(pInstancePr->RemainingTimeInSamples,pParams->TimeInMs,pInstancePr->RemainingTimeInSamples,8);  /* (Q8 * Q0) >>8 into Q0*/
+}
+
+/****************************************************************************************/
+/*  END OF FILE                                                                         */
+/****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h
new file mode 100755
index 0000000..04d5af6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   My Project                                           */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#ifndef LVM_TIMER_PRIVATE_H
+#define LVM_TIMER_PRIVATE_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#include "LVM_Types.h"
+
+/****************************************************************************************/
+/*  TYPE DEFINITIONS                                                                    */
+/****************************************************************************************/
+
+typedef struct
+{
+    LVM_INT32  RemainingTimeInSamples;
+    LVM_INT32  CallBackParam;
+    LVM_INT32  *pCallBackParams;
+    void  *pCallbackInstance;
+    void  (*pCallBack)(void*,void*,LVM_INT32);
+    LVM_INT16 TimerArmed;                        /* Boolean, true between init and callback */
+
+} LVM_Timer_Instance_Private_t;
+
+/****************************************************************************************/
+/*  END OF HEADER                                                                       */
+/****************************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* LVM_TIMER_PRIVATE_H */
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_16.c b/media/libeffects/lvm/lib/Common/src/LoadConst_16.c
new file mode 100755
index 0000000..bc2735f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LoadConst_16.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION LoadConst_16
+***********************************************************************************/
+
+void LoadConst_16(const LVM_INT16 val,
+                  LVM_INT16 *dst,
+                  LVM_INT16 n )
+{
+    LVM_INT16 ii;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = val;
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_32.c b/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
new file mode 100755
index 0000000..19d5d4e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION LoadConst_32
+***********************************************************************************/
+
+void LoadConst_32(const LVM_INT32   val,
+                        LVM_INT32  *dst,
+                        LVM_INT16 n )
+{
+    LVM_INT16 ii;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = val;
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
new file mode 100755
index 0000000..1949f3c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION  MSTO2I_SAT_16X16
+***********************************************************************************/
+
+void MSTo2i_Sat_16x16(const LVM_INT16  *srcM,
+                      const LVM_INT16  *srcS,
+                      LVM_INT16  *dst,
+                      LVM_INT16  n )
+{
+    LVM_INT32 temp,mVal,sVal;
+    LVM_INT16 ii;
+
+
+    for (ii = n; ii != 0; ii--)
+    {
+        mVal=(LVM_INT32)*srcM;
+        srcM++;
+
+        sVal=(LVM_INT32)*srcS;
+        srcS++;
+
+        temp = mVal + sVal;
+
+        if (temp > 0x00007FFF)
+        {
+            *dst = 0x7FFF;
+        }
+        else if (temp < -0x00008000)
+        {
+            *dst = - 0x8000;
+        }
+        else
+        {
+            *dst = (LVM_INT16)temp;
+        }
+        dst++;
+
+        temp = mVal - sVal;
+
+        if (temp > 0x00007FFF)
+        {
+            *dst = 0x7FFF;
+        }
+        else if (temp < -0x00008000)
+        {
+            *dst = - 0x8000;
+        }
+        else
+        {
+            *dst = (LVM_INT16)temp;
+        }
+        dst++;
+    }
+
+    return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c
new file mode 100755
index 0000000..ef04ae8
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     %created_by:    sra % (CM/S)
+     %name:          Mac3s_Sat_16x16.c % (CM/S)
+     %version:       1 % (CM/S)
+     %date_created:  Fri Nov 13 12:07:13 2009 % (CM/S)
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION Mac3S_16X16
+***********************************************************************************/
+
+void Mac3s_Sat_16x16( const LVM_INT16 *src,
+                     const LVM_INT16 val,
+                     LVM_INT16 *dst,
+                     LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT16 srcval;
+    LVM_INT32 Temp,dInVal;
+
+
+    for (ii = n; ii != 0; ii--)
+    {
+        srcval=*src;
+        src++;
+
+        Temp = (srcval *val)>>15;
+
+        dInVal  = (LVM_INT32)*dst;
+
+        Temp = Temp + dInVal;
+
+        if (Temp > 0x00007FFF)
+        {
+            *dst = 0x7FFF;
+        }
+        else if (Temp < -0x00008000)
+        {
+            *dst = - 0x8000;
+        }
+        else
+        {
+            *dst = (LVM_INT16)Temp;
+        }
+
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
new file mode 100755
index 0000000..746a273
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+   FUNCTION MAC3S_16X16
+***********************************************************************************/
+
+void Mac3s_Sat_32x16(  const LVM_INT32 *src,
+                     const LVM_INT16 val,
+                     LVM_INT32 *dst,
+                     LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT32 srcval,temp, dInVal, dOutVal;
+
+
+    for (ii = n; ii != 0; ii--)
+    {
+        srcval=*src;
+        src++;
+
+        MUL32x16INTO32(srcval,val,temp,15)
+
+            dInVal  = *dst;
+        dOutVal = temp + dInVal;
+
+
+        if ((((dOutVal ^ temp) & (dOutVal ^ dInVal)) >> 31)!=0)     /* overflow / underflow */
+        {
+            if(temp<0)
+            {
+                dOutVal=0x80000000l;
+            }
+            else
+            {
+                dOutVal=0x7FFFFFFFl;
+            }
+        }
+
+        *dst = dOutVal;
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
new file mode 100755
index 0000000..36de6c1
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+/**********************************************************************************
+   FUNCTION MIXINSOFT_D32C31_SAT
+***********************************************************************************/
+
+void MixInSoft_D32C31_SAT( Mix_1St_Cll_t        *pInstance,
+                           const LVM_INT32      *src,
+                                 LVM_INT32      *dst,
+                                 LVM_INT16      n)
+{
+    char HardMixing = TRUE;
+
+    if(n<=0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Alpha == 0){
+            pInstance->Current = pInstance->Target;
+        }else if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
+                 (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            Core_MixInSoft_D32C31_SAT( pInstance, src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
+            if ((pInstance->Target>>16) == 0x7FFF)
+                Add2_Sat_32x32( src, dst, n );
+            else{
+                Core_MixInSoft_D32C31_SAT( pInstance, src, dst, n);
+                pInstance->Current = pInstance->Target; /* In case the core function would have changed the Current value */
+            }
+        }
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+    /* Call back before the hard mixing, because in this case, hard mixing makes
+       use of the core soft mix function which can change the Current value!      */
+
+    if (pInstance->CallbackSet){
+        if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
+            (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
+            pInstance->CallbackSet = FALSE;
+            if (pInstance->pCallBack != 0){
+                (*pInstance->pCallBack) ( pInstance->pCallbackHandle, pInstance->pGeneralPurpose,pInstance->CallbackParam );
+            }
+        }
+    }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
new file mode 100755
index 0000000..5cf1a29
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+#define TRUE          1
+#define FALSE         0
+
+
+
+/**********************************************************************************
+   FUNCTION MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+
+void MixSoft_1St_D32C31_WRA(    Mix_1St_Cll_t       *pInstance,
+                                const LVM_INT32     *src,
+                                      LVM_INT32     *dst,
+                                      LVM_INT16     n)
+{
+    char HardMixing = TRUE;
+
+    if(n<=0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if (pInstance->Current != pInstance->Target)
+    {
+        if(pInstance->Alpha == 0){
+            pInstance->Current = pInstance->Target;
+        }else if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
+                 (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
+        }else{
+            /* Soft mixing has to be applied */
+            HardMixing = FALSE;
+            Core_MixSoft_1St_D32C31_WRA( pInstance, src, dst, n);
+        }
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    if (HardMixing){
+        if (pInstance->Target == 0)
+            LoadConst_32(0, dst, n);
+        else if ((pInstance->Target>>16) == 0x7FFF){
+            if (src != dst)
+                Copy_16((LVM_INT16*)src, (LVM_INT16*)dst, (LVM_INT16)(n * 2));
+        }
+        else
+            Mult3s_32x16( src, (LVM_INT16)(pInstance->Current>>16), dst, n );
+    }
+
+    /******************************************************************************
+       CALL BACK
+    *******************************************************************************/
+
+    if (pInstance->CallbackSet){
+        if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
+            (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
+            pInstance->Current = pInstance->Target; /* Difference is not significant anymore.  Make them equal. */
+            pInstance->CallbackSet = FALSE;
+            if (pInstance->pCallBack != 0){
+                (*pInstance->pCallBack) ( pInstance->pCallbackHandle, pInstance->pGeneralPurpose,pInstance->CallbackParam );
+            }
+        }
+    }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
new file mode 100755
index 0000000..83f95ac
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: nxp007753 $*/
+/*     $Revision: 1316 $*/
+/*     $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+
+/**********************************************************************************
+   FUNCTION MIXSOFT_2ST_D32C31_SAT
+***********************************************************************************/
+
+void MixSoft_2St_D32C31_SAT(    Mix_2St_Cll_t       *pInstance,
+                                const LVM_INT32     *src1,
+                                const LVM_INT32     *src2,
+                                      LVM_INT32     *dst,
+                                      LVM_INT16     n)
+{
+
+    if(n<=0)    return;
+
+    /******************************************************************************
+       SOFT MIXING
+    *******************************************************************************/
+    if ((pInstance->Current1 != pInstance->Target1) || (pInstance->Current2 != pInstance->Target2))
+    {
+        MixSoft_1St_D32C31_WRA( (Mix_1St_Cll_t*) pInstance, src1, dst, n);
+        MixInSoft_D32C31_SAT( (void *) &pInstance->Alpha2,     /* Cast to void: no dereferencing in function*/
+            src2, dst, n);
+    }
+
+    /******************************************************************************
+       HARD MIXING
+    *******************************************************************************/
+
+    else
+    {
+        if (pInstance->Current1 == 0)
+            MixSoft_1St_D32C31_WRA( (void *) &pInstance->Alpha2, /* Cast to void: no dereferencing in function*/
+            src2, dst, n);
+        else if (pInstance->Current2 == 0)
+            MixSoft_1St_D32C31_WRA( (Mix_1St_Cll_t*) pInstance, src1, dst, n);
+        else
+            Core_MixHard_2St_D32C31_SAT( pInstance, src1, src2, dst, n);
+    }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mixer_private.h b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
new file mode 100755
index 0000000..d012548
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __MIXER_PRIVATE_H__
+#define __MIXER_PRIVATE_H__
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer.h"
+
+#define POINT_ZERO_ONE_DB 2473805 /* 0.01 dB on a full scale signal = (10^(0.01/20) -1) * 2^31 */
+
+/**********************************************************************************
+   DEFINITIONS
+***********************************************************************************/
+
+/**********************************************************************************/
+
+#endif //#ifndef __MIXER_PRIVATE_H__
+
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c
new file mode 100755
index 0000000..b053e55
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION MonoTo2I_16
+***********************************************************************************/
+
+void MonoTo2I_16( const LVM_INT16 *src,
+                 LVM_INT16 *dst,
+                 LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    src += (n-1);
+    dst += ((n*2)-1);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *src;
+        dst--;
+
+        *dst = *src;
+        dst--;
+        src--;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
new file mode 100755
index 0000000..e8164bb
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION MonoTo2I_32
+***********************************************************************************/
+
+void MonoTo2I_32( const LVM_INT32  *src,
+                 LVM_INT32  *dst,
+                 LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    src += (n-1);
+    dst += ((n*2)-1);
+
+    for (ii = n; ii != 0; ii--)
+    {
+        *dst = *src;
+        dst--;
+
+        *dst = *src;
+        dst--;
+        src--;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
new file mode 100755
index 0000000..ee83524
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+FUNCTION MULT3S_16X16
+***********************************************************************************/
+
+void Mult3s_32x16( const LVM_INT32 *src,
+                  const LVM_INT16 val,
+                  LVM_INT32 *dst,
+                  LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT32 srcval,temp;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        srcval=*src;
+        src++;
+
+        MUL32x16INTO32(srcval,val,temp,15)
+
+        *dst = temp;
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
new file mode 100755
index 0000000..1428777
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "CompLim_private.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 NonLinComp_D16                                             */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Non-linear compression by companding. The function works on a sample by sample      */
+/*  basis by increasing the level near the zero crossing. This gives a ttrade-off       */
+/*  between THD and compression. It uses the equation:                                  */
+/*                                                                                      */
+/*        Output = Input + K * (Input - Input^2)        if Input >  0                   */
+/*               = Input + K * (Input + Input^2)      if Input <= 0                     */
+/*                                                                                      */
+/*    The value of K controls the amount of compression and as a side effect the amount */
+/*  distortion introduced. The amount of compression is signal dependent and the values */
+/*  given below are approximate.                                                        */
+/*                                                                                      */
+/*        Gain (fractional)  Gain (integer)    Compression          Pk-Pk THD           */
+/*            1.0                 32767            +6dB            16dB                 */
+/*            0.78                25559            +5dB            19dB                 */
+/*            0.6                 19661            +4dB            21dB                 */
+/*            0.41                13435            +3dB            24dB                 */
+/*            0.26                 8520            +2dB            28dB                 */
+/*            0.12                 3932            +1dB            34dB                 */
+/*            0.0                     0            +0dB            98dB                 */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*    Gain            -    compression control parameter                                */
+/*    pDataIn         -    pointer to the input data buffer                             */
+/*    pDataOut        -    pointer to the output data buffer                            */
+/*    BlockLength     -    number of samples to process                                 */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*    None                                                                              */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+void NonLinComp_D16(LVM_INT16        Gain,
+                      LVM_INT16        *pDataIn,
+                    LVM_INT16        *pDataOut,
+                    LVM_INT32        BlockLength)
+{
+
+    LVM_INT16            Sample;                    /* Input samples */
+    LVM_INT32            SampleNo;                /* Sample index */
+    LVM_INT16            Temp;
+
+
+    /*
+     * Process a block of samples
+     */
+    for(SampleNo = 0; SampleNo<BlockLength; SampleNo++)
+    {
+
+        /*
+         * Read the input
+         */
+        Sample = *pDataIn;
+        pDataIn++;
+
+
+        /*
+         * Apply the compander, this compresses the signal at the expense of
+         * harmonic distortion. The amount of compression is control by the
+         * gain factor
+         */
+        if ((LVM_INT32)Sample != -32768)
+        {
+            Temp = (LVM_INT16)((Sample * Sample) >> 15);
+            if(Sample >0)
+            {
+                Sample = (LVM_INT16)(Sample + ((Gain * (Sample - Temp)) >> 15));
+            }
+            else
+            {
+                Sample = (LVM_INT16)(Sample + ((Gain * (Sample + Temp)) >> 15));
+            }
+        }
+
+
+        /*
+         * Save the output
+         */
+        *pDataOut = Sample;
+        pDataOut++;
+
+
+    }
+
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
new file mode 100755
index 0000000..06cfe88
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q14 format
+ pBiquadState->coefs[3] is Gain, in Q11 format
+
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
+                                     LVM_INT32               *pDataIn,
+                                     LVM_INT32               *pDataOut,
+                                     LVM_INT16               NrSamples)
+    {
+        LVM_INT32 ynL,ynR,ynLO,ynRO,templ;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL= (A0 (Q14) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>14)  in Q0*/
+            templ=(*pDataIn)-pBiquadState->pDelays[2];
+            MUL32x16INTO32(templ,pBiquadState->coefs[0],ynL,14)
+
+            /* ynL+= ((-B2 (Q14) * y(n-2)L (Q0) ) >>14) in Q0*/
+            MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[1],templ,14)
+            ynL+=templ;
+
+            /* ynL+= ((-B1 (Q14) * y(n-1)L (Q0) ) >>14) in Q0 */
+            MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[2],templ,14)
+            ynL+=templ;
+
+            /* ynLO= ((Gain (Q11) * ynL (Q0))>>11) in Q0*/
+            MUL32x16INTO32(ynL,pBiquadState->coefs[3],ynLO,11)
+
+            /* ynLO=( ynLO(Q0) + x(n)L (Q0) ) in Q0*/
+            ynLO+= (*pDataIn);
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR= (A0 (Q14) * (x(n)R (Q0) - x(n-2)R (Q0) ) >>14)   in Q0*/
+            templ=(*(pDataIn+1))-pBiquadState->pDelays[3];
+            MUL32x16INTO32(templ,pBiquadState->coefs[0],ynR,14)
+
+            /* ynR+= ((-B2 (Q14) * y(n-2)R (Q0) ) >>14)  in Q0*/
+            MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[1],templ,14)
+            ynR+=templ;
+
+            /* ynR+= ((-B1 (Q14) * y(n-1)R (Q0) ) >>14)  in Q0 */
+            MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[2],templ,14)
+            ynR+=templ;
+
+            /* ynRO= ((Gain (Q11) * ynR (Q0))>>11) in Q0*/
+            MUL32x16INTO32(ynR,pBiquadState->coefs[3],ynRO,11)
+
+            /* ynRO=( ynRO(Q0) + x(n)R (Q0) ) in Q0*/
+            ynRO+= (*(pDataIn+1));
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5]=ynR; /* Update y(n-1)R in Q0*/
+            pBiquadState->pDelays[4]=ynL; /* Update y(n-1)L in Q0*/
+            pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+            pDataIn++;
+            pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut=ynLO; /* Write Left output in Q0*/
+            pDataOut++;
+            *pDataOut=ynRO; /* Write Right ouput in Q0*/
+            pDataOut++;
+
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
new file mode 100755
index 0000000..5b78f62
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+ pBiquadState->coefs[3] is Gain, in Q11 format
+
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+void PK_2I_D32F32C30G11_TRC_WRA_01 ( Biquad_Instance_t       *pInstance,
+                                     LVM_INT32               *pDataIn,
+                                     LVM_INT32               *pDataOut,
+                                     LVM_INT16               NrSamples)
+    {
+        LVM_INT32 ynL,ynR,ynLO,ynRO,templ;
+        LVM_INT16 ii;
+        PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+         for (ii = NrSamples; ii != 0; ii--)
+         {
+
+
+            /**************************************************************************
+                            PROCESSING OF THE LEFT CHANNEL
+            ***************************************************************************/
+            /* ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>30)  in Q0*/
+            templ=(*pDataIn)-pBiquadState->pDelays[2];
+            MUL32x32INTO32(templ,pBiquadState->coefs[0],ynL,30)
+
+            /* ynL+= ((-B2 (Q30) * y(n-2)L (Q0) ) >>30) in Q0*/
+            MUL32x32INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[1],templ,30)
+            ynL+=templ;
+
+            /* ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) >>30) in Q0 */
+            MUL32x32INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[2],templ,30)
+            ynL+=templ;
+
+            /* ynLO= ((Gain (Q11) * ynL (Q0))>>11) in Q0*/
+            MUL32x16INTO32(ynL,pBiquadState->coefs[3],ynLO,11)
+            /* ynLO=( ynLO(Q0) + x(n)L (Q0) ) in Q0*/
+            ynLO+= (*pDataIn);
+
+            /**************************************************************************
+                            PROCESSING OF THE RIGHT CHANNEL
+            ***************************************************************************/
+            /* ynR= (A0 (Q30) * (x(n)R (Q0) - x(n-2)R (Q0) ) >>30)   in Q0*/
+            templ=(*(pDataIn+1))-pBiquadState->pDelays[3];
+            MUL32x32INTO32(templ,pBiquadState->coefs[0],ynR,30)
+
+            /* ynR+= ((-B2 (Q30) * y(n-2)R (Q0) ) >>30)  in Q0*/
+            MUL32x32INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[1],templ,30)
+            ynR+=templ;
+
+            /* ynR+= ((-B1 (Q30) * y(n-1)R (Q0) ) >>30)  in Q0 */
+            MUL32x32INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[2],templ,30)
+            ynR+=templ;
+
+            /* ynRO= ((Gain (Q11) * ynR (Q0))>>11) in Q0*/
+            MUL32x16INTO32(ynR,pBiquadState->coefs[3],ynRO,11)
+
+            /* ynRO=( ynRO(Q0) + x(n)R (Q0) ) in Q0*/
+            ynRO+= (*(pDataIn+1));
+
+            /**************************************************************************
+                            UPDATING THE DELAYS
+            ***************************************************************************/
+            pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+            pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+            pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+            pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+            pBiquadState->pDelays[5]=ynR; /* Update y(n-1)R in Q0*/
+            pBiquadState->pDelays[4]=ynL; /* Update y(n-1)L in Q0*/
+            pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+            pDataIn++;
+            pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+            pDataIn++;
+
+            /**************************************************************************
+                            WRITING THE OUTPUT
+            ***************************************************************************/
+            *pDataOut=ynLO; /* Write Left output in Q0*/
+            pDataOut++;
+            *pDataOut=ynRO; /* Write Right ouput in Q0*/
+            pDataOut++;
+        }
+
+    }
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..e7bcd0c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
+
+
+void  PK_2I_D32F32CllGss_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_Taps_t   *pTaps,
+                                         PK_C32_Coefs_t            *pCoef)
+{
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays       =(LVM_INT32 *) pTaps;
+
+  pBiquadState->coefs[0]=pCoef->A0;
+
+  pBiquadState->coefs[1]=pCoef->B2;
+
+  pBiquadState->coefs[2]=pCoef->B1;
+
+  pBiquadState->coefs[3]=pCoef->G;
+
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..741f504
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
+#define _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT32         coefs[5];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..f02305e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
+
+void  PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_Instance_t         *pInstance,
+                                         Biquad_2I_Order2_Taps_t   *pTaps,
+                                         PK_C16_Coefs_t            *pCoef)
+{
+  PFilter_State pBiquadState = (PFilter_State) pInstance;
+  pBiquadState->pDelays       =(LVM_INT32 *) pTaps;
+
+  pBiquadState->coefs[0]=pCoef->A0;
+
+  pBiquadState->coefs[1]=pCoef->B2;
+
+  pBiquadState->coefs[2]=pCoef->B1;
+
+  pBiquadState->coefs[3]=pCoef->G;
+
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..ca31669
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
+#define _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+
+/* The internal state variables are implemented in a (for the user)  hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.        */
+typedef struct _Filter_State_
+{
+  LVM_INT32 *       pDelays;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT32         coefs[5];       /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
new file mode 100755
index 0000000..e449a7f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION Shift_Sat_v16xv16
+***********************************************************************************/
+
+void Shift_Sat_v16xv16 (const   LVM_INT16   val,
+                        const   LVM_INT16   *src,
+                        LVM_INT16   *dst,
+                        LVM_INT16   n)
+{
+    LVM_INT32   temp;
+    LVM_INT32   ii;
+    LVM_INT16   RShift;
+    if(val>0)
+    {
+        for (ii = n; ii != 0; ii--)
+        {
+            temp = (LVM_INT32)*src;
+            src++;
+
+            temp = temp << val;
+
+            if (temp > 0x00007FFF)
+            {
+                *dst = 0x7FFF;
+            }
+            else if (temp < -0x00008000)
+            {
+                *dst = - 0x8000;
+            }
+            else
+            {
+                *dst = (LVM_INT16)temp;
+            }
+            dst++;
+        }
+    }
+    else if(val<0)
+    {
+        RShift=(LVM_INT16)(-val);
+
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = (LVM_INT16)(*src >> RShift);
+            dst++;
+            src++;
+        }
+    }
+    else
+    {
+        if(src!=dst)
+        {
+            Copy_16(src,dst,n);
+        }
+    }
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
new file mode 100755
index 0000000..0ab98ea
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::                                                        */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1000 $*/
+/*     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION Shift_Sat_v32xv32
+***********************************************************************************/
+
+void Shift_Sat_v32xv32 (const   LVM_INT16   val,
+                        const   LVM_INT32   *src,
+                        LVM_INT32   *dst,
+                        LVM_INT16   n)
+{
+    LVM_INT32   ii;
+    LVM_INT16   RShift;
+
+    if(val>0)
+    {
+        LVM_INT32 a,b;
+
+        for (ii = n; ii != 0; ii--)
+        {
+            a=*src;
+            src++;
+
+            b=(a<<val);
+
+            if( (b>>val) != a ) /* if overflow occured, right shift will show difference*/
+            {
+                if(a<0)
+                {
+                    b=0x80000000l;
+                }
+                else
+                {
+                    b=0x7FFFFFFFl;
+                }
+            }
+
+            *dst = b;
+            dst++;
+        }
+    }
+    else if(val<0)
+    {
+        RShift=(LVM_INT16)(-val);
+        for (ii = n; ii != 0; ii--)
+        {
+            *dst = (*src >> RShift);
+            dst++;
+            src++;
+        }
+    }
+    else
+    {
+        if(src!=dst)
+        {
+            Copy_16((LVM_INT16 *)src,(LVM_INT16 *)dst,(LVM_INT16)(n<<1));
+        }
+    }
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
new file mode 100755
index 0000000..ac0343f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     %created_by:    sra % (CM/S)*/
+/*     %name:          dB_to_Lin32.c % (CM/S)*/
+/*     %version:       2 % (CM/S)*/
+/*     %date_created:  Wed Jun 18 11:27:46 2008 % (CM/S)*/
+/*                                                                      */
+/************************************************************************/
+
+/*######################################################################################*/
+/*  Include files                                                                       */
+/*######################################################################################*/
+
+#include "ScalarArithmetic.h"
+
+
+/****************************************************************************************
+ *  Name        : dB_to_Lin32()
+ *  Input       : Signed 16-bit integer
+ *                  MSB (16) = sign bit
+ *                  (15->05) = integer part
+ *                  (04->01) = decimal part
+ *  Output      : Signed 32-bit integer
+ *                  MSB (32) = sign bit
+ *                  (31->16) = integer part
+ *                  (15->01) = decimal part
+ *  Returns     : Lin value format 1.16.15
+ *  Description :
+ *  Remarks     :  Makes an approximation to the conversion by counting the number
+ *                 of 6dB steps for use as shifts and then interpolates with a remainder
+ *                 with the equation:
+ *
+ *                 Correction = (Remainder / 1.5029) - (Remainder^2 / 6)
+ *
+ *                 The two coefficients are scaled from 0x40000000 in 96 steps and calculated
+ *                 as follows:
+ *
+ *                 FIRST_COEF  = 0x80000000 / (96 * 1.5029)
+ *                 SECOND_COEF = 0x80000000 / (96^2 * 6)
+ *
+ ****************************************************************************************/
+
+#define FOUR_OVER_SIX    21846                  /* (4 / 6) * 2^15 */
+#define SIX_DB           96                     /* 6 * 16 or 6dB in Q11.4 format */
+#define FIRST_COEF_NEG   14884305
+#define FIRST_COEF_POS   7442152                /* FIRST_COEF_NEG / 2 */
+#define SECOND_COEF      38836
+#define MAX_VALUE        1536                   /* 96 * 16 */
+
+LVM_INT32   dB_to_Lin32(LVM_INT16    db_fix)
+{
+    LVM_INT32 Lin_val_32;
+    LVM_INT16 Shift;
+    LVM_INT32 Remain;
+
+
+    /*
+     * Check sign of the input
+     */
+    if (db_fix<0)
+    {
+        if (db_fix > -MAX_VALUE)
+        {
+            Shift  = (LVM_INT16)((((LVM_UINT32)(-db_fix) >> 4) * FOUR_OVER_SIX) >> 17);        /* Number of 6dB steps in Q11.4 format */
+            Remain = -db_fix - (Shift * SIX_DB);
+            Remain = (0x7FFFFFFF - (Remain * FIRST_COEF_NEG)) + (Remain * Remain * SECOND_COEF);
+            Lin_val_32 = (LVM_INT32)((LVM_UINT32)Remain >> (16 + Shift));
+        }
+        else
+        {
+            Lin_val_32 = 0;
+        }
+    }
+    else
+    {
+        if (db_fix < MAX_VALUE)
+        {
+            Shift  = (LVM_INT16)((((LVM_UINT32)db_fix >> 4) * FOUR_OVER_SIX) >> 17);        /* Number of 6dB steps in Q11.4 format */
+            Remain = db_fix - (Shift * SIX_DB);
+            Remain = 0x3FFFFFFF + (Remain * FIRST_COEF_POS) + (Remain * Remain * SECOND_COEF);
+            Lin_val_32 = (LVM_INT32)((LVM_UINT32)Remain >> (15 - Shift));
+        }
+        else
+        {
+            Lin_val_32 = 0x7FFFFFFF;
+        }
+    }
+
+
+    return Lin_val_32;  /* format 1.16.15 */
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.c b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.c
new file mode 100755
index 0000000..b500979
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1000 $
+     $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+   INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+   FUNCTION MULT3S_16X16
+***********************************************************************************/
+
+void Mult3s_16x16( const LVM_INT16 *src,
+                  const LVM_INT16 val,
+                  LVM_INT16 *dst,
+                  LVM_INT16 n)
+{
+    LVM_INT16 ii;
+    LVM_INT32 temp;
+
+    for (ii = n; ii != 0; ii--)
+    {
+        temp = (LVM_INT32)(*src) * (LVM_INT32)val;
+        src++;
+
+        *dst = (LVM_INT16)(temp >> 15);
+        dst++;
+    }
+
+    return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
new file mode 100755
index 0000000..7ba583f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1005 $
+     $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Header file for the application layer interface of the N-Band equaliser.            */
+/*                                                                                      */
+/*  This files includes all definitions, types, structures and function                 */
+/*  prototypes required by the calling layer. All other types, structures and           */
+/*  functions are private.                                                              */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*  Note: 1                                                                             */
+/*  =======                                                                             */
+/*  The algorithm can execute either with separate input and output buffers or with     */
+/*  a common buffer, i.e. the data is processed in-place.                               */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*  Note: 2                                                                             */
+/*  =======                                                                             */
+/*  Two data formats are support Stereo and Mono-In-Stereo. The data is interleaved as  */
+/*  follows:                                                                            */
+/*              Byte Offset         Stereo Input         Mono-In-Stereo Input           */
+/*              ===========         ============         ====================           */
+/*                  0               Left Sample #1          Mono Sample #1              */
+/*                  2               Right Sample #1         Mono Sample #1              */
+/*                  4               Left Sample #2          Mono Sample #2              */
+/*                  6               Right Sample #2         Mono Sample #2              */
+/*                  .                      .                     .                      */
+/*                  .                      .                     .                      */
+/*                                                                                      */
+/*  Mono format data is not supported, the calling routine must convert a Mono stream   */
+/*  in to Mono-In-Stereo format.                                                        */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*  Note: 3                                                                             */
+/*  =======                                                                             */
+/*  The format of the data in the filter band definition structure is as follows:       */
+/*                                                                                      */
+/*      Gain        is in integer dB, range -15dB to +15dB inclusive                    */
+/*      Frequency   is the centre frequency in Hz, range DC to Nyquist                  */
+/*      QFactor     is the Q multiplied by 100, range 0.25 (25) to 12 (1200)            */
+/*                                                                                      */
+/*  Example:                                                                            */
+/*      Gain = 7            7dB gain                                                    */
+/*      Frequency = 2467    Centre frequency = 2.467kHz                                 */
+/*      QFactor = 1089      Q = 10.89                                                   */
+/*                                                                                      */
+/*  The equaliser filters are passed as a pointer to and array of filter band           */
+/*  definitions structures. There must be one filter definition for each band.          */
+/*                                                                                      */
+/****************************************************************************************/
+
+
+#ifndef __LVEQNB_H__
+#define __LVEQNB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Common.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Definitions                                                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory table */
+#define LVEQNB_MEMREGION_INSTANCE          0   /* Offset to the instance memory region */
+#define LVEQNB_MEMREGION_PERSISTENT_DATA   1   /* Offset to persistent data memory region */
+#define LVEQNB_MEMREGION_PERSISTENT_COEF   2   /* Offset to persistent coefficient region */
+#define LVEQNB_MEMREGION_SCRATCH           3   /* Offset to data scratch memory region */
+#define LVEQNB_NR_MEMORY_REGIONS           4   /* Number of memory regions */
+
+/* Callback events */
+#define LVEQNB_EVENT_NONE                   0x0000    /* Not a valid event */
+#define LVEQNB_EVENT_ALGOFF                 0x0001    /* EQNB has completed switch off */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Types                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Instance handle */
+typedef void *LVEQNB_Handle_t;
+
+
+/* Operating modes */
+typedef enum
+{
+    LVEQNB_BYPASS   = 0,
+    LVEQNB_ON       = 1,
+    LVEQNB_MODE_MAX = LVM_MAXINT_32
+} LVEQNB_Mode_en;
+
+
+/* Filter mode control */
+typedef enum
+{
+    LVEQNB_FILTER_OFF   = 0,
+    LVEQNB_FILTER_ON    = 1,
+    LVEQNB_FILTER_DUMMY = LVM_MAXINT_32
+} LVEQNB_FilterMode_en;
+
+
+/* Memory Types */
+typedef enum
+{
+    LVEQNB_PERSISTENT      = 0,
+    LVEQNB_PERSISTENT_DATA = 1,
+    LVEQNB_PERSISTENT_COEF = 2,
+    LVEQNB_SCRATCH         = 3,
+    LVEQNB_MEMORY_MAX      = LVM_MAXINT_32
+} LVEQNB_MemoryTypes_en;
+
+
+/* Function return status */
+typedef enum
+{
+    LVEQNB_SUCCESS        = 0,                          /* Successful return from a routine */
+    LVEQNB_ALIGNMENTERROR = 1,                          /* Memory alignment error */
+    LVEQNB_NULLADDRESS    = 2,                          /* NULL allocation address */
+    LVEQNB_TOOMANYSAMPLES = 3,                          /* Maximum block size exceeded */
+    LVEQNB_STATUS_MAX     = LVM_MAXINT_32
+} LVEQNB_ReturnStatus_en;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Linked enumerated type and capability definitions                                   */
+/*                                                                                      */
+/*  The capability definitions are used to define the required capabilities at          */
+/*  initialisation, these are added together to give the capability word. The           */
+/*  enumerated type is used to select the mode through a control function at run time.  */
+/*                                                                                      */
+/*  The capability definition is related to the enumerated type value by the equation:  */
+/*                                                                                      */
+/*          Capability_value = 2^Enumerated_value                                       */
+/*                                                                                      */
+/*  For example, a module could be configurd at initialisation to support two sample    */
+/*  rates only by calling the init function with the value:                             */
+/*      Capabilities.SampleRate = LVEQNB_CAP_32000 + LVEQNB_CAP_44100;                  */
+/*                                                                                      */
+/*  and at run time it would be passed the value LVEQNB_FS_32000 through the control    */
+/*  function to select operation at 32kHz                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/*
+ * Supported source data formats
+ */
+#define LVEQNB_CAP_STEREO                  1
+#define LVEQNB_CAP_MONOINSTEREO            2
+
+typedef enum
+{
+    LVEQNB_STEREO       = 0,
+    LVEQNB_MONOINSTEREO = 1,
+    LVEQNB_SOURCE_MAX   = LVM_MAXINT_32
+} LVEQNB_SourceFormat_en;
+
+
+/*
+ * Supported sample rates in samples per second
+ */
+#define LVEQNB_CAP_FS_8000                 1
+#define LVEQNB_CAP_FS_11025                2
+#define LVEQNB_CAP_FS_12000                4
+#define LVEQNB_CAP_FS_16000                8
+#define LVEQNB_CAP_FS_22050                16
+#define LVEQNB_CAP_FS_24000                32
+#define LVEQNB_CAP_FS_32000                64
+#define LVEQNB_CAP_FS_44100                128
+#define LVEQNB_CAP_FS_48000                256
+
+typedef enum
+{
+    LVEQNB_FS_8000  = 0,
+    LVEQNB_FS_11025 = 1,
+    LVEQNB_FS_12000 = 2,
+    LVEQNB_FS_16000 = 3,
+    LVEQNB_FS_22050 = 4,
+    LVEQNB_FS_24000 = 5,
+    LVEQNB_FS_32000 = 6,
+    LVEQNB_FS_44100 = 7,
+    LVEQNB_FS_48000 = 8,
+    LVEQNB_FS_MAX   = LVM_MAXINT_32
+} LVEQNB_Fs_en;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Structures                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory region definition */
+typedef struct
+{
+    LVM_UINT32                  Size;                   /* Region size in bytes */
+    LVM_UINT16                  Alignment;              /* Region alignment in bytes */
+    LVEQNB_MemoryTypes_en       Type;                   /* Region type */
+    void                        *pBaseAddress;          /* Pointer to the region base address */
+} LVEQNB_MemoryRegion_t;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+    LVEQNB_MemoryRegion_t       Region[LVEQNB_NR_MEMORY_REGIONS];  /* One definition for each region */
+} LVEQNB_MemTab_t;
+
+
+/* Equaliser band definition */
+typedef struct
+{
+    LVM_INT16                   Gain;                   /* Band gain in dB */
+    LVM_UINT16                  Frequency;              /* Band centre frequency in Hz */
+    LVM_UINT16                  QFactor;                /* Band quality factor */
+} LVEQNB_BandDef_t;
+
+
+/* Parameter structure */
+typedef struct
+{
+    /* General parameters */
+    LVEQNB_Mode_en              OperatingMode;
+    LVEQNB_Fs_en                SampleRate;
+    LVEQNB_SourceFormat_en      SourceFormat;
+
+    /* Equaliser parameters */
+    LVM_UINT16                  NBands;                 /* Number of bands */
+    LVEQNB_BandDef_t            *pBandDefinition;       /* Pointer to equaliser definitions */
+
+} LVEQNB_Params_t;
+
+
+/* Capability structure */
+typedef struct
+{
+    /* General parameters */
+    LVM_UINT16                  SampleRate;
+    LVM_UINT16                  SourceFormat;
+    LVM_UINT16                  MaxBlockSize;
+    LVM_UINT16                  MaxBands;
+
+    /* Callback parameters */
+    LVM_Callback                CallBack;               /* Bundle callback */
+    void                        *pBundleInstance;       /* Bundle instance handle */
+
+} LVEQNB_Capabilities_t;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Function Prototypes                                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Memory                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pCapabilities           Pointer to the default capabilities                         */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeded                                                   */
+/*  LVEQNB_NULLADDRESS      When any of pMemoryTable and pCapabilities is NULL address  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t            hInstance,
+                                     LVEQNB_MemTab_t            *pMemoryTable,
+                                     LVEQNB_Capabilities_t      *pCapabilities);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Init                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Create and initialisation function for the N-Band equalliser module                 */
+/*                                                                                      */
+/*  This function can be used to create an algorithm instance by calling with           */
+/*  hInstance set to NULL. In this case the algorithm returns the new instance          */
+/*  handle.                                                                             */
+/*                                                                                      */
+/*  This function can be used to force a full re-initialisation of the algorithm        */
+/*  by calling with hInstance = Instance Handle. In this case the memory table          */
+/*  should be correct for the instance, this can be ensured by calling the function     */
+/*  LVEQNB_Memory before calling this function.                                         */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pMemoryTable            Pointer to the memory definition table                      */
+/*  pCapabilities           Pointer to the initialisation capabilities                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Initialisation succeeded                                    */
+/*  LVEQNB_NULLADDRESS        When pCapabilities or pMemoryTableis or phInstance are NULL */
+/*  LVEQNB_NULLADDRESS        One or more of the memory regions has a NULL base address   */
+/*                          pointer for a memory region with a non-zero size.           */
+/*                                                                                      */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  The instance handle is the pointer to the base address of the first memory      */
+/*      region.                                                                         */
+/*  2.  This function must not be interrupted by the LVEQNB_Process function            */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t          *phInstance,
+                                   LVEQNB_MemTab_t          *pMemoryTable,
+                                   LVEQNB_Capabilities_t    *pCapabilities);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVEQNB_GetParameters                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the equaliser module parameters. The current parameter set is returned      */
+/*  via the parameter pointer.                                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance handle                                            */
+/*  pParams                  Pointer to an empty parameter structure                    */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS           Succeeds                                                   */
+/*  LVEQNB_NULLADDRESS       Instance or pParams  is NULL pointer                       */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t     hInstance,
+                                            LVEQNB_Params_t     *pParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVEQNB_GetCapabilities                                     */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the equaliser module capabilities. The capabilities set is returned         */
+/*  via the pointer.                                                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance handle                                            */
+/*  pCapabilities            Pointer to an empty capability structure                   */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS           Succeeds                                                   */
+/*  LVEQNB_NULLADDRESS       hInstance or pCapabilities is NULL                         */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t           hInstance,
+                                              LVEQNB_Capabilities_t     *pCapabilities);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Control                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the equaliser module parameters.                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pParams                 Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeded                                                   */
+/*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
+/*  LVEQNB_NULLADDRESS      NULL address for the equaliser filter definitions and the   */
+/*                          number of bands is non-zero                                 */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t       hInstance,
+                                      LVEQNB_Params_t       *pParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Process                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the LifeVibes module.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeded                                                   */
+/*  LVEQNB_NULLADDRESS      When hInstance, pInData or pOutData are NULL                */
+/*  LVEQNB_ALIGNMENTERROR   When pInData or pOutData are not 32-bit aligned             */
+/*  LVEQNB_TOOMANYSAMPLES   NumSamples was larger than the maximum block size           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
+                                      const LVM_INT16       *pInData,
+                                      LVM_INT16             *pOutData,
+                                      LVM_UINT16            NumSamples);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif      /* __LVEQNB__ */
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
new file mode 100755
index 0000000..4881049
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1005 $
+     $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Includes                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB_Private.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*    Defines                                                                           */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define PI 3.14159265358979
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  LVEQNB_DoublePrecCoefs                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Calculate double precision coefficients    for a peaking filter                   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  Fs                           Sampling frequency index                               */
+/*  pFilterDefinition          Pointer to the filter definition                         */
+/*  pCoefficients            Pointer to the coefficients                                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS            Always succeeds                                           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The equations used are as follows:                                               */
+/*                                                                                      */
+/*      G  = 10^(GaindB/20) - 1                                                         */
+/*      t0 = 2 * Pi * Fc / Fs                                                           */
+/*      D  = 1                  if GaindB >= 0                                          */
+/*      D  = 1 / (1 + G)        if GaindB <  0                                          */
+/*                                                                                      */
+/*      b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0)                                       */
+/*      b1 = (0.5 - b2) * (1 - coserr(t0))                                              */
+/*      a0 = (0.5 + b2) / 2                                                             */
+/*                                                                                      */
+/*  Where:                                                                              */
+/*      GaindB      is the gain in dBs, range -15dB to +15dB                            */
+/*      Fc          is the centre frequency, DC to Fs/50                                */
+/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
+/*      Q           is the Q factor, 0.25 to 12 (represented by 25 to 1200)             */
+/*                                                                                      */
+/*  2. The double precision coefficients are only used when fc is less than fs/85, so   */
+/*     the cosine of t0 is always close to 1.0. Instead of calculating the cosine       */
+/*     itself the difference from the value 1.0 is calculated, this can be done with    */
+/*     lower precision maths.                                                           */
+/*                                                                                      */
+/*  3. The value of the B2 coefficient is only calculated as a single precision value,  */
+/*     small errors in this value have a combined effect on the Q and Gain but not the  */
+/*     the frequency of the filter.                                                     */
+/*                                                                                      */
+/****************************************************************************************/
+
+
+LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16        Fs,
+                                              LVEQNB_BandDef_t  *pFilterDefinition,
+                                              PK_C32_Coefs_t    *pCoefficients)
+{
+
+    extern LVM_INT16    LVEQNB_GainTable[];
+    extern LVM_INT16    LVEQNB_TwoPiOnFsTable[];
+    extern LVM_INT16    LVEQNB_DTable[];
+    extern LVM_INT16    LVEQNB_DPCosCoef[];
+
+    /*
+     * Get the filter definition
+     */
+    LVM_INT16           Gain        = pFilterDefinition->Gain;
+    LVM_UINT16          Frequency   = pFilterDefinition->Frequency;
+    LVM_UINT16          QFactor     = pFilterDefinition->QFactor;
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_INT32           T0;
+    LVM_INT16           D;
+    LVM_INT32           A0;
+    LVM_INT32           B1;
+    LVM_INT32           B2;
+    LVM_INT32           Dt0;
+    LVM_INT32           B2_Den;
+    LVM_INT32           B2_Num;
+    LVM_INT32           CosErr;
+    LVM_INT16           coef;
+    LVM_INT32           factor;
+    LVM_INT16           t0;
+    LVM_INT16           i;
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs];        /* T0 = 2 * Pi * Fc / Fs */
+    if (Gain >= 0)
+    {
+        D = LVEQNB_DTable[15];                         /* D = 1            if GaindB >= 0 */
+    }
+    else
+    {
+        D = LVEQNB_DTable[Gain+15];                    /* D = 1 / (1 + G)  if GaindB <  0 */
+    }
+
+    /*
+     * Calculate the B2 coefficient
+     */
+    Dt0 = D * (T0 >> 10);
+    B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2);
+    B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18);
+    B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+    /*
+     * Calculate the cosine error by a polynomial expansion using the equation:
+     *
+     *  CosErr += coef(n) * t0^n                For n = 0 to 4
+     */
+    T0 = (T0 >> 6) * 0x7f53;                    /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
+    t0 = (LVM_INT16)(T0 >> 16);
+    factor = 0x7fff;                            /* Initialise to 1.0 for the a0 coefficient */
+    CosErr = 0;                                 /* Initialise the error to zero */
+    for (i=1; i<5; i++)
+    {
+        coef = LVEQNB_DPCosCoef[i];             /* Get the nth coefficient */
+        CosErr += (factor * coef) >> 5;         /* The nth partial sum */
+        factor = (factor * t0) >> 15;           /* Calculate t0^n */
+    }
+    CosErr = CosErr << (LVEQNB_DPCosCoef[0]);   /* Correct the scaling */
+
+    /*
+     * Calculate the B1 and A0 coefficients
+     */
+    B1 = (0x40000000 - B2);                     /* B1 = (0.5 - b2/2) */
+    A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6;    /* Temporary storage for (0.5 - b2/2) * coserr(t0) */
+    B1 -= A0;                                   /* B1 = (0.5 - b2/2) * (1 - coserr(t0))  */
+    A0 = (0x40000000 + B2) >> 1;                /* A0 = (0.5 + b2) */
+
+    /*
+     * Write coeff into the data structure
+     */
+    pCoefficients->A0 = A0;
+    pCoefficients->B1 = B1;
+    pCoefficients->B2 = B2;
+    pCoefficients->G  = LVEQNB_GainTable[Gain+15];
+
+    return(LVEQNB_SUCCESS);
+
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                  LVEQNB_SinglePrecCoefs                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*    Calculate single precision coefficients    for a peaking filter                   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  Fs                           Sampling frequency index                               */
+/*  pFilterDefinition          Pointer to the filter definition                         */
+/*  pCoefficients            Pointer to the coefficients                                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS            Always succeeds                                           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The equations used are as follows:                                               */
+/*                                                                                      */
+/*      G  = 10^(GaindB/20) - 1                                                         */
+/*      t0 = 2 * Pi * Fc / Fs                                                           */
+/*      D  = 1                  if GaindB >= 0                                          */
+/*      D  = 1 / (1 + G)        if GaindB <  0                                          */
+/*                                                                                      */
+/*      b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0)                                       */
+/*      b1 = (0.5 - b2) * cos(t0)                                                       */
+/*      a0 = (0.5 + b2) / 2                                                             */
+/*                                                                                      */
+/*  Where:                                                                              */
+/*      GaindB      is the gain in dBs, range -15dB to +15dB                            */
+/*      Fc          is the centre frequency, DC to Nyquist                              */
+/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
+/*      Q           is the Q factor, 0.25 to 12                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+
+LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
+                                              LVEQNB_BandDef_t  *pFilterDefinition,
+                                              PK_C16_Coefs_t    *pCoefficients)
+{
+
+    extern LVM_INT16    LVEQNB_GainTable[];
+    extern LVM_INT16    LVEQNB_TwoPiOnFsTable[];
+    extern LVM_INT16    LVEQNB_DTable[];
+    extern LVM_INT16    LVEQNB_CosCoef[];
+
+
+    /*
+     * Get the filter definition
+     */
+    LVM_INT16           Gain        = pFilterDefinition->Gain;
+    LVM_UINT16          Frequency   = pFilterDefinition->Frequency;
+    LVM_UINT16          QFactor     = pFilterDefinition->QFactor;
+
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_INT32           T0;
+    LVM_INT16           D;
+    LVM_INT32           A0;
+    LVM_INT32           B1;
+    LVM_INT32           B2;
+    LVM_INT32           Dt0;
+    LVM_INT32           B2_Den;
+    LVM_INT32           B2_Num;
+    LVM_INT32           COS_T0;
+    LVM_INT16           coef;
+    LVM_INT32           factor;
+    LVM_INT16           t0;
+    LVM_INT16           i;
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs];        /* T0 = 2 * Pi * Fc / Fs */
+    if (Gain >= 0)
+    {
+        D = LVEQNB_DTable[15];                         /* D = 1            if GaindB >= 0 */
+    }
+    else
+    {
+        D = LVEQNB_DTable[Gain+15];                    /* D = 1 / (1 + G)  if GaindB <  0 */
+    }
+
+    /*
+     * Calculate the B2 coefficient
+     */
+    Dt0 = D * (T0 >> 10);
+    B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2);
+    B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18);
+    B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+    /*
+     * Calculate the cosine by a polynomial expansion using the equation:
+     *
+     *  Cos += coef(n) * t0^n                   For n = 0 to 6
+     */
+    T0 = (T0 >> 10) * 20859;                    /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
+    t0 = (LVM_INT16)(T0 >> 16);
+    factor = 0x7fff;                            /* Initialise to 1.0 for the a0 coefficient */
+    COS_T0 = 0;                                 /* Initialise the error to zero */
+    for (i=1; i<7; i++)
+    {
+        coef = LVEQNB_CosCoef[i];               /* Get the nth coefficient */
+        COS_T0 += (factor * coef) >> 5;         /* The nth partial sum */
+        factor = (factor * t0) >> 15;           /* Calculate t0^n */
+    }
+    COS_T0 = COS_T0 << (LVEQNB_CosCoef[0]+6);          /* Correct the scaling */
+
+
+    B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16);    /* B1 = (0.5 - b2/2) * cos(t0) */
+    A0 = (0x40000000 + B2) >> 1;                        /* A0 = (0.5 + b2/2) */
+
+    /*
+     * Write coeff into the data structure
+     */
+    pCoefficients->A0 = (LVM_INT16)(A0>>16);
+    pCoefficients->B1 = (LVM_INT16)(B1>>15);
+    pCoefficients->B2 = (LVM_INT16)(B2>>16);
+    pCoefficients->G  = LVEQNB_GainTable[Gain+15];
+
+
+    return(LVEQNB_SUCCESS);
+
+}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
new file mode 100755
index 0000000..87d7145
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 __LVEQNB_COEFFS_H__
+#define __LVEQNB_COEFFS_H__
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* Gain table for (10^(Gain/20) - 1)                                                */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVEQNB_GAINSHIFT                                   11         /* As a power of 2 */
+#define LVEQNB_Gain_Neg15_dB                            -1684         /* Floating point value -0.822172 */
+#define LVEQNB_Gain_Neg14_dB                            -1639         /* Floating point value -0.800474 */
+#define LVEQNB_Gain_Neg13_dB                            -1590         /* Floating point value -0.776128 */
+#define LVEQNB_Gain_Neg12_dB                            -1534         /* Floating point value -0.748811 */
+#define LVEQNB_Gain_Neg11_dB                            -1471         /* Floating point value -0.718162 */
+#define LVEQNB_Gain_Neg10_dB                            -1400         /* Floating point value -0.683772 */
+#define LVEQNB_Gain_Neg9_dB                             -1321         /* Floating point value -0.645187 */
+#define LVEQNB_Gain_Neg8_dB                             -1233         /* Floating point value -0.601893 */
+#define LVEQNB_Gain_Neg7_dB                             -1133         /* Floating point value -0.553316 */
+#define LVEQNB_Gain_Neg6_dB                             -1022         /* Floating point value -0.498813 */
+#define LVEQNB_Gain_Neg5_dB                              -896         /* Floating point value -0.437659 */
+#define LVEQNB_Gain_Neg4_dB                              -756         /* Floating point value -0.369043 */
+#define LVEQNB_Gain_Neg3_dB                              -598         /* Floating point value -0.292054 */
+#define LVEQNB_Gain_Neg2_dB                              -421         /* Floating point value -0.205672 */
+#define LVEQNB_Gain_Neg1_dB                              -223         /* Floating point value -0.108749 */
+#define LVEQNB_Gain_0_dB                                    0         /* Floating point value 0.000000 */
+#define LVEQNB_Gain_1_dB                                  250         /* Floating point value 0.122018 */
+#define LVEQNB_Gain_2_dB                                  530         /* Floating point value 0.258925 */
+#define LVEQNB_Gain_3_dB                                  845         /* Floating point value 0.412538 */
+#define LVEQNB_Gain_4_dB                                 1198         /* Floating point value 0.584893 */
+#define LVEQNB_Gain_5_dB                                 1594         /* Floating point value 0.778279 */
+#define LVEQNB_Gain_6_dB                                 2038         /* Floating point value 0.995262 */
+#define LVEQNB_Gain_7_dB                                 2537         /* Floating point value 1.238721 */
+#define LVEQNB_Gain_8_dB                                 3096         /* Floating point value 1.511886 */
+#define LVEQNB_Gain_9_dB                                 3724         /* Floating point value 1.818383 */
+#define LVEQNB_Gain_10_dB                                4428         /* Floating point value 2.162278 */
+#define LVEQNB_Gain_11_dB                                5219         /* Floating point value 2.548134 */
+#define LVEQNB_Gain_12_dB                                6105         /* Floating point value 2.981072 */
+#define LVEQNB_Gain_13_dB                                7100         /* Floating point value 3.466836 */
+#define LVEQNB_Gain_14_dB                                8216         /* Floating point value 4.011872 */
+#define LVEQNB_Gain_15_dB                                9469         /* Floating point value 4.623413 */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* Frequency table for 2*Pi/Fs                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVEQNB_FREQSHIFT                                   25         /* As a power of 2 */
+#define LVEQNB_2PiOn_8000                               26354         /* Floating point value 0.000785 */
+#define LVEQNB_2PiOn_11025                              19123         /* Floating point value 0.000570 */
+#define LVEQNB_2PiOn_12000                              17569         /* Floating point value 0.000524 */
+#define LVEQNB_2PiOn_16000                              13177         /* Floating point value 0.000393 */
+#define LVEQNB_2PiOn_22050                               9561         /* Floating point value 0.000285 */
+#define LVEQNB_2PiOn_24000                               8785         /* Floating point value 0.000262 */
+#define LVEQNB_2PiOn_32000                               6588         /* Floating point value 0.000196 */
+#define LVEQNB_2PiOn_44100                               4781         /* Floating point value 0.000142 */
+#define LVEQNB_2PiOn_48000                               4392         /* Floating point value 0.000131 */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* 50D table for 50 / ( 1 + Gain )                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVEQNB_100DSHIFT                                    5         /* As a power of 2 */
+#define LVEQNB_100D_Neg15_dB                            17995         /* Floating point value 5.623413 */
+#define LVEQNB_100D_Neg14_dB                            16038         /* Floating point value 5.011872 */
+#define LVEQNB_100D_Neg13_dB                            14294         /* Floating point value 4.466836 */
+#define LVEQNB_100D_Neg12_dB                            12739         /* Floating point value 3.981072 */
+#define LVEQNB_100D_Neg11_dB                            11354         /* Floating point value 3.548134 */
+#define LVEQNB_100D_Neg10_dB                            10119         /* Floating point value 3.162278 */
+#define LVEQNB_100D_Neg9_dB                              9019         /* Floating point value 2.818383 */
+#define LVEQNB_100D_Neg8_dB                              8038         /* Floating point value 2.511886 */
+#define LVEQNB_100D_Neg7_dB                              7164         /* Floating point value 2.238721 */
+#define LVEQNB_100D_Neg6_dB                              6385         /* Floating point value 1.995262 */
+#define LVEQNB_100D_Neg5_dB                              5690         /* Floating point value 1.778279 */
+#define LVEQNB_100D_Neg4_dB                              5072         /* Floating point value 1.584893 */
+#define LVEQNB_100D_Neg3_dB                              4520         /* Floating point value 1.412538 */
+#define LVEQNB_100D_Neg2_dB                              4029         /* Floating point value 1.258925 */
+#define LVEQNB_100D_Neg1_dB                              3590         /* Floating point value 1.122018 */
+#define LVEQNB_100D_0_dB                                 3200         /* Floating point value 1.000000 */
+
+
+#endif
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
new file mode 100755
index 0000000..dac2449
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1316 $
+     $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Defines                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define     LOW_FREQ            298             /* 32768/110 for low test frequency */
+#define     HIGH_FREQ           386             /* 32768/85 for high test frequency */
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVEQNB_GetParameters                                       */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the N-Band equaliser parameters. The current parameter set is returned via  */
+/*  the parameter pointer.                                                              */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance handle                                            */
+/*  pParams                  Pointer to an empty parameter structure                    */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeds                                                    */
+/*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t     hInstance,
+                                            LVEQNB_Params_t     *pParams)
+{
+
+    LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
+
+   /*
+     * Check for error conditions
+     */
+    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    *pParams = pInstance->Params;
+
+    return(LVEQNB_SUCCESS);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                 LVEQNB_GetCapabilities                                 */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Get the N-Band equaliser capabilities. The current capabilities are returned    */
+/*  via the pointer.                                                                */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance                Instance handle                                        */
+/*  pCapabilities            Pointer to an empty capability structure               */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVEQNB_Success           Succeeds                                               */
+/*  LVEQNB_NULLADDRESS       hInstance or pCapabilities is NULL                     */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  This function may be interrupted by the LVEQNB_Process function             */
+/*                                                                                  */
+/************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t           hInstance,
+                                              LVEQNB_Capabilities_t     *pCapabilities)
+{
+
+    LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
+
+    if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    *pCapabilities = pInstance->Capabilities;
+
+    return(LVEQNB_SUCCESS);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVEQNB_SetFilters                                           */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the filter type based on the definition.                                   */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  void                Nothing                                                     */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1. To select the biquad type the follow rules are applied:                      */
+/*          Double precision    if (fc <= fs/110)                                   */
+/*          Double precision    if (fs/110 < fc < fs/85) & (Q>3)                    */
+/*          Single precision    otherwise                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVEQNB_SetFilters(LVEQNB_Instance_t     *pInstance,
+                          LVEQNB_Params_t       *pParams)
+{
+
+    extern const LVM_UINT16   LVEQNB_SampleRateTab[];           /* Sample rate table */
+    LVM_UINT16          i;                                      /* Filter band index */
+    LVM_UINT32          fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate];  /* Sample rate */
+    LVM_UINT32          fc;                                     /* Filter centre frequency */
+    LVM_INT16           QFactor;                                /* Filter Q factor */
+
+
+    pInstance->NBands = pParams->NBands;
+
+    for (i=0; i<pParams->NBands; i++)
+    {
+        /*
+         * Get the filter settings
+         */
+        fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency;     /* Get the band centre frequency */
+        QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor;   /* Get the band Q factor */
+
+
+        /*
+         * For each filter set the type of biquad required
+         */
+        pInstance->pBiquadType[i] = LVEQNB_SinglePrecision;         /* Default to single precision */
+        if ((fc << 15) <= (LOW_FREQ * fs))
+        {
+            /*
+             * fc <= fs/110
+             */
+            pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
+        }
+        else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300))
+        {
+            /*
+             * (fs/110 < fc < fs/85) & (Q>3)
+             */
+            pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
+        }
+
+
+        /*
+         * Check for out of range frequencies
+         */
+        if (fc > (fs >> 1))
+        {
+            pInstance->pBiquadType[i] = LVEQNB_OutOfRange;
+        }
+
+
+        /*
+         * Copy the filter definition to persistant memory
+         */
+        pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i];
+
+    }
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVEQNB_SetCoefficients                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the filter coefficients. This uses the type to select single or double     */
+/*  precision coefficients.                                                         */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*  pParams             Initialisation parameters                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVEQNB_SetCoefficients(LVEQNB_Instance_t     *pInstance)
+{
+
+    LVM_UINT16              i;                          /* Filter band index */
+    LVEQNB_BiquadType_en    BiquadType;                 /* Filter biquad type */
+
+
+    /*
+     * Set the coefficients for each band by the init function
+     */
+    for (i=0; i<pInstance->Params.NBands; i++)
+    {
+
+        /*
+         * Check band type for correct initialisation method and recalculate the coefficients
+         */
+        BiquadType = pInstance->pBiquadType[i];
+        switch  (BiquadType)
+        {
+            case    LVEQNB_DoublePrecision:
+            {
+                PK_C32_Coefs_t      Coefficients;
+
+                /*
+                 * Calculate the double precision coefficients
+                 */
+                LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
+                                       &pInstance->pBandDefinitions[i],
+                                       &Coefficients);
+
+                /*
+                 * Set the coefficients
+                 */
+                PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
+                                                   &pInstance->pEQNB_Taps[i],
+                                                   &Coefficients);
+                break;
+            }
+
+            case    LVEQNB_SinglePrecision:
+            {
+                PK_C16_Coefs_t      Coefficients;
+
+                /*
+                 * Calculate the single precision coefficients
+                 */
+                LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
+                                       &pInstance->pBandDefinitions[i],
+                                       &Coefficients);
+
+                /*
+                 * Set the coefficients
+                 */
+                PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
+                                                   &pInstance->pEQNB_Taps[i],
+                                                   &Coefficients);
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVEQNB_ClearFilterHistory                                   */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Clears the filter data history                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*                                                                                  */
+/************************************************************************************/
+
+void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
+{
+    LVM_INT16       *pTapAddress;
+    LVM_INT16       NumTaps;
+
+
+    pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps;
+    NumTaps     = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16));
+
+    if (NumTaps != 0)
+    {
+        LoadConst_16(0,                                 /* Clear the history, value 0 */
+                     pTapAddress,                       /* Destination */
+                     NumTaps);                          /* Number of words */
+    }
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Control                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the LifeVibes module parameters.                                    */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pParams                 Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_Success          Always succeeds                                             */
+/*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
+/*  LVEQNB_NULLADDRESS      NULL address for the equaliser filter definitions and the   */
+/*                          number of bands is non-zero                                 */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t        hInstance,
+                                      LVEQNB_Params_t        *pParams)
+{
+
+    LVEQNB_Instance_t    *pInstance = (LVEQNB_Instance_t  *)hInstance;
+    LVM_INT16            bChange    = LVM_FALSE;
+    LVM_INT16            i = 0;
+    LVEQNB_Mode_en       OperatingModeSave ;
+
+    /*
+     * Check for error conditions
+     */
+    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    OperatingModeSave = pInstance->Params.OperatingMode;
+
+    /* Set the alpha factor of the mixer */
+    if (pParams->SampleRate != pInstance->Params.SampleRate)
+    {
+        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+        LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+    }
+
+
+    if( (pInstance->Params.NBands            !=  pParams->NBands          ) ||
+        (pInstance->Params.OperatingMode     !=  pParams->OperatingMode   ) ||
+        (pInstance->Params.pBandDefinition   !=  pParams->pBandDefinition ) ||
+        (pInstance->Params.SampleRate        !=  pParams->SampleRate      ) ||
+        (pInstance->Params.SourceFormat      !=  pParams->SourceFormat    ))
+    {
+
+        bChange = LVM_TRUE;
+    }
+    else
+    {
+        for(i = 0; i < pParams->NBands; i++)
+        {
+
+            if((pInstance->pBandDefinitions[i].Frequency  != pParams->pBandDefinition[i].Frequency )||
+                (pInstance->pBandDefinitions[i].Gain       != pParams->pBandDefinition[i].Gain      )||
+                (pInstance->pBandDefinitions[i].QFactor    != pParams->pBandDefinition[i].QFactor   ))
+            {
+
+                bChange = LVM_TRUE;
+            }
+        }
+    }
+
+
+    if(bChange){
+
+        /*
+         * If the sample rate has changed clear the history
+         */
+        if (pInstance->Params.SampleRate != pParams->SampleRate)
+        {
+            LVEQNB_ClearFilterHistory(pInstance);           /* Clear the history */
+        }
+
+        /*
+         * Update the instance parameters
+         */
+        pInstance->Params = *pParams;
+
+
+        /*
+         * Reset the filters except if the algo is switched off
+         */
+        if(pParams->OperatingMode != LVEQNB_BYPASS){
+            /*
+             * Reset the filters as all parameters could have changed
+             */
+            LVEQNB_SetFilters(pInstance,                        /* Instance pointer */
+                              pParams);                         /* New parameters */
+
+            /*
+             * Update the filters
+             */
+            LVEQNB_SetCoefficients(pInstance);                  /* Instance pointer */
+        }
+
+        if(pParams->OperatingMode != OperatingModeSave)
+        {
+            if(pParams->OperatingMode == LVEQNB_ON)
+            {
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16);
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0);
+
+                pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
+                pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
+            }
+            else
+            {
+                /* Stay on the ON operating mode until the transition is done */
+                pInstance->Params.OperatingMode = LVEQNB_ON;
+
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0);
+                LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16);
+                pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
+                pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
+            }
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+
+            pInstance->bInOperatingModeTransition = LVM_TRUE;
+        }
+
+    }
+    return(LVEQNB_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_BypassMixerCallBack                                  */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  CallBack function of the mixer                                                      */
+/*  transition                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance,
+                                      void *pGeneralPurpose,
+                                      LVM_INT16 CallbackParam)
+{
+    LVEQNB_Instance_t      *pInstance =(LVEQNB_Instance_t  *)hInstance;
+    LVM_Callback            CallBack  = pInstance->Capabilities.CallBack;
+
+    (void) pGeneralPurpose;
+
+     /*
+      * Send an ALGOFF event if the ON->OFF switch transition is finished
+      */
+    if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) &&
+       (CallbackParam == 0)){
+        pInstance->Params.OperatingMode = LVEQNB_BYPASS;
+        if (CallBack != LVM_NULL){
+            CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
+        }
+    }
+
+    /*
+     *  Exit transition state
+     */
+    pInstance->bInOperatingModeTransition = LVM_FALSE;
+
+    return 1;
+}
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
new file mode 100755
index 0000000..a29fe05
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1005 $
+     $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Memory                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pCapabilities           Pointer to the instance capabilities                        */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeded                                                   */
+/*  LVEQNB_NULLADDRESS      When any of pMemoryTable and pCapabilities is NULL address  */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVEQNB_Process function                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t            hInstance,
+                                     LVEQNB_MemTab_t            *pMemoryTable,
+                                     LVEQNB_Capabilities_t      *pCapabilities)
+{
+
+    INST_ALLOC          AllocMem;
+    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t *)hInstance;
+
+
+    if((pMemoryTable == LVM_NULL)|| (pCapabilities == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+        /*
+         * Instance memory
+         */
+        InstAlloc_Init(&AllocMem,
+                       LVM_NULL);
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            sizeof(LVEQNB_Instance_t));
+        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Size         = InstAlloc_GetTotal(&AllocMem);
+        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Alignment    = LVEQNB_INSTANCE_ALIGN;
+        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Type         = LVEQNB_PERSISTENT;
+        pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+
+        /*
+         * Persistant data memory
+         */
+        InstAlloc_Init(&AllocMem,
+                       LVM_NULL);
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            sizeof(Biquad_2I_Order2_Taps_t));
+        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
+                            sizeof(Biquad_2I_Order2_Taps_t));
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t))); /* Equaliser Biquad Taps */
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)));        /* Filter definitions */
+        InstAlloc_AddMember(&AllocMem,
+                            (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)));    /* Biquad types */
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&AllocMem);
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment    = LVEQNB_DATA_ALIGN;
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type         = LVEQNB_PERSISTENT_DATA;
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistant coefficient memory
+         */
+        InstAlloc_Init(&AllocMem,
+                       LVM_NULL);
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            sizeof(Biquad_Instance_t));
+        InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
+                            sizeof(Biquad_Instance_t));
+        InstAlloc_AddMember(&AllocMem,
+                            pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&AllocMem);
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment    = LVEQNB_COEF_ALIGN;
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type         = LVEQNB_PERSISTENT_COEF;
+        pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Scratch memory
+         */
+        InstAlloc_Init(&AllocMem,
+                       LVM_NULL);
+        InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
+                            LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
+        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size              = InstAlloc_GetTotal(&AllocMem);
+        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment         = LVEQNB_SCRATCH_ALIGN;
+        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type              = LVEQNB_SCRATCH;
+        pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress      = LVM_NULL;
+    }
+    else
+    {
+        /* Read back memory allocation table */
+        *pMemoryTable = pInstance->MemoryTable;
+    }
+
+    return(LVEQNB_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Init                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Create and initialisation function for the N-Band equaliser module                  */
+/*                                                                                      */
+/*  This function can be used to create an algorithm instance by calling with           */
+/*  hInstance set to NULL. In this case the algorithm returns the new instance          */
+/*  handle.                                                                             */
+/*                                                                                      */
+/*  This function can be used to force a full re-initialisation of the algorithm        */
+/*  by calling with hInstance = Instance Handle. In this case the memory table          */
+/*  should be correct for the instance, this can be ensured by calling the function     */
+/*  DBE_Memory before calling this function.                                            */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pMemoryTable            Pointer to the memory definition table                      */
+/*  pCapabilities           Pointer to the instance capabilities                        */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Initialisation succeeded                                    */
+/*  LVEQNB_NULLADDRESS        When pCapabilities or pMemoryTableis or phInstance are NULL */
+/*  LVEQNB_NULLADDRESS        One or more of the memory regions has a NULL base address   */
+/*                          pointer for a memory region with a non-zero size.           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  The instance handle is the pointer to the base address of the first memory      */
+/*      region.                                                                         */
+/*  2.  This function must not be interrupted by the LVEQNB_Process function            */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t          *phInstance,
+                                   LVEQNB_MemTab_t          *pMemoryTable,
+                                   LVEQNB_Capabilities_t    *pCapabilities)
+{
+
+    LVEQNB_Instance_t   *pInstance;
+    LVM_UINT32          MemSize;
+    INST_ALLOC          AllocMem;
+    LVM_INT32           i;
+
+    /*
+     * Check for NULL pointers
+     */
+    if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pCapabilities == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    /*
+     * Check the memory table for NULL pointers
+     */
+    for (i = 0; i < LVEQNB_NR_MEMORY_REGIONS; i++)
+    {
+        if (pMemoryTable->Region[i].Size!=0)
+        {
+            if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+            {
+                return(LVEQNB_NULLADDRESS);
+            }
+        }
+    }
+
+    /*
+     * Set the instance handle if not already initialised
+     */
+
+    InstAlloc_Init(&AllocMem,  pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress);
+
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = InstAlloc_AddMember(&AllocMem, sizeof(LVEQNB_Instance_t));
+    }
+    pInstance =(LVEQNB_Instance_t  *)*phInstance;
+
+
+
+    /*
+     * Save the memory table in the instance structure
+     */
+    pInstance->Capabilities = *pCapabilities;
+
+
+    /*
+     * Save the memory table in the instance structure and
+     * set the structure pointers
+     */
+    pInstance->MemoryTable       = *pMemoryTable;
+
+    /*
+     * Allocate coefficient memory
+     */
+    InstAlloc_Init(&AllocMem,
+                   pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress);
+
+    pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem,
+                                                       pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
+
+
+
+    /*
+     * Allocate data memory
+     */
+    InstAlloc_Init(&AllocMem,
+                   pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress);
+
+    MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t));
+    pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem,
+                                                                           MemSize);
+    MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t));
+    pInstance->pBandDefinitions  = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem,
+                                                                           MemSize);
+    MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en));
+    pInstance->pBiquadType = (LVEQNB_BiquadType_en *)InstAlloc_AddMember(&AllocMem,
+                                                                         MemSize);
+
+
+    /*
+     * Internally map, structure and allign scratch memory
+     */
+    InstAlloc_Init(&AllocMem,
+                   pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress);
+
+    pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem,
+                                                                 sizeof(LVM_INT16));
+
+    /*
+     * Update the instance parameters
+     */
+    pInstance->Params.NBands          = 0;
+    pInstance->Params.OperatingMode   = LVEQNB_BYPASS;
+    pInstance->Params.pBandDefinition = LVM_NULL;
+    pInstance->Params.SampleRate      = LVEQNB_FS_8000;
+    pInstance->Params.SourceFormat    = LVEQNB_STEREO;
+
+    /*
+     * Initialise the filters
+     */
+    LVEQNB_SetFilters(pInstance,                        /* Set the filter types */
+                      &pInstance->Params);
+
+    LVEQNB_SetCoefficients(pInstance);                  /* Set the filter coefficients */
+
+    LVEQNB_ClearFilterHistory(pInstance);               /* Clear the filter history */
+
+    /*
+     * Initialise the bypass variables
+     */
+    pInstance->BypassMixer.MixerStream[0].CallbackSet        = 0;
+    pInstance->BypassMixer.MixerStream[0].CallbackParam      = 0;
+    pInstance->BypassMixer.MixerStream[0].pCallbackHandle    = (void*)pInstance;
+    pInstance->BypassMixer.MixerStream[0].pCallBack          = LVEQNB_BypassMixerCallBack;
+    LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0);
+    LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2);
+
+    pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
+    pInstance->BypassMixer.MixerStream[1].CallbackParam      = 0;
+    pInstance->BypassMixer.MixerStream[1].pCallbackHandle    = LVM_NULL;
+    pInstance->BypassMixer.MixerStream[1].pCallBack          = LVM_NULL;
+    LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16);
+    LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2);
+
+    pInstance->bInOperatingModeTransition      = LVM_FALSE;
+
+    return(LVEQNB_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
new file mode 100755
index 0000000..0ae84af
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1005 $
+     $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __LVEQNB_PRIVATE_H__
+#define __LVEQNB_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB.h"                                     /* Calling or Application layer definitions */
+#include "BIQUAD.h"
+#include "LVC_Mixer.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Defines                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* General */
+#define LVEQNB_INVALID              0xFFFF              /* Invalid init parameter */
+
+/* Memory */
+#define LVEQNB_INSTANCE_ALIGN       4                   /* 32-bit alignment for instance structures */
+#define LVEQNB_DATA_ALIGN           4                   /* 32-bit alignment for structures */
+#define LVEQNB_COEF_ALIGN           4                   /* 32-bit alignment for long words */
+#define LVEQNB_SCRATCHBUFFERS       4                   /* Number of buffers required for inplace processing */
+#define LVEQNB_SCRATCH_ALIGN        4                   /* 32-bit alignment for long data */
+
+#define LVEQNB_BYPASS_MIXER_TC      100                 /* Bypass Mixer TC */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Types                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Filter biquad types */
+typedef enum
+{
+    LVEQNB_SinglePrecision = 0,
+    LVEQNB_DoublePrecision = 1,
+    LVEQNB_OutOfRange      = 2,
+    LVEQNB_BIQUADTYPE_MAX  = LVM_MAXINT_32
+} LVEQNB_BiquadType_en;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Structures                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+
+
+/* Instance structure */
+typedef struct
+{
+    /* Public parameters */
+    LVEQNB_MemTab_t                 MemoryTable;        /* Instance memory allocation table */
+    LVEQNB_Params_t                 Params;             /* Instance parameters */
+    LVEQNB_Capabilities_t           Capabilities;       /* Instance capabilities */
+
+    /* Aligned memory pointers */
+    LVM_INT16                      *pFastTemporary;        /* Fast temporary data base address */
+
+    /* Process variables */
+    Biquad_2I_Order2_Taps_t         *pEQNB_Taps;        /* Equaliser Taps */
+    Biquad_Instance_t               *pEQNB_FilterState; /* State for each filter band */
+
+    /* Filter definitions and call back */
+    LVM_UINT16                      NBands;             /* Number of bands */
+    LVEQNB_BandDef_t                *pBandDefinitions;  /* Filter band definitions */
+    LVEQNB_BiquadType_en            *pBiquadType;       /* Filter biquad types */
+
+    /* Bypass variable */
+    LVMixer3_2St_st           BypassMixer;              /* Bypass mixer used in transitions */
+    LVM_INT16               bInOperatingModeTransition; /* Operating mode transition flag */
+
+} LVEQNB_Instance_t;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* Function prototypes                                                                  */
+/*                                                                                      */
+/****************************************************************************************/
+
+void    LVEQNB_SetFilters(LVEQNB_Instance_t   *pInstance,
+                          LVEQNB_Params_t     *pParams);
+
+void    LVEQNB_SetCoefficients(LVEQNB_Instance_t    *pInstance);
+
+void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance);
+
+LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16        Fs,
+                                              LVEQNB_BandDef_t  *pFilterDefinition,
+                                              PK_C16_Coefs_t    *pCoefficients);
+
+LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16        Fs,
+                                              LVEQNB_BandDef_t  *pFilterDefinition,
+                                              PK_C32_Coefs_t    *pCoefficients);
+
+LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance, void *pGeneralPurpose, LVM_INT16 CallbackParam);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVEQNB_PRIVATE_H__ */
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
new file mode 100755
index 0000000..e29e881
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/**********************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1005 $
+     $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Defines                                                                             */
+/*                                                                                      */
+/****************************************************************************************/
+
+#define SHIFT       13
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Process                                              */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the N-Band Equaliser module.                                   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVEQNB_SUCCESS          Succeeded                                                   */
+/*  LVEQNB_NULLADDRESS      When hInstance, pInData or pOutData are NULL                */
+/*  LVEQNB_ALIGNMENTERROR   When pInData or pOutData are not 32-bit aligned             */
+/*  LVEQNB_TOOMANYSAMPLES   NumSamples was larger than the maximum block size           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t       hInstance,
+                                      const LVM_INT16       *pInData,
+                                      LVM_INT16             *pOutData,
+                                      LVM_UINT16            NumSamples)
+{
+
+    LVM_UINT16          i;
+    Biquad_Instance_t   *pBiquad;
+    LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t  *)hInstance;
+    LVM_INT32           *pScratch;
+
+
+     /* Check for NULL pointers */
+    if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+    {
+        return LVEQNB_NULLADDRESS;
+    }
+
+    /* Check if the input and output data buffers are 32-bit aligned */
+    if ((((LVM_INT32)pInData % 4) != 0) || (((LVM_INT32)pOutData % 4) != 0))
+    {
+        return LVEQNB_ALIGNMENTERROR;
+    }
+
+    pScratch  = (LVM_INT32 *)pInstance->pFastTemporary;
+
+    /*
+    * Check the number of samples is not too large
+    */
+    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+    {
+        return(LVEQNB_TOOMANYSAMPLES);
+    }
+
+    if (pInstance->Params.OperatingMode == LVEQNB_ON)
+    {
+        /*
+         * Convert from 16-bit to 32-bit
+         */
+        Int16LShiftToInt32_16x32((LVM_INT16 *)pInData,      /* Source */
+                                 pScratch,                  /* Destination */
+                                 (LVM_INT16)(2*NumSamples), /* Left and Right */
+                                 SHIFT);                    /* Scaling shift */
+
+        /*
+         * For each section execte the filter unless the gain is 0dB
+         */
+        if (pInstance->NBands != 0)
+        {
+            for (i=0; i<pInstance->NBands; i++)
+            {
+                /*
+                 * Check if band is non-zero dB gain
+                 */
+                if (pInstance->pBandDefinitions[i].Gain != 0)
+                {
+                    /*
+                     * Get the address of the biquad instance
+                     */
+                    pBiquad = &pInstance->pEQNB_FilterState[i];
+
+
+                    /*
+                     * Select single or double precision as required
+                     */
+                    switch (pInstance->pBiquadType[i])
+                    {
+                        case LVEQNB_SinglePrecision:
+                        {
+                            PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
+                                                          (LVM_INT32 *)pScratch,
+                                                          (LVM_INT32 *)pScratch,
+                                                          (LVM_INT16)NumSamples);
+                            break;
+                        }
+
+                        case LVEQNB_DoublePrecision:
+                        {
+                            PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad,
+                                                          (LVM_INT32 *)pScratch,
+                                                          (LVM_INT32 *)pScratch,
+                                                          (LVM_INT16)NumSamples);
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                }
+            }
+        }
+
+
+        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+                /*
+                 * Convert from 32-bit to 16- bit and saturate
+                 */
+                Int32RShiftToInt16_Sat_32x16(pScratch,                      /* Source */
+                                             (LVM_INT16 *)pScratch,         /* Destination */
+                                             (LVM_INT16)(2*NumSamples),     /* Left and Right */
+                                             SHIFT);                        /* Scaling shift */
+
+                LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
+                                                (LVM_INT16 *)pScratch,
+                                                (LVM_INT16 *)pInData,
+                                                (LVM_INT16 *)pScratch,
+                                                (LVM_INT16)(2*NumSamples));
+
+                Copy_16((LVM_INT16*)pScratch,                           /* Source */
+                        pOutData,                                       /* Destination */
+                        (LVM_INT16)(2*NumSamples));                     /* Left and Right samples */
+        }
+        else{
+
+            /*
+             * Convert from 32-bit to 16- bit and saturate
+             */
+            Int32RShiftToInt16_Sat_32x16(pScratch,              /* Source */
+                                         pOutData,              /* Destination */
+                                         (LVM_INT16 )(2*NumSamples), /* Left and Right */
+                                         SHIFT);                /* Scaling shift */
+        }
+    }
+    else
+    {
+        /*
+         * Mode is OFF so copy the data if necessary
+         */
+        if (pInData != pOutData)
+        {
+            Copy_16(pInData,                                    /* Source */
+                    pOutData,                                   /* Destination */
+                    (LVM_INT16)(2*NumSamples));                 /* Left and Right samples */
+        }
+    }
+
+
+
+    return(LVEQNB_SUCCESS);
+
+}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
new file mode 100755
index 0000000..33c07da
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1005 $
+     $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Coeffs.h"
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Sample rate table                                                             */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT16    LVEQNB_SampleRateTab[] = {8000,                    /* 8kS/s  */
+                                              11025,
+                                              12000,
+                                              16000,
+                                              22050,
+                                              24000,
+                                              32000,
+                                              44100,
+                                              48000};                  /* 48kS/s */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Coefficient calculation tables                                                */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+const LVM_INT16     LVEQNB_TwoPiOnFsTable[] = {LVEQNB_2PiOn_8000,      /* 8kS/s */
+                                               LVEQNB_2PiOn_11025,
+                                               LVEQNB_2PiOn_12000,
+                                               LVEQNB_2PiOn_16000,
+                                               LVEQNB_2PiOn_22050,
+                                               LVEQNB_2PiOn_24000,
+                                               LVEQNB_2PiOn_32000,
+                                               LVEQNB_2PiOn_44100,
+                                               LVEQNB_2PiOn_48000};    /* 48kS/s */
+
+/*
+ * Gain table
+ */
+const LVM_INT16     LVEQNB_GainTable[] = {LVEQNB_Gain_Neg15_dB,        /* -15dB gain */
+                                          LVEQNB_Gain_Neg14_dB,
+                                          LVEQNB_Gain_Neg13_dB,
+                                          LVEQNB_Gain_Neg12_dB,
+                                          LVEQNB_Gain_Neg11_dB,
+                                          LVEQNB_Gain_Neg10_dB,
+                                          LVEQNB_Gain_Neg9_dB,
+                                          LVEQNB_Gain_Neg8_dB,
+                                          LVEQNB_Gain_Neg7_dB,
+                                          LVEQNB_Gain_Neg6_dB,
+                                          LVEQNB_Gain_Neg5_dB,
+                                          LVEQNB_Gain_Neg4_dB,
+                                          LVEQNB_Gain_Neg3_dB,
+                                          LVEQNB_Gain_Neg2_dB,
+                                          LVEQNB_Gain_Neg1_dB,
+                                          LVEQNB_Gain_0_dB,            /* 0dB gain */
+                                          LVEQNB_Gain_1_dB,
+                                          LVEQNB_Gain_2_dB,
+                                          LVEQNB_Gain_3_dB,
+                                          LVEQNB_Gain_4_dB,
+                                          LVEQNB_Gain_5_dB,
+                                          LVEQNB_Gain_6_dB,
+                                          LVEQNB_Gain_7_dB,
+                                          LVEQNB_Gain_8_dB,
+                                          LVEQNB_Gain_9_dB,
+                                          LVEQNB_Gain_10_dB,
+                                          LVEQNB_Gain_11_dB,
+                                          LVEQNB_Gain_12_dB,
+                                          LVEQNB_Gain_13_dB,
+                                          LVEQNB_Gain_14_dB,
+                                          LVEQNB_Gain_15_dB};          /* +15dB gain */
+
+
+/*
+ * D table for 100 / (Gain + 1)
+ */
+const LVM_INT16    LVEQNB_DTable[] = {LVEQNB_100D_Neg15_dB,            /* -15dB gain */
+                                      LVEQNB_100D_Neg14_dB,
+                                      LVEQNB_100D_Neg13_dB,
+                                      LVEQNB_100D_Neg12_dB,
+                                      LVEQNB_100D_Neg11_dB,
+                                      LVEQNB_100D_Neg10_dB,
+                                      LVEQNB_100D_Neg9_dB,
+                                      LVEQNB_100D_Neg8_dB,
+                                      LVEQNB_100D_Neg7_dB,
+                                      LVEQNB_100D_Neg6_dB,
+                                      LVEQNB_100D_Neg5_dB,
+                                      LVEQNB_100D_Neg4_dB,
+                                      LVEQNB_100D_Neg3_dB,
+                                      LVEQNB_100D_Neg2_dB,
+                                      LVEQNB_100D_Neg1_dB,
+                                      LVEQNB_100D_0_dB};               /* 0dB gain */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Filter polynomial coefficients                                                */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ *  Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+const LVM_INT16     LVEQNB_CosCoef[] = {3,                             /* Shifts */
+                                        4096,                          /* a0 */
+                                        -36,                           /* a1 */
+                                        -19725,                        /* a2 */
+                                        -2671,                         /* a3 */
+                                        23730,                         /* a4 */
+                                        -9490};                        /* a5 */
+
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ *  CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+const LVM_INT16     LVEQNB_DPCosCoef[] = {1,                           /* Shifts */
+                                          0,                           /* a0 */
+                                          -6,                          /* a1 */
+                                          16586,                       /* a2 */
+                                          -44};                        /* a3 */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Bypass mixer time constants (100ms)                                             */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVEQNB_MIX_TC_Fs8000    32580         /* Floating point value 0.994262695 */
+#define LVEQNB_MIX_TC_Fs11025   32632         /* Floating point value 0.995849609 */
+#define LVEQNB_MIX_TC_Fs12000   32643         /* Floating point value 0.996185303 */
+#define LVEQNB_MIX_TC_Fs16000   32674         /* Floating point value 0.997131348 */
+#define LVEQNB_MIX_TC_Fs22050   32700         /* Floating point value 0.997924805 */
+#define LVEQNB_MIX_TC_Fs24000   32705         /* Floating point value 0.998077393 */
+#define LVEQNB_MIX_TC_Fs32000   32721         /* Floating point value 0.998565674 */
+#define LVEQNB_MIX_TC_Fs44100   32734         /* Floating point value 0.998962402 */
+#define LVEQNB_MIX_TC_Fs48000   32737         /* Floating point value 0.999053955 */
+
+
+const LVM_INT16 LVEQNB_MixerTCTable[] = {
+    LVEQNB_MIX_TC_Fs8000,
+    LVEQNB_MIX_TC_Fs11025,
+    LVEQNB_MIX_TC_Fs12000,
+    LVEQNB_MIX_TC_Fs16000,
+    LVEQNB_MIX_TC_Fs22050,
+    LVEQNB_MIX_TC_Fs24000,
+    LVEQNB_MIX_TC_Fs32000,
+    LVEQNB_MIX_TC_Fs44100,
+    LVEQNB_MIX_TC_Fs48000};
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
new file mode 100755
index 0000000..b9903b2
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#ifndef _LVPSA_H_
+#define _LVPSA_H_
+
+
+#include "LVM_Types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  CONSTANTS DEFINITIONS                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory table*/
+#define     LVPSA_NR_MEMORY_REGIONS                  4      /* Number of memory regions                                          */
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  TYPES DEFINITIONS                                                                   */
+/*                                                                                      */
+/****************************************************************************************/
+/* Memory Types */
+typedef enum
+{
+    LVPSA_PERSISTENT      = LVM_PERSISTENT,
+    LVPSA_PERSISTENT_DATA = LVM_PERSISTENT_DATA,
+    LVPSA_PERSISTENT_COEF = LVM_PERSISTENT_COEF,
+    LVPSA_SCRATCH         = LVM_SCRATCH,
+    LVPSA_MEMORY_DUMMY = LVM_MAXINT_32                      /* Force 32 bits enum, don't use it!                                 */
+} LVPSA_MemoryTypes_en;
+
+/* Level detection speed control parameters */
+typedef enum
+{
+    LVPSA_SPEED_LOW,                                        /* Low speed level   detection                                       */
+    LVPSA_SPEED_MEDIUM,                                     /* Medium speed level   detection                                    */
+    LVPSA_SPEED_HIGH,                                       /* High speed level   detection                                      */
+    LVPSA_SPEED_DUMMY = LVM_MAXINT_32                       /* Force 32 bits enum, don't use it!                                 */
+} LVPSA_LevelDetectSpeed_en;
+
+/* Filter control parameters */
+typedef struct
+{
+    LVM_UINT16                 CenterFrequency;             /* Center frequency of the band-pass filter (in Hz)                  */
+    LVM_UINT16                 QFactor;                     /* Quality factor of the filter             (in 1/100)               */
+    LVM_INT16                  PostGain;                    /* Postgain to apply after the filtering    (in dB Q16.0)            */
+
+} LVPSA_FilterParam_t;
+
+/* LVPSA initialization parameters */
+typedef struct
+{
+    LVM_UINT16                 SpectralDataBufferDuration;  /* Spectral data buffer duration in time (ms in Q16.0)               */
+    LVM_UINT16                 MaxInputBlockSize;           /* Maximum expected input block size (in samples)                    */
+    LVM_UINT16                 nBands;                      /* Number of bands of the SA                                         */
+    LVPSA_FilterParam_t       *pFiltersParams;              /* Points to nBands filter param structures for filters settings     */
+
+} LVPSA_InitParams_t, *pLVPSA_InitParams_t;
+
+/* LVPSA control parameters */
+typedef struct
+{
+    LVM_Fs_en                  Fs;                          /* Input sampling rate                                               */
+    LVPSA_LevelDetectSpeed_en  LevelDetectionSpeed;         /* Level detection speed                                             */
+
+} LVPSA_ControlParams_t, *pLVPSA_ControlParams_t;
+
+/* Memory region definition */
+typedef struct
+{
+    LVM_UINT32                 Size;                        /* Region size in bytes                                              */
+    LVPSA_MemoryTypes_en       Type;                        /* Region type                                                       */
+    void                       *pBaseAddress;               /* Pointer to the region base address                                */
+} LVPSA_MemoryRegion_t;
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+    LVPSA_MemoryRegion_t       Region[LVPSA_NR_MEMORY_REGIONS];/* One definition for each region                                 */
+} LVPSA_MemTab_t;
+
+/* Audio time type */
+typedef LVM_INT32 LVPSA_Time;
+
+/* Module instance Handle */
+typedef void *pLVPSA_Handle_t;
+
+/* LVPSA return codes */
+typedef enum
+{
+    LVPSA_OK,                                               /* The function ran without any problem                              */
+    LVPSA_ERROR_INVALIDPARAM,                               /* A parameter is incorrect                                          */
+    LVPSA_ERROR_WRONGTIME,                                  /* An incorrect AudioTime is used                                    */
+    LVPSA_ERROR_NULLADDRESS,                                /* A pointer has a NULL value                                        */
+    LVPSA_RETURN_DUMMY = LVM_MAXINT_32                      /* Force 32 bits enum, don't use it!                                 */
+} LVPSA_RETURN;
+
+
+
+/*********************************************************************************************************************************
+   FUNCTIONS PROTOTYPE
+**********************************************************************************************************************************/
+/*********************************************************************************************************************************/
+/*                                                                                                                               */
+/* FUNCTION:            LVPSA_Memory                                                                                         */
+/*                                                                                                                               */
+/* DESCRIPTION:                                                                                                                  */
+/*  This function is used for memory allocation and free. It can be called in                                                    */
+/*  two ways:                                                                                                                    */
+/*                                                                                                                               */
+/*      hInstance = NULL                Returns the memory requirements                                                          */
+/*      hInstance = Instance handle     Returns the memory requirements and                                                      */
+/*                                      allocated base addresses for the instance                                                */
+/*                                                                                                                               */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory                                               */
+/*  base address pointers are NULL on return.                                                                                    */
+/*                                                                                                                               */
+/*  When the function is called for free (hInstance = Instance Handle) the memory                                                */
+/*  table returns the allocated memory and base addresses used during initialisation.                                            */
+/*                                                                                                                               */
+/* PARAMETERS:                                                                                                                   */
+/*  hInstance           Instance Handle                                                                                          */
+/*  pMemoryTable        Pointer to an empty memory definition table                                                              */
+/*  pInitParams         Pointer to the instance init parameters                                                                  */
+/*                                                                                                                               */
+/* RETURNS:                                                                                                                      */
+/*  LVPSA_OK            Succeeds                                                                                                 */
+/*  otherwise           Error due to bad parameters                                                                              */
+/*                                                                                                                               */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_Memory            ( pLVPSA_Handle_t             hInstance,
+                                       LVPSA_MemTab_t             *pMemoryTable,
+                                       LVPSA_InitParams_t         *pInitParams    );
+
+/*********************************************************************************************************************************/
+/*                                                                                                                               */
+/* FUNCTION:            LVPSA_Init                                                                                               */
+/*                                                                                                                               */
+/* DESCRIPTION:                                                                                                                  */
+/*  Initializes the LVPSA module.                                                                                                */
+/*                                                                                                                               */
+/*                                                                                                                               */
+/* PARAMETERS:                                                                                                                   */
+/*  phInstance          Pointer to the instance Handle                                                                           */
+/*  pInitParams         Pointer to the instance init parameters                                                                  */
+/*  pControlParams      Pointer to the instance control parameters                                                               */
+/*  pMemoryTable        Pointer to the memory definition table                                                                   */
+/*                                                                                                                               */
+/*                                                                                                                               */
+/* RETURNS:                                                                                                                      */
+/*  LVPSA_OK            Succeeds                                                                                                 */
+/*  otherwise           Error due to bad parameters                                                                              */
+/*                                                                                                                               */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_Init              ( pLVPSA_Handle_t             *phInstance,
+                                       LVPSA_InitParams_t          *pInitParams,
+                                       LVPSA_ControlParams_t       *pControlParams,
+                                       LVPSA_MemTab_t              *pMemoryTable  );
+
+/*********************************************************************************************************************************/
+/*                                                                                                                               */
+/* FUNCTION:            LVPSA_Control                                                                                            */
+/*                                                                                                                               */
+/* DESCRIPTION:                                                                                                                  */
+/*  Controls the LVPSA module.                                                                                                   */
+/*                                                                                                                               */
+/* PARAMETERS:                                                                                                                   */
+/*  hInstance           Instance Handle                                                                                          */
+/*  pNewParams          Pointer to the instance new control parameters                                                           */
+/*                                                                                                                               */
+/* RETURNS:                                                                                                                      */
+/*  LVPSA_OK            Succeeds                                                                                                 */
+/*  otherwise           Error due to bad parameters                                                                              */
+/*                                                                                                                               */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_Control           ( pLVPSA_Handle_t             hInstance,
+                                       LVPSA_ControlParams_t      *pNewParams     );
+
+/*********************************************************************************************************************************/
+/*                                                                                                                               */
+/* FUNCTION:            LVPSA_Process                                                                                            */
+/*                                                                                                                               */
+/* DESCRIPTION:                                                                                                                  */
+/*  The process calculates the levels of the frequency bands.                                                                    */
+/*                                                                                                                               */
+/* PARAMETERS:                                                                                                                   */
+/*  hInstance           Instance Handle                                                                                          */
+/*  pLVPSA_InputSamples Pointer to the input samples buffer                                                                      */
+/*  InputBlockSize      Number of mono samples to process                                                                        */
+/*  AudioTime           Playback time of the first input sample                                                                  */
+/*                                                                                                                               */
+/*                                                                                                                               */
+/* RETURNS:                                                                                                                      */
+/*  LVPSA_OK            Succeeds                                                                                                 */
+/*  otherwise           Error due to bad parameters                                                                              */
+/*                                                                                                                               */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
+                                       LVM_INT16           *pLVPSA_InputSamples,
+                                       LVM_UINT16           InputBlockSize,
+                                       LVPSA_Time           AudioTime             );
+
+/*********************************************************************************************************************************/
+/*                                                                                                                               */
+/* FUNCTION:            LVPSA_GetSpectrum                                                                                        */
+/*                                                                                                                               */
+/* DESCRIPTION:                                                                                                                  */
+/*  This function is used for memory allocation and free.                                                                        */
+/*                                                                                                                               */
+/*                                                                                                                               */
+/* PARAMETERS:                                                                                                                   */
+/*  hInstance            Instance Handle                                                                                         */
+/*  GetSpectrumAudioTime Time to retrieve the values at                                                                          */
+/*  pCurrentValues       Pointer to an empty buffer : Current level values output                                                */
+/*  pPeakValues          Pointer to an empty buffer : Peak level values output                                                   */
+/*                                                                                                                               */
+/*                                                                                                                               */
+/* RETURNS:                                                                                                                      */
+/*  LVPSA_OK            Succeeds                                                                                                 */
+/*  otherwise           Error due to bad parameters                                                                              */
+/*                                                                                                                               */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_GetSpectrum       ( pLVPSA_Handle_t      hInstance,
+                                       LVPSA_Time           GetSpectrumAudioTime,
+                                       LVM_UINT8           *pCurrentValues,
+                                       LVM_UINT8           *pPeakValues           );
+
+/*********************************************************************************************************************************/
+/*                                                                                                                               */
+/* FUNCTION:            LVPSA_GetControlParams                                                                                   */
+/*                                                                                                                               */
+/* DESCRIPTION:                                                                                                                  */
+/*  Get the current control parameters of the LVPSA module.                                                                      */
+/*                                                                                                                               */
+/* PARAMETERS:                                                                                                                   */
+/*  hInstance           Instance Handle                                                                                          */
+/*  pParams             Pointer to an empty control parameters structure                                                         */
+/* RETURNS:                                                                                                                      */
+/*  LVPSA_OK            Succeeds                                                                                                 */
+/*  otherwise           Error due to bad parameters                                                                              */
+/*                                                                                                                               */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_GetControlParams  (    pLVPSA_Handle_t            hInstance,
+                                          LVPSA_ControlParams_t     *pParams      );
+
+/*********************************************************************************************************************************/
+/*                                                                                                                               */
+/* FUNCTION:            LVPSA_GetInitParams                                                                                      */
+/*                                                                                                                               */
+/* DESCRIPTION:                                                                                                                  */
+/*  Get the initialization parameters of the LVPSA module.                                                                       */
+/*                                                                                                                               */
+/* PARAMETERS:                                                                                                                   */
+/*  hInstance           Instance Handle                                                                                          */
+/*  pParams             Pointer to an empty init parameters structure                                                            */
+/* RETURNS:                                                                                                                      */
+/*  LVPSA_OK            Succeeds                                                                                                 */
+/*  otherwise           Error due to bad parameters                                                                              */
+/*                                                                                                                               */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_GetInitParams     (    pLVPSA_Handle_t            hInstance,
+                                          LVPSA_InitParams_t        *pParams      );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LVPSA_H */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
new file mode 100755
index 0000000..1be8ff0
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#include    "LVPSA.h"
+#include    "LVPSA_Private.h"
+#include    "VectorArithmetic.h"
+
+#define     LOW_FREQ            298             /* 32768/110 for low test frequency */
+#define     HIGH_FREQ           386             /* 32768/85 for high test frequency */
+
+LVPSA_RETURN LVPSA_SetBPFiltersType (  LVPSA_InstancePr_t        *pInst,
+                                       LVPSA_ControlParams_t      *pParams  );
+
+LVPSA_RETURN LVPSA_SetQPFCoefficients( LVPSA_InstancePr_t        *pInst,
+                                       LVPSA_ControlParams_t      *pParams  );
+
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs(  LVM_UINT16             Fs,
+                                       LVPSA_FilterParam_t   *pFilterParams,
+                                       BP_C16_Coefs_t        *pCoefficients);
+
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs(  LVM_UINT16            Fs,
+                                       LVPSA_FilterParam_t  *pFilterParams,
+                                       BP_C32_Coefs_t       *pCoefficients);
+
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs(  LVM_UINT16              Fs,
+                                       LVPSA_FilterParam_t     *pFilterParams,
+                                       BP_C32_Coefs_t          *pCoefficients);
+
+LVPSA_RETURN LVPSA_SetBPFCoefficients( LVPSA_InstancePr_t        *pInst,
+                                       LVPSA_ControlParams_t      *pParams  );
+
+LVPSA_RETURN LVPSA_ClearFilterHistory( LVPSA_InstancePr_t        *pInst);
+
+
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_Control                                               */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Give some new control parameters to the module.                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance           Pointer to the instance                                     */
+/*  NewParams           Structure that contains the new parameters                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Control           ( pLVPSA_Handle_t             hInstance,
+                                       LVPSA_ControlParams_t      *pNewParams     )
+{
+
+    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
+
+    if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+    if(pNewParams->Fs >= LVPSA_NR_SUPPORTED_RATE)
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+    if(pNewParams->LevelDetectionSpeed >= LVPSA_NR_SUPPORTED_SPEED)
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+
+    pLVPSA_Inst->NewParams = *pNewParams;
+    pLVPSA_Inst->bControlPending = LVM_TRUE;
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_GetControlParams                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Get the current control parameters of the module                                */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance       Pointer to the instance                                         */
+/*  pParams         Pointer to an empty control structure                           */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetControlParams         (    pLVPSA_Handle_t            hInstance,
+                                                 LVPSA_ControlParams_t     *pParams )
+{
+    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
+
+    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+    pParams->Fs                     = pLVPSA_Inst->CurrentParams.Fs;
+    pParams->LevelDetectionSpeed    = pLVPSA_Inst->CurrentParams.LevelDetectionSpeed;
+
+    return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_GetInitParams                                         */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Get the initialization parameters of the module                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance       Pointer to the instance                                         */
+/*  pParams         Pointer to an empty control structure                           */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetInitParams         (    pLVPSA_Handle_t            hInstance,
+                                              LVPSA_InitParams_t        *pParams )
+{
+    LVPSA_InstancePr_t     *pLVPSA_Inst    = (LVPSA_InstancePr_t*)hInstance;
+
+    if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+    pParams->SpectralDataBufferDuration   = pLVPSA_Inst->SpectralDataBufferDuration;
+    pParams->MaxInputBlockSize            = pLVPSA_Inst->MaxInputBlockSize;
+    pParams->nBands                       = pLVPSA_Inst->nBands;
+    pParams->pFiltersParams               = pLVPSA_Inst->pFiltersParams;
+
+    return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_ApplyNewSettings                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Reinitialize some parameters and changes filters' coefficients if               */
+/*  some control parameters have changed.                                           */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t     *pInst)
+{
+    LVM_UINT16 ii;
+    LVM_UINT16 Freq;
+    LVPSA_ControlParams_t   Params;
+    extern LVM_INT16        LVPSA_nSamplesBufferUpdate[];
+    extern LVM_UINT16       LVPSA_SampleRateTab[];
+    extern LVM_UINT16       LVPSA_DownSamplingFactor[];
+
+
+    if(pInst == 0)
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+    Params = pInst->NewParams;
+
+    /* Modifies filters types and coefficients, clear the taps and
+       re-initializes parameters if sample frequency has changed    */
+    if(Params.Fs != pInst->CurrentParams.Fs)
+    {
+        pInst->CurrentParams.Fs = Params.Fs;
+
+        /* Initialize the center freqeuncies as a function of the sample rate */
+        Freq = (LVM_UINT16) ((LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1) / (pInst->nBands + 1));
+        for(ii = pInst->nBands; ii > 0; ii--)
+        {
+            pInst->pFiltersParams[ii-1].CenterFrequency = (LVM_UINT16) (Freq * ii);
+        }
+
+        /* Count the number of relevant filters. If the center frequency of the filter is
+           bigger than the nyquist frequency, then the filter is not relevant and doesn't
+           need to be used */
+        for(ii = pInst->nBands; ii > 0; ii--)
+        {
+            if(pInst->pFiltersParams[ii-1].CenterFrequency < (LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1))
+            {
+                pInst->nRelevantFilters = ii;
+                break;
+            }
+        }
+        LVPSA_SetBPFiltersType(pInst, &Params);
+        LVPSA_SetBPFCoefficients(pInst, &Params);
+        LVPSA_SetQPFCoefficients(pInst, &Params);
+        LVPSA_ClearFilterHistory(pInst);
+        pInst->nSamplesBufferUpdate = (LVM_UINT16)LVPSA_nSamplesBufferUpdate[Params.Fs];
+        pInst->BufferUpdateSamplesCount = 0;
+        pInst->DownSamplingFactor = LVPSA_DownSamplingFactor[Params.Fs];
+        pInst->DownSamplingCount = 0;
+        for(ii = 0; ii < (pInst->nBands * pInst->SpectralDataBufferLength); ii++)
+        {
+            pInst->pSpectralDataBufferStart[ii] = 0;
+        }
+        for(ii = 0; ii < pInst->nBands; ii++)
+        {
+            pInst->pPreviousPeaks[ii] = 0;
+        }
+    }
+    else
+    {
+        if(Params.LevelDetectionSpeed != pInst->CurrentParams.LevelDetectionSpeed)
+        {
+            LVPSA_SetQPFCoefficients(pInst, &Params);
+        }
+    }
+
+    pInst->CurrentParams = pInst->NewParams;
+
+    return (LVPSA_OK);
+}
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_SetBPFiltersType                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the filter type based on the BPFilterType.                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*  pParams             Poniter to conrol parameters                                */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Always succeeds                                             */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1. To select the biquad type the follow rules are applied:                      */
+/*          Double precision    if (fc <= fs/110)                                   */
+/*          Double precision    if (fs/110 < fc < fs/85) & (Q>3)                    */
+/*          Single precision    otherwise                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetBPFiltersType (   LVPSA_InstancePr_t        *pInst,
+                                        LVPSA_ControlParams_t      *pParams  )
+{
+
+    extern LVM_UINT16   LVPSA_SampleRateTab[];                                            /* Sample rate table */
+    LVM_UINT16          ii;                                                         /* Filter band index */
+    LVM_UINT32          fs = (LVM_UINT32)LVPSA_SampleRateTab[(LVM_UINT16)pParams->Fs];      /* Sample rate */
+    LVM_UINT32          fc;                                                         /* Filter centre frequency */
+    LVM_INT16           QFactor;                                                    /* Filter Q factor */
+
+    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+    {
+        /*
+         * Get the filter settings
+         */
+        fc = (LVM_UINT32)pInst->pFiltersParams[ii].CenterFrequency;     /* Get the band centre frequency */
+        QFactor =(LVM_INT16) pInst->pFiltersParams[ii].QFactor;                    /* Get the band Q factor */
+
+
+        /*
+         * For each filter set the type of biquad required
+         */
+        pInst->pBPFiltersPrecision[ii] = LVPSA_SimplePrecisionFilter;     /* Default to single precision */
+        if ((LOW_FREQ * fs) >= (fc << 15))
+        {
+            /*
+             * fc <= fs/110
+             */
+            pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
+        }
+        else
+        {
+            if (((LOW_FREQ * fs) < (fc << 15)) && ((fc << 15) < (HIGH_FREQ * fs)) && (QFactor > 300))
+            {
+                /*
+                * (fs/110 < fc < fs/85) & (Q>3)
+                */
+                pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
+            }
+        }
+    }
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_SetBPFCoefficients                                    */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the band pass filter coefficients. This uses the type to select            */
+/*  single or double precision coefficients.                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*  Params              Initialisation parameters                                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Always succeeds                                             */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetBPFCoefficients(  LVPSA_InstancePr_t        *pInst,
+                                        LVPSA_ControlParams_t      *pParams)
+{
+
+    LVM_UINT16                      ii;
+
+    /*
+     * Set the coefficients for each band by the init function
+     */
+    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+    {
+        switch  (pInst->pBPFiltersPrecision[ii])
+        {
+            case    LVPSA_DoublePrecisionFilter:
+            {
+                BP_C32_Coefs_t      Coefficients;
+
+                /*
+                 * Calculate the double precision coefficients
+                 */
+                LVPSA_BPDoublePrecCoefs((LVM_UINT16)pParams->Fs,
+                                       &pInst->pFiltersParams[ii],
+                                       &Coefficients);
+
+                /*
+                 * Set the coefficients
+                 */
+                BP_1I_D16F32Cll_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+                                                  &pInst->pBP_Taps[ii],
+                                                  &Coefficients);
+                break;
+            }
+
+            case    LVPSA_SimplePrecisionFilter:
+            {
+                BP_C16_Coefs_t      Coefficients;
+
+                /*
+                 * Calculate the single precision coefficients
+                 */
+                LVPSA_BPSinglePrecCoefs((LVM_UINT16)pParams->Fs,
+                                       &pInst->pFiltersParams[ii],
+                                       &Coefficients);
+
+                /*
+                 * Set the coefficients
+                 */
+                BP_1I_D16F16Css_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+                                                  &pInst->pBP_Taps[ii],
+                                                  &Coefficients);
+                break;
+            }
+        }
+    }
+
+    return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_SetQPFCoefficients                                    */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets the quasi peak filters coefficients. This uses the chosen                  */
+/*  LevelDetectionSpeed from the control parameters.                                */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*  Params              Control parameters                                          */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Always succeeds                                             */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetQPFCoefficients(   LVPSA_InstancePr_t        *pInst,
+                                         LVPSA_ControlParams_t      *pParams  )
+{
+    LVM_UINT16     ii;
+    LVM_Fs_en      Fs = pParams->Fs;
+    QPD_C32_Coefs  *pCoefficients;
+    extern         QPD_C32_Coefs     LVPSA_QPD_Coefs[];
+
+
+    pCoefficients = &LVPSA_QPD_Coefs[(pParams->LevelDetectionSpeed * LVPSA_NR_SUPPORTED_RATE) + Fs];
+
+
+    for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+    {
+            LVPSA_QPD_Init (&pInst->pQPD_States[ii],
+                            &pInst->pQPD_Taps[ii],
+                            pCoefficients );
+    }
+
+    return(LVPSA_OK);
+
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVPSA_BPSinglePrecCoefs                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Calculate single precision coefficients for a band pass filter                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  Fs                       Sampling frequency index                                   */
+/*  pFilterParams            Pointer to the filter definition                           */
+/*  pCoefficients            Pointer to the coefficients                                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVPSA_OK         Always succeeds                                                    */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The equations used are as follows:                                               */
+/*                                                                                      */
+/*      t0 = 2 * Pi * Fc / Fs                                                           */
+/*                                                                                      */
+/*      b2 = -0.5 * (2Q - t0) / (2Q + t0)                                               */
+/*      b1 = (0.5 - b2) * cos(t0)                                                       */
+/*      a0 = (0.5 + b2) / 2                                                             */
+/*                                                                                      */
+/*  Where:                                                                              */
+/*      Fc          is the centre frequency, DC to Nyquist                              */
+/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
+/*      Q           is the Q factor, 0.25 to 12                                         */
+/*                                                                                      */
+/*  2. This function is entirely based on the LVEQNB_SinglePrecCoefs function           */
+/*     of the n bands equalizer (LVEQNB                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs(    LVM_UINT16              Fs,
+                                         LVPSA_FilterParam_t    *pFilterParams,
+                                         BP_C16_Coefs_t         *pCoefficients)
+{
+
+    extern LVM_INT16    LVPSA_TwoPiOnFsTable[];
+    extern LVM_INT16    LVPSA_CosCoef[];
+
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_INT32           T0;
+    LVM_INT16           D;
+    LVM_INT32           A0;
+    LVM_INT32           B1;
+    LVM_INT32           B2;
+    LVM_INT32           Dt0;
+    LVM_INT32           B2_Den;
+    LVM_INT32           B2_Num;
+    LVM_INT32           COS_T0;
+    LVM_INT16           coef;
+    LVM_INT32           factor;
+    LVM_INT16           t0;
+    LVM_INT16           i;
+
+
+    /*
+     * Get the filter definition
+     */
+    LVM_UINT16          Frequency   = pFilterParams->CenterFrequency;
+    LVM_UINT16          QFactor     = pFilterParams->QFactor;
+
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = (LVM_INT32)Frequency * LVPSA_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
+    D = 3200;                                               /* Floating point value 1.000000 (1*100*2^5) */
+                                                            /* Force D = 1 : the function was originally used for a peaking filter.
+                                                               The D parameter do not exist for a BandPass filter coefficients */
+
+    /*
+     * Calculate the B2 coefficient
+     */
+    Dt0 = D * (T0 >> 10);
+    B2_Den = (LVM_INT32)(((LVM_UINT32)QFactor << 19) + (LVM_UINT32)(Dt0 >> 2));
+    B2_Num = (LVM_INT32)((LVM_UINT32)(Dt0 >> 3) - ((LVM_UINT32)QFactor << 18));
+    B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+    /*
+     * Calculate the cosine by a polynomial expansion using the equation:
+     *
+     *  Cos += coef(n) * t0^n                   For n = 0 to 6
+     */
+    T0 = (T0 >> 10) * 20859;                    /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
+    t0 = (LVM_INT16)(T0 >> 16);
+    factor = 0x7fff;                            /* Initialise to 1.0 for the a0 coefficient */
+    COS_T0 = 0;                                 /* Initialise the error to zero */
+    for (i=1; i<7; i++)
+    {
+        coef = LVPSA_CosCoef[i];                /* Get the nth coefficient */
+        COS_T0 += (factor * coef) >> 5;         /* The nth partial sum */
+        factor = (factor * t0) >> 15;           /* Calculate t0^n */
+    }
+    COS_T0 = COS_T0 << (LVPSA_CosCoef[0]+6);          /* Correct the scaling */
+
+
+    B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16);    /* B1 = (0.5 - b2) * cos(t0) */
+    A0 = (0x40000000 + B2) >> 1;                        /* A0 = (0.5 + b2) / 2 */
+
+    /*
+     * Write coeff into the data structure
+     */
+    pCoefficients->A0 = (LVM_INT16)(A0>>16);
+    pCoefficients->B1 = (LVM_INT16)(B1>>15);
+    pCoefficients->B2 = (LVM_INT16)(B2>>16);
+
+
+    return(LVPSA_OK);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVPSA_BPDoublePrecCoefs                                    */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Calculate double precision coefficients for a band pass filter                      */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  Fs                       Sampling frequency index                                   */
+/*  pFilterParams            Pointer to the filter definition                           */
+/*  pCoefficients            Pointer to the coefficients                                */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVPSA_OK                 Always succeeds                                            */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1. The equations used are as follows:                                               */
+/*                                                                                      */
+/*      t0 = 2 * Pi * Fc / Fs                                                           */
+/*                                                                                      */
+/*      b2 = -0.5 * (2Q - t0) / (2Q + t0)                                               */
+/*      b1 = (0.5 - b2) * (1 - coserr(t0))                                              */
+/*      a0 = (0.5 + b2) / 2                                                             */
+/*                                                                                      */
+/*  Where:                                                                              */
+/*      Fc          is the centre frequency, DC to Fs/50                                */
+/*      Fs          is the sample frequency, 8000 to 48000 in descrete steps            */
+/*      Q           is the Q factor, 0.25 to 12 (represented by 25 to 1200)             */
+/*                                                                                      */
+/*  2. The double precision coefficients are only used when fc is less than fs/85, so   */
+/*     the cosine of t0 is always close to 1.0. Instead of calculating the cosine       */
+/*     itself the difference from the value 1.0 is calculated, this can be done with    */
+/*     lower precision maths.                                                           */
+/*                                                                                      */
+/*  3. The value of the B2 coefficient is only calculated as a single precision value,  */
+/*     small errors in this value have a combined effect on the Q and Gain but not the  */
+/*     the frequency of the filter.                                                     */
+/*                                                                                      */
+/*  4. This function is entirely based on the LVEQNB_DoublePrecCoefs function           */
+/*     of the n bands equalizer (LVEQNB                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs(   LVM_UINT16            Fs,
+                                        LVPSA_FilterParam_t  *pFilterParams,
+                                        BP_C32_Coefs_t       *pCoefficients)
+{
+
+    extern LVM_INT16    LVPSA_TwoPiOnFsTable[];
+    extern LVM_INT16    LVPSA_DPCosCoef[];
+
+    /*
+     * Intermediate variables and temporary values
+     */
+    LVM_INT32           T0;
+    LVM_INT16           D;
+    LVM_INT32           A0;
+    LVM_INT32           B1;
+    LVM_INT32           B2;
+    LVM_INT32           Dt0;
+    LVM_INT32           B2_Den;
+    LVM_INT32           B2_Num;
+    LVM_INT32           CosErr;
+    LVM_INT16           coef;
+    LVM_INT32           factor;
+    LVM_INT16           t0;
+    LVM_INT16           i;
+
+    /*
+     * Get the filter definition
+     */
+    LVM_UINT16          Frequency   = pFilterParams->CenterFrequency;
+    LVM_UINT16          QFactor     = pFilterParams->QFactor;
+
+
+    /*
+     * Calculating the intermediate values
+     */
+    T0 = (LVM_INT32)Frequency * LVPSA_TwoPiOnFsTable[Fs];   /* T0 = 2 * Pi * Fc / Fs */
+    D = 3200;                                               /* Floating point value 1.000000 (1*100*2^5) */
+                                                            /* Force D = 1 : the function was originally used for a peaking filter.
+                                                               The D parameter do not exist for a BandPass filter coefficients */
+
+    /*
+     * Calculate the B2 coefficient
+     */
+    Dt0 = D * (T0 >> 10);
+    B2_Den = (LVM_INT32)(((LVM_UINT32)QFactor << 19) + (LVM_UINT32)(Dt0 >> 2));
+    B2_Num = (LVM_INT32)((LVM_UINT32)(Dt0 >> 3) - ((LVM_UINT32)QFactor << 18));
+    B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+    /*
+     * Calculate the cosine error by a polynomial expansion using the equation:
+     *
+     *  CosErr += coef(n) * t0^n                For n = 0 to 4
+     */
+    T0 = (T0 >> 6) * 0x7f53;                    /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
+    t0 = (LVM_INT16)(T0 >> 16);
+    factor = 0x7fff;                            /* Initialise to 1.0 for the a0 coefficient */
+    CosErr = 0;                                 /* Initialise the error to zero */
+    for (i=1; i<5; i++)
+    {
+        coef = LVPSA_DPCosCoef[i];              /* Get the nth coefficient */
+        CosErr += (factor * coef) >> 5;         /* The nth partial sum */
+        factor = (factor * t0) >> 15;           /* Calculate t0^n */
+    }
+    CosErr = CosErr << (LVPSA_DPCosCoef[0]);          /* Correct the scaling */
+
+    /*
+     * Calculate the B1 and A0 coefficients
+     */
+    B1 = (0x40000000 - B2);                     /* B1 = (0.5 - b2) */
+    A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6;    /* Temporary storage for (0.5 - b2) * coserr(t0) */
+    B1 -= A0;                                   /* B1 = (0.5 - b2) * (1 - coserr(t0))  */
+    A0 = (0x40000000 + B2) >> 1;                /* A0 = (0.5 + b2) / 2 */
+
+    /*
+     * Write coeff into the data structure
+     */
+    pCoefficients->A0 = A0;
+    pCoefficients->B1 = B1;
+    pCoefficients->B2 = B2;
+
+    return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_ClearFilterHistory                                    */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Clears the filters' data history                                                */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst           Pointer to the instance                                         */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK         Always succeeds                                                */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ClearFilterHistory(LVPSA_InstancePr_t        *pInst)
+{
+    LVM_INT8       *pTapAddress;
+    LVM_UINT32       i;
+
+    /* Band Pass filters taps */
+    pTapAddress = (LVM_INT8 *)pInst->pBP_Taps;
+    for(i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_Taps_t); i++)
+    {
+        pTapAddress[i] = 0;
+    }
+
+    /* Quasi-peak filters taps */
+    pTapAddress = (LVM_INT8 *)pInst->pQPD_Taps;
+    for(i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++)
+    {
+        pTapAddress[i] = 0;
+    }
+
+    return(LVPSA_OK);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
new file mode 100755
index 0000000..ab45678
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#include    "LVPSA.h"
+#include    "LVPSA_Private.h"
+#include    "InstAlloc.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_Init                                                  */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialize the LVPSA module                                                     */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  phInstance          Pointer to pointer to the instance                          */
+/*  InitParams          Init parameters structure                                   */
+/*  ControlParams       Control parameters structure                                */
+/*  pMemoryTable        Memory table that contains memory areas definition          */
+/*                                                                                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Init              ( pLVPSA_Handle_t             *phInstance,
+                                       LVPSA_InitParams_t          *pInitParams,
+                                       LVPSA_ControlParams_t       *pControlParams,
+                                       LVPSA_MemTab_t              *pMemoryTable )
+{
+    LVPSA_InstancePr_t          *pLVPSA_Inst;
+    LVPSA_RETURN                errorCode       = LVPSA_OK;
+    LVM_UINT32                  ii;
+    extern LVM_INT16            LVPSA_GainTable[];
+    LVM_UINT32                  BufferLength = 0;
+
+    /* Ints_Alloc instances, needed for memory alignment management */
+    INST_ALLOC          Instance;
+    INST_ALLOC          Scratch;
+    INST_ALLOC          Data;
+    INST_ALLOC          Coef;
+
+    /* Check parameters */
+    if((phInstance == LVM_NULL) || (pInitParams == LVM_NULL) || (pControlParams == LVM_NULL) || (pMemoryTable == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+    if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION)   ||
+        (pInitParams->SpectralDataBufferDuration == 0)                        ||
+        (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE)      ||
+        (pInitParams->MaxInputBlockSize == 0)                           ||
+        (pInitParams->nBands < LVPSA_NBANDSMIN)                         ||
+        (pInitParams->nBands > LVPSA_NBANDSMAX)                         ||
+        (pInitParams->pFiltersParams == 0))
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+    for(ii = 0; ii < pInitParams->nBands; ii++)
+    {
+        if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
+           (pInitParams->pFiltersParams[ii].PostGain        > LVPSA_MAXPOSTGAIN)   ||
+           (pInitParams->pFiltersParams[ii].PostGain        < LVPSA_MINPOSTGAIN)   ||
+           (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR)            ||
+           (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
+           {
+                return(LVPSA_ERROR_INVALIDPARAM);
+           }
+    }
+
+
+    /*Inst_Alloc instances initialization */
+    InstAlloc_Init( &Instance   , pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress);
+    InstAlloc_Init( &Scratch    , pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress);
+    InstAlloc_Init( &Data       , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress);
+    InstAlloc_Init( &Coef       , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress);
+
+
+    /* Set the instance handle if not already initialised */
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+    }
+    pLVPSA_Inst =(LVPSA_InstancePr_t*)*phInstance;
+
+
+    /* Check the memory table for NULL pointers */
+    for (ii = 0; ii < LVPSA_NR_MEMORY_REGIONS; ii++)
+    {
+        if (pMemoryTable->Region[ii].Size!=0)
+        {
+            if (pMemoryTable->Region[ii].pBaseAddress==LVM_NULL)
+            {
+                return(LVPSA_ERROR_NULLADDRESS);
+            }
+            pLVPSA_Inst->MemoryTable.Region[ii] = pMemoryTable->Region[ii];
+        }
+    }
+
+    /* Initialize module's internal parameters */
+    pLVPSA_Inst->bControlPending = LVM_FALSE;
+    pLVPSA_Inst->nBands = pInitParams->nBands;
+    pLVPSA_Inst->MaxInputBlockSize = pInitParams->MaxInputBlockSize;
+    pLVPSA_Inst->SpectralDataBufferDuration = pInitParams->SpectralDataBufferDuration;
+    pLVPSA_Inst->CurrentParams.Fs = LVM_FS_DUMMY;
+    pLVPSA_Inst->CurrentParams.LevelDetectionSpeed = LVPSA_SPEED_DUMMY;
+
+    {   /* for avoiding QAC warnings */
+        LVM_INT32 SDBD=(LVM_INT32)pLVPSA_Inst->SpectralDataBufferDuration;
+        LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
+        LVM_INT32 BL;
+
+        MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
+
+        BufferLength=(LVM_UINT32)BL;
+    }
+
+    if((BufferLength * LVPSA_InternalRefreshTime) != pLVPSA_Inst->SpectralDataBufferDuration)
+    {
+        pLVPSA_Inst->SpectralDataBufferLength = BufferLength + 1;
+    }
+    else
+    {
+        pLVPSA_Inst->SpectralDataBufferLength = BufferLength;
+    }
+
+
+    /* Assign the pointers */
+
+    pLVPSA_Inst->pPostGains                 = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
+    pLVPSA_Inst->pFiltersParams             = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
+    pLVPSA_Inst->pSpectralDataBufferStart   = InstAlloc_AddMember( &Instance, pInitParams->nBands * pLVPSA_Inst->SpectralDataBufferLength * sizeof(LVM_UINT8) );
+    pLVPSA_Inst->pPreviousPeaks             = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
+    pLVPSA_Inst->pBPFiltersPrecision        = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
+
+    pLVPSA_Inst->pBP_Instances          = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
+    pLVPSA_Inst->pQPD_States            = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
+
+    pLVPSA_Inst->pBP_Taps               = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
+    pLVPSA_Inst->pQPD_Taps              = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
+
+
+    /* Copy filters parameters in the private instance */
+    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+    {
+        pLVPSA_Inst->pFiltersParams[ii] = pInitParams->pFiltersParams[ii];
+    }
+
+    /* Set Post filters gains*/
+    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+    {
+        pLVPSA_Inst->pPostGains[ii] =(LVM_UINT16) LVPSA_GainTable[pInitParams->pFiltersParams[ii].PostGain + 15];
+    }
+    pLVPSA_Inst->pSpectralDataBufferWritePointer = pLVPSA_Inst->pSpectralDataBufferStart;
+
+
+    /* Initialize control dependant internal parameters */
+    errorCode = LVPSA_Control (*phInstance, pControlParams);
+
+    if(errorCode!=0)
+    {
+        return errorCode;
+    }
+
+    errorCode = LVPSA_ApplyNewSettings (pLVPSA_Inst);
+
+    if(errorCode!=0)
+    {
+        return errorCode;
+    }
+
+    return(errorCode);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
new file mode 100755
index 0000000..059cb4e
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#include    "LVPSA.h"
+#include    "LVPSA_Private.h"
+#include    "InstAlloc.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVEQNB_Memory                                               */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL         Returns the memory requirements                        */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) the memory      */
+/*  base address pointers are NULL on return.                                           */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the memory       */
+/*  table returns the allocated memory and base addresses used during initialisation.   */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  InitParams              Pointer to the instance init parameters                     */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVPSA_OK            Succeeds                                                        */
+/*  otherwise           Error due to bad parameters                                     */
+/*                                                                                      */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_Memory            ( pLVPSA_Handle_t             hInstance,
+                                       LVPSA_MemTab_t             *pMemoryTable,
+                                       LVPSA_InitParams_t         *pInitParams    )
+{
+    LVM_UINT32          ii;
+    LVM_UINT32          BufferLength;
+    INST_ALLOC          Instance;
+    INST_ALLOC          Scratch;
+    INST_ALLOC          Data;
+    INST_ALLOC          Coef;
+    LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+
+    InstAlloc_Init( &Instance   , LVM_NULL);
+    InstAlloc_Init( &Scratch    , LVM_NULL);
+    InstAlloc_Init( &Data       , LVM_NULL);
+    InstAlloc_Init( &Coef       , LVM_NULL);
+
+
+    if((pMemoryTable == LVM_NULL) || (pInitParams == LVM_NULL))
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+
+        /* Check init parameter */
+        if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION)   ||
+            (pInitParams->SpectralDataBufferDuration == 0)                        ||
+            (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE)      ||
+            (pInitParams->MaxInputBlockSize == 0)                           ||
+            (pInitParams->nBands < LVPSA_NBANDSMIN)                         ||
+            (pInitParams->nBands > LVPSA_NBANDSMAX)                         ||
+            (pInitParams->pFiltersParams == 0))
+        {
+            return(LVPSA_ERROR_INVALIDPARAM);
+        }
+        for(ii = 0; ii < pInitParams->nBands; ii++)
+        {
+            if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
+               (pInitParams->pFiltersParams[ii].PostGain        > LVPSA_MAXPOSTGAIN)   ||
+               (pInitParams->pFiltersParams[ii].PostGain        < LVPSA_MINPOSTGAIN)   ||
+               (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR)            ||
+               (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
+               {
+                    return(LVPSA_ERROR_INVALIDPARAM);
+               }
+        }
+
+        /*
+         * Instance memory
+         */
+
+        InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
+
+        {
+            /* for avoiding QAC warnings as MUL32x32INTO32 works on LVM_INT32 only*/
+            LVM_INT32 SDBD=(LVM_INT32)pInitParams->SpectralDataBufferDuration;
+            LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
+            LVM_INT32 BL;
+
+            MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
+            BufferLength=(LVM_UINT32)BL;
+        }
+
+
+        if((BufferLength * LVPSA_InternalRefreshTime) != pInitParams->SpectralDataBufferDuration)
+        {
+            BufferLength++;
+        }
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * BufferLength * sizeof(LVM_UINT8) );
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
+        InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
+        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Size         = InstAlloc_GetTotal(&Instance);
+        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Type         = LVPSA_PERSISTENT;
+        pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+        /*
+         * Scratch memory
+         */
+        InstAlloc_AddMember( &Scratch, 2 * pInitParams->MaxInputBlockSize * sizeof(LVM_INT16) );
+        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Size         = InstAlloc_GetTotal(&Scratch);
+        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Type         = LVPSA_SCRATCH;
+        pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistent coefficients memory
+         */
+        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
+        InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&Coef);
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Type         = LVPSA_PERSISTENT_COEF;
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Persistent data memory
+         */
+        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
+        InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&Data);
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Type         = LVPSA_PERSISTENT_DATA;
+        pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+    }
+    else
+    {
+        /* Read back memory allocation table */
+        *pMemoryTable = pLVPSA_Inst->MemoryTable;
+    }
+
+    return(LVPSA_OK);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
new file mode 100755
index 0000000..eb9fa8f
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#ifndef _LVPSA_PRIVATE_H_
+#define _LVPSA_PRIVATE_H_
+
+#include "LVPSA.h"
+#include "BIQUAD.h"
+#include "LVPSA_QPD.h"
+#include "LVM_Macros.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************
+   CONSTANT DEFINITIONS
+***********************************************************************************/
+
+/* Memory */
+#define LVPSA_INSTANCE_ALIGN             4      /* 32-bit alignment for structures                                  */
+#define LVPSA_SCRATCH_ALIGN              4      /* 32-bit alignment for long data                                   */
+#define LVPSA_COEF_ALIGN                 4      /* 32-bit alignment for long words                                  */
+#define LVPSA_DATA_ALIGN                 4      /* 32-bit alignment for long data                                   */
+
+#define LVPSA_MEMREGION_INSTANCE         0      /* Offset to instance memory region in memory table                 */
+#define LVPSA_MEMREGION_PERSISTENT_COEF  1      /* Offset to persistent coefficients  memory region in memory table */
+#define LVPSA_MEMREGION_PERSISTENT_DATA  2      /* Offset to persistent taps  memory region in memory table         */
+#define LVPSA_MEMREGION_SCRATCH          3      /* Offset to scratch  memory region in memory table                 */
+
+#define LVPSA_NR_SUPPORTED_RATE          9      /* From 8000Hz to 48000Hz                                           */
+#define LVPSA_NR_SUPPORTED_SPEED         3      /* LOW, MEDIUM, HIGH                                                */
+
+#define LVPSA_MAXBUFFERDURATION          4000   /* Maximum length in ms of the levels buffer                        */
+#define LVPSA_MAXINPUTBLOCKSIZE          5000   /* Maximum length in mono samples of the block to process           */
+#define LVPSA_NBANDSMIN                  1      /* Minimum number of frequency band                                 */
+#define LVPSA_NBANDSMAX                  30     /* Maximum number of frequency band                                 */
+#define LVPSA_MAXCENTERFREQ              20000  /* Maximum possible center frequency                                */
+#define LVPSA_MINPOSTGAIN                -15    /* Minimum possible post gain                                       */
+#define LVPSA_MAXPOSTGAIN                15     /* Maximum possible post gain                                       */
+#define LVPSA_MINQFACTOR                 25     /* Minimum possible Q factor                                        */
+#define LVPSA_MAXQFACTOR                 1200   /* Maximum possible Q factor                                        */
+
+#define LVPSA_MAXLEVELDECAYFACTOR        0x4111 /* Decay factor for the maximum values calculation                  */
+#define LVPSA_MAXLEVELDECAYSHIFT         14     /* Decay shift for the maximum values calculation                   */
+
+#define LVPSA_MAXUNSIGNEDCHAR            0xFF
+
+#define LVPSA_FsInvertShift              31
+#define LVPSA_GAINSHIFT                  11
+#define LVPSA_FREQSHIFT                  25
+
+/**********************************************************************************
+   TYPES DEFINITIONS
+***********************************************************************************/
+
+#define LVPSA_InternalRefreshTime       0x0014    /* 20 ms (50Hz) in Q16.0      */
+#define LVPSA_InternalRefreshTimeInv    0x0666    /* 1/20ms left shifted by 15  */
+#define LVPSA_InternalRefreshTimeShift  15
+
+
+/* Precision of the filter */
+typedef enum
+{
+    LVPSA_SimplePrecisionFilter,    /* Simple precision */
+    LVPSA_DoublePrecisionFilter     /* Double precision */
+} LVPSA_BPFilterPrecision_en;
+
+typedef struct
+{
+    LVM_CHAR                    bControlPending;                    /* Flag incating a change of the control parameters                                             */
+    LVM_UINT16                  nBands;                             /* Number of bands of the spectrum analyzer                                                     */
+    LVM_UINT16                  MaxInputBlockSize;                  /* Maximum input data buffer size                                                               */
+
+    LVPSA_ControlParams_t       CurrentParams;                      /* Current control parameters of the module                                                     */
+    LVPSA_ControlParams_t       NewParams;                          /* New control parameters given by the user                                                     */
+    LVPSA_MemTab_t              MemoryTable;
+
+    LVPSA_BPFilterPrecision_en *pBPFiltersPrecision;                /* Points a nBands elements array that contains the filter precision for each band              */
+    Biquad_Instance_t          *pBP_Instances;                      /* Points a nBands elements array that contains the band pass filter instance for each band     */
+    Biquad_1I_Order2_Taps_t    *pBP_Taps;                           /* Points a nBands elements array that contains the band pass filter taps for each band         */
+    QPD_State_t                *pQPD_States;                        /* Points a nBands elements array that contains the QPD filter instance for each band           */
+    QPD_Taps_t                 *pQPD_Taps;                          /* Points a nBands elements array that contains the QPD filter taps for each band               */
+    LVM_UINT16                 *pPostGains;                         /* Points a nBands elements array that contains the post-filter gains for each band             */
+
+    LVPSA_FilterParam_t        *pFiltersParams;                     /* Copy of the filters parameters from the input parameters                                     */
+
+
+    LVM_UINT16                  nSamplesBufferUpdate;               /* Number of samples to make 20ms                                                               */
+    LVM_INT32                   BufferUpdateSamplesCount;           /* Counter used to know when to put a new value in the buffer                                   */
+    LVM_UINT16                  nRelevantFilters;                   /* Number of relevent filters depending on sampling frequency and bands center frequency        */
+    LVM_UINT16                  LocalSamplesCount;                  /* Counter used to update the SpectralDataBufferAudioTime                                       */
+
+    LVM_UINT16                  DownSamplingFactor;                 /* Down sampling factor depending on the sampling frequency                                     */
+    LVM_UINT16                  DownSamplingCount;                  /* Counter used for the downsampling handling                                                   */
+
+    LVM_UINT16                  SpectralDataBufferDuration;         /* Length of the buffer in time (ms) defined by the application                                 */
+    LVM_UINT8                  *pSpectralDataBufferStart;           /* Starting address of the buffer                                                               */
+    LVM_UINT8                  *pSpectralDataBufferWritePointer;    /* Current position of the writting pointer of the buffer                                       */
+    LVPSA_Time                  SpectralDataBufferAudioTime;        /* AudioTime at which the last value save occured in the buffer                                 */
+    LVM_UINT32                  SpectralDataBufferLength;           /* Number of spectrum data value that the buffer can contain (per band)
+                                                                       = SpectralDataBufferDuration/20ms                                                            */
+
+    LVM_UINT8                  *pPreviousPeaks;                     /* Points to a nBands elements array that contains the previous peak value of the level
+                                                                     detection. Those values are decremented after each call to the GetSpectrum function          */
+
+}LVPSA_InstancePr_t, *pLVPSA_InstancePr_t;
+
+
+
+/**********************************************************************************
+   FUNCTIONS PROTOTYPE
+***********************************************************************************/
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_ApplyNewSettings                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Reinitialize some parameters and changes filters' coefficients if               */
+/*  some control parameters have changed.                                           */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the instance                                     */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Always succeeds                                             */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t     *pInst);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LVPSA_PRIVATE_H */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
new file mode 100755
index 0000000..d88a751
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#include    "LVPSA.h"
+#include    "LVPSA_Private.h"
+#include    "LVM_Macros.h"
+#include    "VectorArithmetic.h"
+
+#define LVM_MININT_32   0x80000000
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_Process                                               */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  The process applies band pass filters to the signal. Each output                */
+/*  feeds a quasi peak filter for level detection.                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance           Pointer to the instance                                     */
+/*  pLVPSA_InputSamples Pointer to the input samples buffer                         */
+/*  InputBlockSize      Number of mono samples to process                           */
+/*  AudioTime           Playback time of the input samples                          */
+/*                                                                                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
+                                       LVM_INT16           *pLVPSA_InputSamples,
+                                       LVM_UINT16           InputBlockSize,
+                                       LVPSA_Time           AudioTime            )
+
+{
+    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+    LVM_INT16               *pScratch;
+    LVM_INT16               ii;
+    LVM_INT32               AudioTimeInc;
+    extern LVM_UINT32       LVPSA_SampleRateInvTab[];
+    LVM_UINT8               *pWrite_Save;         /* Position of the write pointer at the beginning of the process  */
+
+    /******************************************************************************
+       CHECK PARAMETERS
+    *******************************************************************************/
+    if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+    if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
+    {
+        return(LVPSA_ERROR_INVALIDPARAM);
+    }
+
+    pScratch = (LVM_INT16*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
+    pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+
+    /******************************************************************************
+       APPLY NEW SETTINGS IF NEEDED
+    *******************************************************************************/
+    if (pLVPSA_Inst->bControlPending == LVM_TRUE)
+    {
+        pLVPSA_Inst->bControlPending = 0;
+        LVPSA_ApplyNewSettings( pLVPSA_Inst);
+    }
+
+    /******************************************************************************
+       PROCESS SAMPLES
+    *******************************************************************************/
+    /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
+    Copy_16( pLVPSA_InputSamples,pScratch,(LVM_INT16)InputBlockSize);
+    Shift_Sat_v16xv16(-1,pScratch,pScratch,(LVM_INT16)InputBlockSize);
+
+    for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
+    {
+        switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
+        {
+            case LVPSA_SimplePrecisionFilter:
+                BP_1I_D16F16C14_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
+                                              pScratch,
+                                              pScratch + InputBlockSize,
+                                              (LVM_INT16)InputBlockSize);
+                break;
+
+            case LVPSA_DoublePrecisionFilter:
+                BP_1I_D16F32C30_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
+                                              pScratch,
+                                              pScratch + InputBlockSize,
+                                              (LVM_INT16)InputBlockSize);
+                break;
+            default:
+                break;
+        }
+
+
+        LVPSA_QPD_Process   ( pLVPSA_Inst,
+                              pScratch + InputBlockSize,
+                              (LVM_INT16)InputBlockSize,
+                              ii);
+    }
+
+    /******************************************************************************
+       UPDATE SpectralDataBufferAudioTime
+    *******************************************************************************/
+
+    if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
+    {
+        MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
+                        (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
+                        AudioTimeInc,
+                        LVPSA_FsInvertShift)
+        pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
+    }
+
+    return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_GetSpectrum                                           */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Gets the levels values at a certain point in time                               */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance            Pointer to the instance                                    */
+/*  GetSpectrumAudioTime Retrieve the values at this time                           */
+/*  pCurrentValues       Pointer to a buffer that will contain levels' values       */
+/*  pMaxValues           Pointer to a buffer that will contain max levels' values   */
+/*                                                                                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVPSA_OK            Succeeds                                                    */
+/*  otherwise           Error due to bad parameters                                 */
+/*                                                                                  */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetSpectrum       ( pLVPSA_Handle_t      hInstance,
+                                       LVPSA_Time           GetSpectrumAudioTime,
+                                       LVM_UINT8           *pCurrentValues,
+                                       LVM_UINT8           *pPeakValues           )
+
+{
+
+    LVPSA_InstancePr_t      *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+    LVM_INT32               StatusDelta, ii;
+    LVM_UINT8               *pRead;
+
+    if(hInstance == LVM_NULL || pCurrentValues == LVM_NULL || pPeakValues == LVM_NULL)
+    {
+        return(LVPSA_ERROR_NULLADDRESS);
+    }
+
+
+    /* First find the place where to look in the status buffer */
+    if(GetSpectrumAudioTime <= pLVPSA_Inst->SpectralDataBufferAudioTime)
+    {
+        MUL32x32INTO32((pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift);
+        if((StatusDelta * LVPSA_InternalRefreshTime) != (pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime))
+        {
+            StatusDelta += 1;
+        }
+    }
+    else
+    {
+        /* This part handles the wrap around */
+        MUL32x32INTO32(((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift)
+        if(((LVM_INT32)(StatusDelta * LVPSA_InternalRefreshTime)) != ((LVM_INT32)((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime))))
+        {
+            StatusDelta += 1;
+        }
+    }
+    /* Check whether the desired level is not too "old" (see 2.10 in LVPSA_DesignNotes.doc)*/
+    if(
+        ((GetSpectrumAudioTime < pLVPSA_Inst->SpectralDataBufferAudioTime)&&
+         ((GetSpectrumAudioTime<0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>0))&&
+         (((LVM_INT32)(-GetSpectrumAudioTime + pLVPSA_Inst->SpectralDataBufferAudioTime))>LVM_MAXINT_32))||
+
+         ((GetSpectrumAudioTime > pLVPSA_Inst->SpectralDataBufferAudioTime)&&
+         (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>=0))||
+          ((GetSpectrumAudioTime<=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))||
+         (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))&&
+         (((LVM_INT32)(GetSpectrumAudioTime - pLVPSA_Inst->SpectralDataBufferAudioTime))<LVM_MAXINT_32))))||
+
+        (StatusDelta > (LVM_INT32)pLVPSA_Inst->SpectralDataBufferLength) ||
+        (!StatusDelta))
+    {
+        for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+        {
+            pCurrentValues[ii]  = 0;
+            pPeakValues[ii]      = 0;
+        }
+        return(LVPSA_OK);
+    }
+    /* Set the reading pointer */
+    if((LVM_INT32)(StatusDelta * pLVPSA_Inst->nBands) > (pLVPSA_Inst->pSpectralDataBufferWritePointer - pLVPSA_Inst->pSpectralDataBufferStart))
+    {
+        pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer + (pLVPSA_Inst->SpectralDataBufferLength - (LVM_UINT32)StatusDelta) * pLVPSA_Inst->nBands;
+    }
+    else
+    {
+        pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer  - StatusDelta * pLVPSA_Inst->nBands;
+    }
+
+
+    /* Read the status buffer and fill the output buffers */
+    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+    {
+        pCurrentValues[ii] = pRead[ii];
+        if(pLVPSA_Inst->pPreviousPeaks[ii] <= pRead[ii])
+        {
+            pLVPSA_Inst->pPreviousPeaks[ii] = pRead[ii];
+        }
+        else if(pLVPSA_Inst->pPreviousPeaks[ii] != 0)
+        {
+            LVM_INT32 temp;
+            /*Re-compute max values for decay */
+            temp = (LVM_INT32)(LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]);
+            temp = ((temp * LVPSA_MAXLEVELDECAYFACTOR)>>LVPSA_MAXLEVELDECAYSHIFT);
+            /* If the gain has no effect, "help" the value to increase */
+            if(temp == (LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]))
+            {
+                temp += 1;
+            }
+            /* Saturate */
+            temp = (temp > LVPSA_MAXUNSIGNEDCHAR) ? LVPSA_MAXUNSIGNEDCHAR : temp;
+            /* Store new max level */
+            pLVPSA_Inst->pPreviousPeaks[ii] =  (LVM_UINT8)(LVPSA_MAXUNSIGNEDCHAR - temp);
+        }
+
+        pPeakValues[ii] = pLVPSA_Inst->pPreviousPeaks[ii];
+    }
+
+    return(LVPSA_OK);
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
new file mode 100755
index 0000000..641357e
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#ifndef _LVPSA_QPD_H_
+#define _LVPSA_QPD_H_
+
+#include "LVM_Types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct
+{
+  LVM_INT32                            *pDelay;        /* pointer to the delayed samples (data of 32 bits)   */
+  LVM_INT32                            Coefs[2];       /* pointer to the filter coefficients */
+}QPD_State_t, *pQPD_State_t;
+
+typedef struct
+{
+    LVM_INT32 KP;    /*should store a0*/
+    LVM_INT32 KM;    /*should store b2*/
+
+} QPD_C32_Coefs, *PQPD_C32_Coefs;
+
+typedef struct
+{
+    LVM_INT32 Storage[1];
+
+} QPD_Taps_t, *pQPD_Taps_t;
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_Process                                           */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Apply downsampling, post gain, quasi peak filtering and write the levels values */
+/*  in the buffer every 20 ms.                                                      */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*                                                                                  */
+/* RETURNS:             void                                                        */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_Process (            void                               *hInstance,
+                                    LVM_INT16                          *pInSamps,
+                                    LVM_INT16                           numSamples,
+                                    LVM_INT16                           BandIndex);
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_Init                                              */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialize a quasi peak filter instance.                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInstance           Pointer to the instance                                     */
+/*   pTaps               Pointer to the filter's taps                               */
+/*   pCoef               Pointer to the filter's coefficients                       */
+/*                                                                                  */
+/* RETURNS:     void                                                                */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_Init (   QPD_State_t       *pInstance,
+                        QPD_Taps_t        *pTaps,
+                        QPD_C32_Coefs     *pCoef     );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
new file mode 100755
index 0000000..37abe40
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#include "LVPSA_QPD.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_Init                                              */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialize a quasi peak filter instance.                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pQPD_State          Pointer to the filter state                                 */
+/*   pTaps               Pointer to the filter's taps                               */
+/*   pCoef               Pointer to the filter's coefficients                       */
+/*                                                                                  */
+/* RETURNS:     void                                                                */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_Init (   pQPD_State_t       pQPD_State,
+                        QPD_Taps_t        *pTaps,
+                        QPD_C32_Coefs     *pCoef     )
+{
+    pQPD_State->pDelay  = pTaps->Storage;
+    pQPD_State->Coefs[0]  = pCoef->KP;
+    pQPD_State->Coefs[1]  = pCoef->KM;
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
new file mode 100755
index 0000000..7087475
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+#include "LVPSA_QPD.h"
+#include "LVPSA_Private.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_WritePeak                                         */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Write a level value in the buffer in the corresponding band.                    */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pInst               Pointer to the LVPSA instance                               */
+/*  ppWrite             Pointer to pointer to the buffer                            */
+/*  CallNumber          Number of the band the value should be written in           */
+/*  Value               Value to write in the buffer                                */
+/*                                                                                  */
+/* RETURNS:             void                                                        */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_WritePeak(   pLVPSA_InstancePr_t       pLVPSA_Inst,
+                            LVM_UINT8             **ppWrite,
+                            LVM_INT16               BandIndex,
+                            LVM_INT16               Value   );
+
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_Process                                           */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Apply downsampling, post gain, quasi peak filtering and write the levels values */
+/*  in the buffer every 20 ms.                                                      */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*                                                                                  */
+/* RETURNS:             void                                                        */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_Process (            void                               *hInstance,
+                                    LVM_INT16                          *pInSamps,
+                                    LVM_INT16                           numSamples,
+                                    LVM_INT16                           BandIndex)
+{
+
+    /******************************************************************************
+       PARAMETERS
+    *******************************************************************************/
+    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+    QPD_State_t *pQPDState =  (QPD_State_t*)&pLVPSA_Inst->pQPD_States[BandIndex];
+
+    /* Pointer to taps */
+    LVM_INT32* pDelay  = pQPDState->pDelay;
+
+    /* Parameters needed during quasi peak calculations */
+    LVM_INT32   X0;
+    LVM_INT32   temp,temp2;
+    LVM_INT32   accu;
+    LVM_INT16   Xg0;
+    LVM_INT16   D0;
+    LVM_INT16   V0 = (LVM_INT16)(*pDelay);
+
+    /* Filter's coef */
+    LVM_INT32   Kp = pQPDState->Coefs[0];
+    LVM_INT32   Km = pQPDState->Coefs[1];
+
+    LVM_INT16   ii = numSamples;
+
+    LVM_UINT8  *pWrite = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+    LVM_INT32   BufferUpdateSamplesCount = pLVPSA_Inst->BufferUpdateSamplesCount;
+    LVM_UINT16  DownSamplingFactor = pLVPSA_Inst->DownSamplingFactor;
+
+    /******************************************************************************
+       INITIALIZATION
+    *******************************************************************************/
+    /* Correct the pointer to take the first down sampled signal sample */
+    pInSamps += pLVPSA_Inst->DownSamplingCount;
+    /* Correct also the number of samples */
+    ii = (LVM_INT16)(ii - (LVM_INT16)pLVPSA_Inst->DownSamplingCount);
+
+    while (ii > 0)
+    {
+        /* Apply post gain */
+        X0 = ((*pInSamps) * pLVPSA_Inst->pPostGains[BandIndex]) >> (LVPSA_GAINSHIFT-1); /* - 1 to compensate scaling in process function*/
+        pInSamps = pInSamps + DownSamplingFactor;
+
+        /* Saturate and take absolute value */
+        if(X0 < 0)
+            X0 = -X0;
+        if (X0 > 0x7FFF)
+            Xg0 = 0x7FFF;
+        else
+            Xg0 = (LVM_INT16)(X0);
+
+
+        /* Quasi peak filter calculation */
+        D0  = (LVM_INT16)(Xg0 - V0);
+
+        temp2 = (LVM_INT32)D0;
+        MUL32x32INTO32(temp2,Kp,accu,31);
+
+        D0    = (LVM_INT16)(D0>>1);
+        if (D0 < 0){
+            D0 = (LVM_INT16)(-D0);
+        }
+
+        temp2 = (LVM_INT32)D0;
+        MUL32x32INTO32((LVM_INT32)D0,Km,temp,31);
+        accu +=temp + Xg0;
+
+        if (accu > 0x7FFF)
+            accu = 0x7FFF;
+        else if(accu < 0)
+            accu = 0x0000;
+
+        V0 = (LVM_INT16)accu;
+
+        if(((pLVPSA_Inst->nSamplesBufferUpdate - BufferUpdateSamplesCount) < DownSamplingFactor))
+        {
+            LVPSA_QPD_WritePeak( pLVPSA_Inst,
+                                &pWrite,
+                                 BandIndex,
+                                 V0);
+            BufferUpdateSamplesCount -= pLVPSA_Inst->nSamplesBufferUpdate;
+            pLVPSA_Inst->LocalSamplesCount = (LVM_UINT16)(numSamples - ii);
+        }
+        BufferUpdateSamplesCount+=DownSamplingFactor;
+
+        ii = (LVM_INT16)(ii-DownSamplingFactor);
+
+    }
+
+    /* Store last taps in memory */
+    *pDelay = (LVM_INT32)(V0);
+
+    /* If this is the last call to the function after last band processing,
+       update the parameters. */
+    if(BandIndex == (pLVPSA_Inst->nRelevantFilters-1))
+    {
+        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+        /* Adjustment for 11025Hz input, 220,5 is normally
+           the exact number of samples for 20ms.*/
+        if((pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite)&&(pLVPSA_Inst->CurrentParams.Fs == LVM_FS_11025))
+        {
+            if(pLVPSA_Inst->nSamplesBufferUpdate == 220)
+            {
+                pLVPSA_Inst->nSamplesBufferUpdate = 221;
+            }
+            else
+            {
+                pLVPSA_Inst->nSamplesBufferUpdate = 220;
+            }
+        }
+        pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+        pLVPSA_Inst->BufferUpdateSamplesCount = BufferUpdateSamplesCount;
+        pLVPSA_Inst->DownSamplingCount = (LVM_UINT16)(-ii);
+    }
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:            LVPSA_QPD_WritePeak                                         */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Write a level value in the spectrum data buffer in the corresponding band.      */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  pLVPSA_Inst               Pointer to the LVPSA instance                         */
+/*  ppWrite             Pointer to pointer to the buffer                            */
+/*  CallNumber          Number of the band the value should be written in           */
+/*  Value               Value to write in the spectrum data buffer                  */
+/*                                                                                  */
+/* RETURNS:             void                                                        */
+/*                                                                                  */
+/************************************************************************************/
+void LVPSA_QPD_WritePeak(   pLVPSA_InstancePr_t       pLVPSA_Inst,
+                            LVM_UINT8             **ppWrite,
+                            LVM_INT16               BandIndex,
+                            LVM_INT16               Value   )
+{
+    LVM_UINT8 *pWrite = *ppWrite;
+
+
+    /* Write the value and update the write pointer */
+    *(pWrite + BandIndex) = (LVM_UINT8)(Value>>7);
+    pWrite += pLVPSA_Inst->nBands;
+    if (pWrite == (pLVPSA_Inst->pSpectralDataBufferStart + pLVPSA_Inst->nBands * pLVPSA_Inst->SpectralDataBufferLength))
+    {
+        pWrite = pLVPSA_Inst->pSpectralDataBufferStart;
+    }
+
+    *ppWrite = pWrite;
+
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
new file mode 100755
index 0000000..f4a35c5
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************/
+/*                                                                      */
+/*     Project::   PSA_01_ARMC_01                                       */
+/*     $Author: beq07716 $*/
+/*     $Revision: 1006 $*/
+/*     $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/*                                                                      */
+/************************************************************************/
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVPSA.h"
+#include "LVPSA_QPD.h"
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rate table                                                               */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT16    LVPSA_SampleRateTab[] = {   8000,                    /* 8kS/s  */
+                                                11025,
+                                                12000,
+                                                16000,
+                                                22050,
+                                                24000,
+                                                32000,
+                                                44100,
+                                                48000};                  /* 48kS/s */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rate inverse table                                                       */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT32    LVPSA_SampleRateInvTab[] = {    268435,                    /* 8kS/s  */
+                                                    194783,
+                                                    178957,
+                                                    134218,
+                                                    97391,
+                                                    89478,
+                                                    67109,
+                                                    48696,
+                                                    44739};                  /* 48kS/s */
+
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Number of samples in 20ms                                                       */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the number of samples
+ * during 20ms
+ */
+const LVM_UINT16    LVPSA_nSamplesBufferUpdate[]  = {   160,                   /* 8kS/s  */
+                                                        220,
+                                                        240,
+                                                        320,
+                                                        441,
+                                                        480,
+                                                        640,
+                                                        882,
+                                                        960};                  /* 48kS/s */
+/************************************************************************************/
+/*                                                                                  */
+/*  Down sampling factors                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the down sampling factor
+ */
+const LVM_UINT16    LVPSA_DownSamplingFactor[]  = {     5,                    /* 8000  S/s  */
+                                                        7,                    /* 11025 S/s  */
+                                                        8,                    /* 12000 S/s  */
+                                                        10,                   /* 16000 S/s  */
+                                                        15,                   /* 22050 S/s  */
+                                                        16,                   /* 24000 S/s  */
+                                                        21,                   /* 32000 S/s  */
+                                                        30,                   /* 44100 S/s  */
+                                                        32};                  /* 48000 S/s  */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Coefficient calculation tables                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+const LVM_INT16     LVPSA_TwoPiOnFsTable[] = {  26354,      /* 8kS/s */
+                                                19123,
+                                                17569,
+                                                13177,
+                                                 9561,
+                                                 8785,
+                                                 6588,
+                                                 4781,
+                                                 4392};    /* 48kS/s */
+
+/*
+ * Gain table
+ */
+const LVM_INT16     LVPSA_GainTable[] = {   364,          /* -15dB gain */
+                                            408,
+                                            458,
+                                            514,
+                                            577,
+                                            647,
+                                            726,
+                                            815,
+                                            914,
+                                            1026,
+                                            1151,
+                                            1292,
+                                            1449,
+                                            1626,
+                                            1825,
+                                            2048,         /* 0dB gain */
+                                            2297,
+                                            2578,
+                                            2892,
+                                            3245,
+                                            3641,
+                                            4096,
+                                            4584,
+                                            5144,
+                                            5772,
+                                            6476,
+                                            7266,
+                                            8153,
+                                            9148,
+                                            10264,
+                                            11576};        /* +15dB gain */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Cosone polynomial coefficients                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ *  Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+const LVM_INT16     LVPSA_CosCoef[] = { 3,                             /* Shifts */
+                                        4096,                          /* a0 */
+                                        -36,                           /* a1 */
+                                        -19725,                        /* a2 */
+                                        -2671,                         /* a3 */
+                                        23730,                         /* a4 */
+                                        -9490};                        /* a5 */
+
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ *  CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+const LVM_INT16     LVPSA_DPCosCoef[] = {   1,                           /* Shifts */
+                                            0,                           /* a0 */
+                                            -6,                          /* a1 */
+                                            16586,                       /* a2 */
+                                            -44};                        /* a3 */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Quasi peak filter coefficients table                                            */
+/*                                                                                  */
+/************************************************************************************/
+const QPD_C32_Coefs     LVPSA_QPD_Coefs[] = {
+
+                                         {0x80CEFD2B,0x00CB9B17},  /* 8kS/s  */    /* LVPSA_SPEED_LOW   */
+                                         {0x80D242E7,0x00CED11D},
+                                         {0x80DCBAF5,0x00D91679},
+                                         {0x80CEFD2B,0x00CB9B17},
+                                         {0x80E13739,0x00DD7CD3},
+                                         {0x80DCBAF5,0x00D91679},
+                                         {0x80D94BAF,0x00D5B7E7},
+                                         {0x80E13739,0x00DD7CD3},
+                                         {0x80DCBAF5,0x00D91679},  /* 48kS/s */
+
+                                         {0x8587513D,0x055C22CF},  /* 8kS/s  */    /* LVPSA_SPEED_MEDIUM      */
+                                         {0x859D2967,0x0570F007},
+                                         {0x85E2EFAC,0x05B34D79},
+                                         {0x8587513D,0x055C22CF},
+                                         {0x8600C7B9,0x05CFA6CF},
+                                         {0x85E2EFAC,0x05B34D79},
+                                         {0x85CC1018,0x059D8F69},
+                                         {0x8600C7B9,0x05CFA6CF},//{0x8600C7B9,0x05CFA6CF},
+                                         {0x85E2EFAC,0x05B34D79},  /* 48kS/s */
+
+                                         {0xA115EA7A,0x1CDB3F5C},  /* 8kS/s  */   /* LVPSA_SPEED_HIGH      */
+                                         {0xA18475F0,0x1D2C83A2},
+                                         {0xA2E1E950,0x1E2A532E},
+                                         {0xA115EA7A,0x1CDB3F5C},
+                                         {0xA375B2C6,0x1E943BBC},
+                                         {0xA2E1E950,0x1E2A532E},
+                                         {0xA26FF6BD,0x1DD81530},
+                                         {0xA375B2C6,0x1E943BBC},
+                                         {0xA2E1E950,0x1E2A532E}}; /* 48kS/s */
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
new file mode 100755
index 0000000..1ab45cc
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/****************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1001 $
+     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Header file for the application layer interface of Concert Sound and Concert        */
+/*  Sound EX.                                                                           */
+/*                                                                                      */
+/*  This files includes all definitions, types, structures and function                 */
+/*  prototypes required by the calling layer. All other types, structures and           */
+/*  functions are private.                                                              */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*  Note: 1                                                                             */
+/*  =======                                                                             */
+/*  The algorithm can execute either with separate input and output buffers or with     */
+/*  a common buffer, i.e. the data is processed in-place. If the buffers are the        */
+/*  same then the MIPs will be slightly higher and an extra stereo scratch buffer is    */
+/*  required.                                                                           */
+/*                                                                                      */
+/****************************************************************************************/
+/*                                                                                      */
+/*  Note: 2                                                                             */
+/*  =======                                                                             */
+/*  Two data formats are support Stereo and Mono-In-Stereo. The data is interleaved as  */
+/*  follows:                                                                            */
+/*              Byte Offset         Stereo Input         Mono-In-Stereo Input           */
+/*              ===========         ============         ====================           */
+/*                  0               Left Sample #1          Mono Sample #1              */
+/*                  2               Right Sample #1         Mono Sample #1              */
+/*                  4               Left Sample #2          Mono Sample #2              */
+/*                  6               Right Sample #2         Mono Sample #2              */
+/*                  .                      .                     .                      */
+/*                  .                      .                     .                      */
+/*                                                                                      */
+/*  Mono format data is not supported, the calling routine must convert a Mono stream   */
+/*  in to Mono-In-Stereo format.                                                        */
+/*                                                                                      */
+/****************************************************************************************/
+
+#ifndef LVCS_H
+#define LVCS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Includes                                                                            */
+/*                                                                                      */
+/****************************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Common.h"
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Definitions                                                                         */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory table */
+#define LVCS_MEMREGION_PERSISTENT_SLOW_DATA    0    /* Offset to the instance memory region */
+#define LVCS_MEMREGION_PERSISTENT_FAST_DATA    1    /* Offset to the persistent data memory region */
+#define LVCS_MEMREGION_PERSISTENT_FAST_COEF    2    /* Offset to the persistent coefficient memory region */
+#define LVCS_MEMREGION_TEMPORARY_FAST          3    /* Offset to temporary memory region */
+#define LVCS_NR_MEMORY_REGIONS                 4    /* Number of memory regions */
+
+/* Effect Level */
+#define LVCS_EFFECT_LOW                    16384    /* Effect scaling 50% */
+#define LVCS_EFFECT_MEDIUM                 24576    /* Effect scaling 75% */
+#define LVCS_EFFECT_HIGH                   32767    /* Effect Scaling 100% */
+
+/* Callback events */
+#define LVCS_EVENT_NONE                   0x0000    /* Not a valid event */
+#define LVCS_EVENT_ALGOFF                 0x0001    /* CS has completed switch off */
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Types                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Instance handle */
+typedef void *LVCS_Handle_t;
+
+
+/* Operating modes */
+typedef enum
+{
+    LVCS_OFF = 0,
+    LVCS_ON  = 15,
+    LVCS_MAX = LVM_MAXENUM
+} LVCS_Modes_en;
+
+
+/* Memory Types */
+typedef enum
+{
+    LVCS_SCRATCH        = 0,
+    LVCS_DATA           = 1,
+    LVCS_COEFFICIENT    = 2,
+    LVCS_PERSISTENT     = 3,
+    LVCS_MEMORYTYPE_MAX = LVM_MAXENUM
+} LVCS_MemoryTypes_en;
+
+
+/* Function return status */
+typedef enum
+{
+    LVCS_SUCCESS        = 0,                        /* Successful return from a routine */
+    LVCS_ALIGNMENTERROR = 1,                        /* Memory alignment error */
+    LVCS_NULLADDRESS    = 2,                        /* NULL allocation address */
+    LVCS_TOOMANYSAMPLES = 3,                        /* Maximum block size exceeded */
+    LVCS_INVALIDBUFFER  = 4,                        /* Invalid buffer processing request */
+    LVCS_STATUSMAX      = LVM_MAXENUM
+} LVCS_ReturnStatus_en;
+
+
+/*
+ * Source data formats
+ */
+typedef enum
+{
+    LVCS_STEREO       = 0,
+    LVCS_MONOINSTEREO = 1,
+    LVCS_SOURCEMAX    = LVM_MAXENUM
+} LVCS_SourceFormat_en;
+
+
+/*
+ * Supported output devices
+ */
+typedef enum
+{
+    LVCS_HEADPHONES             = 0,
+    LVCS_EX_HEADPHONES          = 1,
+    LVCS_SPEAKERTYPE_MAX        = LVM_MAXENUM
+} LVCS_SpeakerType_en;
+
+/*
+ * Speaker Coefficients Table
+ */
+typedef struct
+{
+    void    *pTable1;
+    void    *pTable2;
+    void    *pTable3;
+    void    *pTable4;
+    void    *pTable5;
+    void    *pTable6;
+    void    *pTable7;
+    void    *pTable8;
+} LVCS_CSMS_Coef_Tables_t;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Structures                                                                          */
+/*                                                                                      */
+/****************************************************************************************/
+
+/* Memory region definition */
+typedef struct
+{
+    LVM_UINT32              Size;                   /* Region size in bytes */
+    LVCS_MemoryTypes_en     Type;                   /* Region type */
+    void                    *pBaseAddress;          /* Pointer to the region base address */
+} LVCS_MemoryRegion_t;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+    LVCS_MemoryRegion_t Region[LVCS_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVCS_MemTab_t;
+
+
+/* Concert Sound parameter structure */
+typedef struct
+{
+    LVCS_Modes_en           OperatingMode;          /* Algorithm mode */
+    LVCS_SpeakerType_en     SpeakerType;            /* Output device type */
+    LVCS_SourceFormat_en    SourceFormat;           /* Source data format */
+    LVM_Mode_en             CompressorMode;         /* Non-Linear Compressor Mode */
+    LVM_Fs_en               SampleRate;             /* Sampling rate */
+    LVM_INT16               EffectLevel;            /* Effect level */
+    LVM_UINT16              ReverbLevel;            /* Reverb level in % */
+} LVCS_Params_t;
+
+
+/* Concert Sound Capability structure */
+typedef struct
+{
+    /* General parameters */
+    LVM_UINT16              MaxBlockSize;           /* Maximum block size in sample pairs */
+
+    /* Callback parameters */
+    LVM_Callback            CallBack;               /* Bundle callback */
+    void                    *pBundleInstance;       /* Bundle instance handle */
+
+} LVCS_Capabilities_t;
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Function Prototypes                                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVCS_Memory                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) it is           */
+/*  passed the default capabilities, of these only the buffer processing setting is     */
+/*  used.                                                                               */
+/*                                                                                      */
+/*  When called for memory allocation the memory base address pointers are NULL on      */
+/*  return.                                                                             */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the              */
+/*  capabilities are ignored and the memory table returns the allocated memory and      */
+/*  base addresses used during initialisation.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pCapabilities           Pointer to the default capabilites                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVCS_Success            Succeeded                                                   */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVCS_Process function                   */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Memory(LVCS_Handle_t          hInstance,
+                                 LVCS_MemTab_t          *pMemoryTable,
+                                 LVCS_Capabilities_t    *pCapabilities);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVCS_Init                                                   */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Create and initialisation function for the Concert Sound module                     */
+/*                                                                                      */
+/*  This function can be used to create an algorithm instance by calling with           */
+/*  hInstance set to NULL. In this case the algorithm returns the new instance          */
+/*  handle.                                                                             */
+/*                                                                                      */
+/*  This function can be used to force a full re-initialisation of the algorithm        */
+/*  by calling with hInstance = Instance Handle. In this case the memory table          */
+/*  should be correct for the instance, this can be ensured by calling the function     */
+/*  LVCS_Memory before calling this function.                                           */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pMemoryTable            Pointer to the memory definition table                      */
+/*  pCapabilities           Pointer to the initialisation capabilities                  */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVCS_Success            Initialisation succeeded                                    */
+/*  LVCS_AlignmentError     Instance or scratch memory on incorrect alignment           */
+/*  LVCS_NullAddress        Instance or scratch memory has a NULL pointer               */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  The instance handle is the pointer to the base address of the first memory      */
+/*      region.                                                                         */
+/*  2.  This function must not be interrupted by the LVCS_Process function              */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Init(LVCS_Handle_t            *phInstance,
+                               LVCS_MemTab_t            *pMemoryTable,
+                               LVCS_Capabilities_t      *pCapabilities);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                 LVCS_GetParameters                                         */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Request the Concert Sound parameters. The current parameter set is returned         */
+/*  via the parameter pointer.                                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance                Instance handle                                            */
+/*  pParams                  Pointer to an empty parameter structure                    */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVCS_Success             Always succeeds                                            */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVCS_Process function                   */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_GetParameters(LVCS_Handle_t   hInstance,
+                                        LVCS_Params_t   *pParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVCS_Control                                                */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Sets or changes the Concert Sound parameters.                                       */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pParams                 Pointer to a parameter structure                            */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVCS_Success            Succeeded                                                   */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function must not be interrupted by the LVCS_Process function              */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Control(LVCS_Handle_t     hInstance,
+                                  LVCS_Params_t     *pParams);
+
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVCS_Process                                                */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  Process function for the Concert Sound module. The implementation supports two      */
+/*  variants of the algorithm, one for headphones and one for mobile speakers.          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance handle                                             */
+/*  pInData                 Pointer to the input data                                   */
+/*  pOutData                Pointer to the output data                                  */
+/*  NumSamples              Number of samples in the input buffer                       */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVCS_Success            Succeeded                                                   */
+/*  LVCS_TooManySamples     NumSamples was larger than the maximum block size           */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
+                                  const LVM_INT16           *pInData,
+                                  LVM_INT16                 *pOutData,
+                                  LVM_UINT16                NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* LVCS_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
new file mode 100755
index 0000000..b1d9408
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq06068 $
+     $Revision: 1307 $
+     $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_BypassMix.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/*  Function Prototypes                                                                 */
+/*                                                                                      */
+/****************************************************************************************/
+LVM_INT32 LVCS_MixerCallback(   LVCS_Handle_t   hInstance,
+                                void            *pGeneralPurpose,
+                                LVM_INT16       CallbackParam);
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_BypassMixInit                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialises the bypass mixer module                                             */
+/*                                                                                  */
+/*  The overall gain of the processed path is set by the gains in the individual    */
+/*  processing blocks and by the effect level gain.                                 */
+/*                                                                                  */
+/*  The unprocessed path must have matching gain for the processed path to ensure   */
+/*  as they are mixed together the correct effect is achieved, this is the value    */
+/*  UnprocLoss.                                                                     */
+/*                                                                                  */
+/*  The overall gain is corrected by a combination of a shift with saturation and a */
+/*  linear scaler, loss. The loss ensures the sum in the mixer does not saturate    */
+/*  and also corrects for any excess gain in the shift.                             */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pParams                 Initialisation parameters                               */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams)
+{
+
+    LVM_UINT16          Offset;
+    LVM_UINT32          Gain;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_BypassMix_t    *pConfig   = (LVCS_BypassMix_t *)&pInstance->BypassMix;
+    const Gain_t        *pOutputGainTable;
+    LVM_INT32           Current;
+
+
+    /*
+     * Set the transition gain
+     */
+    if ((pParams->OperatingMode == LVCS_ON) &&
+        (pInstance->bTimerDone == LVM_TRUE)
+        && (pInstance->MSTarget1 != 0x7FFF) /* this indicates an off->on transtion */
+        )
+    {
+        pInstance->TransitionGain = pParams->EffectLevel;
+    }
+    else
+    {
+        /* Select no effect level */
+        pInstance->TransitionGain = 0;
+    }
+
+    /*
+     * Calculate the output gain table offset
+     */
+    Offset = (LVM_UINT16)(pParams->SpeakerType + (pParams->SourceFormat*(1+LVCS_EX_HEADPHONES)));
+    pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
+
+    /*
+     * Setup the mixer gain for the processed path
+     */
+    Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * pInstance->TransitionGain);
+
+    pConfig->Mixer_Instance.MixerStream[0].CallbackParam = 0;
+    pConfig->Mixer_Instance.MixerStream[0].pCallbackHandle = LVM_NULL;
+    pConfig->Mixer_Instance.MixerStream[0].pCallBack = LVM_NULL;
+    pConfig->Mixer_Instance.MixerStream[0].CallbackSet=1;
+    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[0]);
+    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[0],(LVM_INT32)(Gain >> 15),Current);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+    /*
+     * Setup the mixer gain for the unprocessed path
+     */
+    Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * (0x7FFF - pInstance->TransitionGain));
+    Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
+    Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[1]);
+    LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[1],(LVM_INT32)(Gain >> 15),Current);
+    LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+    pConfig->Mixer_Instance.MixerStream[1].CallbackParam = 0;
+    pConfig->Mixer_Instance.MixerStream[1].pCallbackHandle = hInstance;
+    pConfig->Mixer_Instance.MixerStream[1].CallbackSet=1;
+    pConfig->Mixer_Instance.MixerStream[1].pCallBack = LVCS_MixerCallback;
+
+    /*
+     * Setup the output gain shift
+     */
+    pConfig->Output_Shift = pOutputGainTable[Offset].Shift;
+
+
+    /*
+     * Correct gain for the effect level
+     */
+    {
+
+        LVM_INT16           GainCorrect;
+        LVM_INT32           Gain1;
+        LVM_INT32           Gain2;
+
+        Gain1 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[0]);
+        Gain2 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[1]);
+        /*
+         * Calculate the gain correction
+         */
+        if (pInstance->Params.CompressorMode == LVM_MODE_ON)
+        {
+        GainCorrect = (LVM_INT16)(  pInstance->VolCorrect.GainMin
+                                    - (((LVM_INT32)pInstance->VolCorrect.GainMin * (LVM_INT32)pInstance->TransitionGain) >> 15)
+                                    + (((LVM_INT32)pInstance->VolCorrect.GainFull * (LVM_INT32)pInstance->TransitionGain) >> 15) );
+
+        /*
+         * Apply the gain correction and shift, note the result is in Q3.13 format
+         */
+        Gain1 = (Gain1 * GainCorrect) << 4;
+        Gain2 = (Gain2 * GainCorrect) << 4;
+        }
+        else
+        {
+            Gain1 = Gain1 << 16;
+            Gain2 = Gain2 << 16;
+        }
+
+
+
+        /*
+         * Set the gain values
+         */
+        pConfig->Output_Shift = pConfig->Output_Shift;
+        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[0],Gain1>>16);
+        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+        LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[1],Gain2>>16);
+        LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+    }
+
+    return(LVCS_SUCCESS);
+
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_BypassMixer                                        */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Apply Bypass Mix.                                                               */
+/*                                                                                  */
+/*  This mixes the processed and unprocessed data streams together to correct the   */
+/*  overall system gain and allow progressive control of the Concert Sound effect.  */
+/*                                                                                  */
+/*  When the bypass mixer is enabled the output is the processed signal only and    */
+/*  without gain correction.                                                        */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pProcessed              Pointer to the processed data                           */
+/*  pUnprocessed            Pointer to the unprocessed data                         */
+/*  pOutData                Pointer to the output data                              */
+/*  NumSamples              Number of samples to process                            */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
+                                      const LVM_INT16       *pProcessed,
+                                      const LVM_INT16       *pUnprocessed,
+                                      LVM_INT16             *pOutData,
+                                      LVM_UINT16            NumSamples)
+{
+
+    LVCS_Instance_t     *pInstance      = (LVCS_Instance_t  *)hInstance;
+    LVCS_BypassMix_t    *pConfig        = (LVCS_BypassMix_t *)&pInstance->BypassMix;
+
+    /*
+     * Check if the bypass mixer is enabled
+     */
+    if ((pInstance->Params.OperatingMode & LVCS_BYPASSMIXSWITCH) != 0)
+    {
+        /*
+         * Apply the bypass mix
+         */
+        LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance,
+                                        pProcessed,
+                                        (LVM_INT16 *) pUnprocessed,
+                                        pOutData,
+                                        (LVM_INT16)(2*NumSamples));
+
+        /*
+         * Apply output gain correction shift
+         */
+        Shift_Sat_v16xv16 ((LVM_INT16)pConfig->Output_Shift,
+                          (LVM_INT16*)pOutData,
+                          (LVM_INT16*)pOutData,
+                          (LVM_INT16)(2*NumSamples));          /* Left and right*/
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_MixerCallback                                      */
+/*                                                                                  */
+/************************************************************************************/
+LVM_INT32 LVCS_MixerCallback(LVCS_Handle_t      hInstance,
+                            void                *pGeneralPurpose,
+                            LVM_INT16           CallbackParam)
+{
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+
+   (void)pGeneralPurpose;
+
+    /*
+     * Off transition has completed in Headphone mode
+     */
+    if ((pInstance->OutputDevice == LVCS_HEADPHONE) &&
+        (pInstance->bInOperatingModeTransition)     &&
+        (pInstance->MSTarget0 == 0x0000)&&  /* this indicates an on->off transition */
+        (CallbackParam == 0))
+    {
+        /* Set operating mode to OFF */
+        pInstance->Params.OperatingMode = LVCS_OFF;
+
+        /* Exit transition state */
+        pInstance->bInOperatingModeTransition = LVM_FALSE;
+
+        /* Signal to the bundle */
+        if((*pInstance->Capabilities.CallBack) != LVM_NULL){
+            (*pInstance->Capabilities.CallBack)(pInstance->Capabilities.pBundleInstance,
+                                                LVM_NULL,
+                                                (ALGORITHM_CS_ID | LVCS_EVENT_ALGOFF));
+        }
+    }
+
+
+    if ((pInstance->OutputDevice == LVCS_HEADPHONE)  &&
+        (pInstance->MSTarget0 == 1) &&
+        (pInstance->bTimerDone == LVM_TRUE)){
+
+        /* Exit transition state */
+        pInstance->bInOperatingModeTransition = LVM_FALSE;
+    }
+
+    return 1;
+}
+
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
new file mode 100755
index 0000000..79dff41
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1001 $
+     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVCS_BYPASSMIX_H__
+#define __LVCS_BYPASSMIX_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVC_Mixer.h"
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Structures                                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Bypass mixer structure */
+typedef struct
+{
+    /* Mixer settings */
+    LVMixer3_2St_st         Mixer_Instance;             /* Mixer instance */
+    LVM_UINT16              Output_Shift;               /* Correcting gain output shift */
+
+} LVCS_BypassMix_t;
+
+
+/* Output gain type */
+typedef struct
+{
+    /* Output gain settings, Gain = (Loss/32768) * 2^Shift */
+    LVM_UINT16              Shift;                      /* Left shifts required */
+    LVM_UINT16              Loss;                       /* Loss required */
+    LVM_UINT16              UnprocLoss;                 /* Unprocessed path loss */
+} Gain_t;
+
+
+/************************************************************************************/
+/*                                                                                    */
+/*    Function prototypes                                                                */
+/*                                                                                    */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t       hInstance,
+                                           LVCS_Params_t    *pParams);
+
+
+LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t         hInstance,
+                                      const LVM_INT16       *pProcessed,
+                                      const LVM_INT16       *unProcessed,
+                                            LVM_INT16       *pOutData,
+                                            LVM_UINT16      NumSamples);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* BYPASSMIX_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
new file mode 100755
index 0000000..fea44bf
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq06068 $
+     $Revision: 1307 $
+     $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                 LVCS_GetParameters                                     */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Request the Concert Sound parameters. The current parameter set is returned     */
+/*  via the parameter pointer.                                                      */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance                Instance handle                                        */
+/*  pParams                  Pointer to an empty parameter structure                */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success             Always succeeds                                        */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  This function may be interrupted by the LVCS_Process function               */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_GetParameters(LVCS_Handle_t   hInstance,
+                                        LVCS_Params_t   *pParams)
+{
+
+    LVCS_Instance_t     *pInstance =(LVCS_Instance_t  *)hInstance;
+
+    *pParams = pInstance->Params;
+
+    return(LVCS_SUCCESS);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Control                                            */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Sets or changes the Concert Sound parameters.                                   */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance handle                                         */
+/*  pParams                 Pointer to a parameter structure                        */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Succeeded                                               */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  This function must not be interrupted by the LVCS_Process function          */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Control(LVCS_Handle_t      hInstance,
+                                  LVCS_Params_t      *pParams)
+{
+    LVM_INT16                   Offset;
+    LVCS_Instance_t             *pInstance =(LVCS_Instance_t  *)hInstance;
+    LVCS_ReturnStatus_en        err;
+    LVCS_Modes_en               OperatingModeSave = pInstance->Params.OperatingMode;
+
+    if (pParams->SampleRate != pInstance->Params.SampleRate)
+    {
+        pInstance->TimerParams.SamplingRate = LVCS_SampleRateTable[pParams->SampleRate];
+    }
+
+    /*
+     * If the reverb level has changed
+     */
+    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
+    {
+        err=LVCS_ReverbGeneratorInit(hInstance,pParams);
+    }
+
+    /*
+     * If the sample rate or speaker has changed then perform a full re-initialisation
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+       (pInstance->Params.SpeakerType != pParams->SpeakerType))
+    {
+        const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
+
+        /*
+         * Output device
+         */
+        pInstance->OutputDevice = LVCS_HEADPHONE;
+
+        /*
+         * Get the volume correction parameters
+         */
+        /* Use internal coefficient table */
+        pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+        Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
+
+        pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
+
+        LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
+
+
+        {
+            LVM_UINT32          Gain;
+            const Gain_t        *pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
+            Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * LVM_MAXINT_16);
+            Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
+            Gain=Gain>>15;
+            /*
+             * Apply the gain correction and shift, note the result is in Q3.13 format
+             */
+            Gain = (Gain * pInstance->VolCorrect.GainMin) >>12;
+
+            LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],0,Gain);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],
+                    LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+            LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],
+                    LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+
+        }
+
+
+        err=LVCS_SEnhancerInit(hInstance,
+                           pParams);
+
+        err=LVCS_ReverbGeneratorInit(hInstance,
+                                 pParams);
+
+        err=LVCS_EqualiserInit(hInstance,
+                           pParams);
+
+        err=LVCS_BypassMixInit(hInstance,
+                           pParams);
+
+    }
+
+
+    /*
+     * Check if the effect level or source format has changed
+     */
+    else if ((pInstance->Params.EffectLevel != pParams->EffectLevel) ||
+            (pInstance->Params.SourceFormat != pParams->SourceFormat))
+    {
+        const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
+
+        /*
+         * Get the volume correction parameters
+         */
+        /* Use internal coefficient table */
+        pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+        Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
+
+        pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
+
+        /* Update the effect level and alpha-mixer gains */
+        err=LVCS_BypassMixInit(hInstance,
+                           pParams);
+
+        if(err != LVCS_SUCCESS)
+        {
+            return err;
+        }
+    }
+    else
+    {
+        pInstance->Params = *pParams;
+    }
+
+    /*
+     * Update the instance parameters
+     */
+    pInstance->Params = *pParams;
+
+    /* Stay on the current operating mode until the transition is done */
+    if((pParams->OperatingMode != OperatingModeSave) ||
+       (pInstance->bInOperatingModeTransition == LVM_TRUE)){
+
+        /* Set the reverb delay timeout */
+        if(pInstance->bInOperatingModeTransition != LVM_TRUE){
+            pInstance->bTimerDone = LVM_FALSE;
+            pInstance->TimerParams.TimeInMs = (LVM_INT16)(((pInstance->Reverberation.DelaySize << 2)/pInstance->TimerParams.SamplingRate) + 1);
+            LVM_Timer_Init ( &pInstance->TimerInstance,
+                             &pInstance->TimerParams);
+        }
+
+        /* Update the effect level and alpha-mixer gains */
+        err=LVCS_BypassMixInit(hInstance,
+                           pParams);
+
+        /* Change transition bypass mixer settings if needed depending on transition type */
+        if(pParams->OperatingMode != LVCS_OFF){
+            pInstance->MSTarget0=LVM_MAXINT_16;
+            pInstance->MSTarget1=0;
+        }
+        else
+        {
+            pInstance->Params.OperatingMode = OperatingModeSave;
+            pInstance->MSTarget1=LVM_MAXINT_16;
+            pInstance->MSTarget0=0;
+        }
+
+
+        /* Set transition flag */
+        pInstance->bInOperatingModeTransition = LVM_TRUE;
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVCS_TimerCallBack                                          */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  CallBack function of the Timer.                                                     */
+/*                                                                                      */
+/****************************************************************************************/
+void LVCS_TimerCallBack (void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam)
+{
+    LVCS_Instance_t     *pInstance  = (LVCS_Instance_t  *)hInstance;
+
+    /* Avoid warnings because pCallBackParams and CallbackParam are not used*/
+    if((pCallBackParams != LVM_NULL) || (CallbackParam != 0)){
+        pCallBackParams = hInstance;
+        CallbackParam = 0;
+        return;
+    }
+
+    pInstance->bTimerDone = LVM_TRUE;
+
+
+    return;
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
new file mode 100755
index 0000000..7ab6571
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1315 $
+     $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Equaliser.h"
+#include "BIQUAD.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_EqualiserInit                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialises the equaliser module                                                */
+/*                                                                                  */
+/*  The function selects the coefficients for the filters and clears the data       */
+/*  history. It is also used for re-initialisation when one of the system control   */
+/*  parameters changes but will only change the coefficients and clear the history  */
+/*  if the sample rate or speaker type has changed.                                 */
+/*                                                                                  */
+/*  To avoid excessive testing during the sample processing the biquad type is      */
+/*  set as a callback function in the init routine.                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pParams                 Initialisation parameters                               */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams)
+{
+
+    LVM_UINT16          Offset;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t *)&pInstance->Equaliser;
+    LVCS_Data_t         *pData     = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+    LVCS_Coefficient_t  *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+    BQ_C16_Coefs_t      Coeffs;
+    const BiquadA012B12CoefsSP_t *pEqualiserCoefTable;
+
+    /*
+     * If the sample rate changes re-initialise the filters
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.SpeakerType != pParams->SpeakerType))
+    {
+        /*
+         * Setup the filter coefficients and clear the history
+         */
+        Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1+LVM_FS_48000)));
+        pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
+
+        /* Left and right filters */
+        /* Convert incoming coefficients to the required format/ordering */
+        Coeffs.A0 = (LVM_INT16) pEqualiserCoefTable[Offset].A0;
+        Coeffs.A1 = (LVM_INT16) pEqualiserCoefTable[Offset].A1;
+        Coeffs.A2 = (LVM_INT16) pEqualiserCoefTable[Offset].A2;
+        Coeffs.B1 = (LVM_INT16)-pEqualiserCoefTable[Offset].B1;
+        Coeffs.B2 = (LVM_INT16)-pEqualiserCoefTable[Offset].B2;
+
+        LoadConst_16((LVM_INT16)0,                                                       /* Value */
+                     (void *)&pData->EqualiserBiquadTaps,   /* Destination Cast to void:\
+                                                               no dereferencing in function*/
+                     (LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps)/sizeof(LVM_INT16)));    /* Number of words */
+
+        BQ_2I_D16F32Css_TRC_WRA_01_Init(&pCoefficients->EqualiserBiquadInstance,
+                                        &pData->EqualiserBiquadTaps,
+                                        &Coeffs);
+
+        /* Callbacks */
+        switch(pEqualiserCoefTable[Offset].Scale)
+        {
+            case 13:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C13_TRC_WRA_01;
+                break;
+            case 14:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C14_TRC_WRA_01;
+                break;
+            case 15:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F32C15_TRC_WRA_01;
+                break;
+        }
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Equaliser                                          */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Apply the equaliser filter.                                                     */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pInputOutput            Pointer to the input/output buffer                      */
+/*  NumSamples              The number of samples to process                        */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  Always processes in place.                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t       hInstance,
+                                    LVM_INT16           *pInputOutput,
+                                    LVM_UINT16          NumSamples)
+{
+
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_Equaliser_t    *pConfig   = (LVCS_Equaliser_t  *)&pInstance->Equaliser;
+    LVCS_Coefficient_t  *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+
+    /*
+     * Check if the equaliser is required
+     */
+    if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0)
+    {
+        /* Apply filter to the left and right channels */
+        (pConfig->pBiquadCallBack)((Biquad_Instance_t*)&pCoefficients->EqualiserBiquadInstance,
+                                   (LVM_INT16 *)pInputOutput,
+                                   (LVM_INT16 *)pInputOutput,
+                                   (LVM_INT16)NumSamples);
+    }
+
+    return(LVCS_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
new file mode 100755
index 0000000..10b02cc
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1001 $
+     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVCS_EQUALISER_H__
+#define __LVCS_EQUALISER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Structures                                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Equaliser structure */
+typedef struct
+{
+    void (*pBiquadCallBack) (Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+
+} LVCS_Equaliser_t;
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Function prototypes                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams);
+
+LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t            hInstance,
+                                    LVM_INT16                *pInputOutput,
+                                    LVM_UINT16                NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* EQUALISER_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
new file mode 100755
index 0000000..1d55281
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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 __LVCS_HEADPHONE_COEFFS_H__
+#define __LVCS_HEADPHONE_COEFFS_H__
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* The Stereo Enhancer                                                              */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Stereo Enhancer coefficients for 8000 Hz sample rate, scaled with 0.161258 */
+#define CS_MIDDLE_8000_A0                          7462         /* Floating point value 0.227720 */
+#define CS_MIDDLE_8000_A1                         -7049         /* Floating point value -0.215125 */
+#define CS_MIDDLE_8000_A2                             0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_8000_B1                        -30209         /* Floating point value -0.921899 */
+#define CS_MIDDLE_8000_B2                             0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_8000_SCALE                         15
+#define CS_SIDE_8000_A0                           20036         /* Floating point value 0.611441 */
+#define CS_SIDE_8000_A1                          -12463         /* Floating point value -0.380344 */
+#define CS_SIDE_8000_A2                           -7573         /* Floating point value -0.231097 */
+#define CS_SIDE_8000_B1                          -20397         /* Floating point value -0.622470 */
+#define CS_SIDE_8000_B2                           -4285         /* Floating point value -0.130759 */
+#define CS_SIDE_8000_SCALE                           15
+
+/* Stereo Enhancer coefficients for 11025Hz sample rate, scaled with 0.162943 */
+#define CS_MIDDLE_11025_A0                         7564         /* Floating point value 0.230838 */
+#define CS_MIDDLE_11025_A1                        -7260         /* Floating point value -0.221559 */
+#define CS_MIDDLE_11025_A2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_11025_B1                       -30902         /* Floating point value -0.943056 */
+#define CS_MIDDLE_11025_B2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_11025_SCALE                        15
+#define CS_SIDE_11025_A0                          18264         /* Floating point value 0.557372 */
+#define CS_SIDE_11025_A1                         -12828         /* Floating point value -0.391490 */
+#define CS_SIDE_11025_A2                          -5436         /* Floating point value -0.165881 */
+#define CS_SIDE_11025_B1                         -28856         /* Floating point value -0.880608 */
+#define CS_SIDE_11025_B2                           1062         /* Floating point value 0.032397 */
+#define CS_SIDE_11025_SCALE                          15
+
+/* Stereo Enhancer coefficients for 12000Hz sample rate, scaled with 0.162191 */
+#define CS_MIDDLE_12000_A0                         7534         /* Floating point value 0.229932 */
+#define CS_MIDDLE_12000_A1                        -7256         /* Floating point value -0.221436 */
+#define CS_MIDDLE_12000_A2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_12000_B1                       -31051         /* Floating point value -0.947616 */
+#define CS_MIDDLE_12000_B2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_12000_SCALE                        15
+#define CS_SIDE_12000_A0                          18298         /* Floating point value 0.558398 */
+#define CS_SIDE_12000_A1                         -12852         /* Floating point value -0.392211 */
+#define CS_SIDE_12000_A2                          -5446         /* Floating point value -0.166187 */
+#define CS_SIDE_12000_B1                         -29247         /* Floating point value -0.892550 */
+#define CS_SIDE_12000_B2                           1077         /* Floating point value 0.032856 */
+#define CS_SIDE_12000_SCALE                          15
+
+/* Stereo Enhancer coefficients for 16000Hz sample rate, scaled with 0.162371 */
+#define CS_MIDDLE_16000_A0                         7558         /* Floating point value 0.230638 */
+#define CS_MIDDLE_16000_A1                        -7348         /* Floating point value -0.224232 */
+#define CS_MIDDLE_16000_A2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_16000_B1                       -31475         /* Floating point value -0.960550 */
+#define CS_MIDDLE_16000_B2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_16000_SCALE                        15
+#define CS_SIDE_16000_A0                           8187         /* Floating point value 0.499695 */
+#define CS_SIDE_16000_A1                          -5825         /* Floating point value -0.355543 */
+#define CS_SIDE_16000_A2                          -2362         /* Floating point value -0.144152 */
+#define CS_SIDE_16000_B1                         -17216         /* Floating point value -1.050788 */
+#define CS_SIDE_16000_B2                           2361         /* Floating point value 0.144104 */
+#define CS_SIDE_16000_SCALE                          14
+
+/* Stereo Enhancer coefficients for 22050Hz sample rate, scaled with 0.160781 */
+#define CS_MIDDLE_22050_A0                         7496         /* Floating point value 0.228749 */
+#define CS_MIDDLE_22050_A1                        -7344         /* Floating point value -0.224128 */
+#define CS_MIDDLE_22050_A2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_22050_B1                       -31826         /* Floating point value -0.971262 */
+#define CS_MIDDLE_22050_B2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_22050_SCALE                        15
+#define CS_SIDE_22050_A0                           7211         /* Floating point value 0.440112 */
+#define CS_SIDE_22050_A1                          -4278         /* Floating point value -0.261096 */
+#define CS_SIDE_22050_A2                          -2933         /* Floating point value -0.179016 */
+#define CS_SIDE_22050_B1                         -18297         /* Floating point value -1.116786 */
+#define CS_SIDE_22050_B2                           2990         /* Floating point value 0.182507 */
+#define CS_SIDE_22050_SCALE                          14
+
+/* Stereo Enhancer coefficients for 24000Hz sample rate, scaled with 0.161882 */
+#define CS_MIDDLE_24000_A0                         7550         /* Floating point value 0.230395 */
+#define CS_MIDDLE_24000_A1                        -7409         /* Floating point value -0.226117 */
+#define CS_MIDDLE_24000_A2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_24000_B1                       -31902         /* Floating point value -0.973573 */
+#define CS_MIDDLE_24000_B2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_24000_SCALE                        15
+#define CS_SIDE_24000_A0                           6796         /* Floating point value 0.414770 */
+#define CS_SIDE_24000_A1                          -4705         /* Floating point value -0.287182 */
+#define CS_SIDE_24000_A2                          -2090         /* Floating point value -0.127588 */
+#define CS_SIDE_24000_B1                         -20147         /* Floating point value -1.229648 */
+#define CS_SIDE_24000_B2                           4623         /* Floating point value 0.282177 */
+#define CS_SIDE_24000_SCALE                          14
+
+/* Stereo Enhancer coefficients for 32000Hz sample rate, scaled with 0.160322 */
+#define CS_MIDDLE_32000_A0                         7484         /* Floating point value 0.228400 */
+#define CS_MIDDLE_32000_A1                        -7380         /* Floating point value -0.225214 */
+#define CS_MIDDLE_32000_A2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_32000_B1                       -32117         /* Floating point value -0.980126 */
+#define CS_MIDDLE_32000_B2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_32000_SCALE                        15
+#define CS_SIDE_32000_A0                           5973         /* Floating point value 0.364579 */
+#define CS_SIDE_32000_A1                          -3397         /* Floating point value -0.207355 */
+#define CS_SIDE_32000_A2                          -2576         /* Floating point value -0.157224 */
+#define CS_SIDE_32000_B1                         -20877         /* Floating point value -1.274231 */
+#define CS_SIDE_32000_B2                           5120         /* Floating point value 0.312495 */
+#define CS_SIDE_32000_SCALE                          14
+
+/* Stereo Enhancer coefficients for 44100Hz sample rate, scaled with 0.163834 */
+#define CS_MIDDLE_44100_A0                         7654         /* Floating point value 0.233593 */
+#define CS_MIDDLE_44100_A1                        -7577         /* Floating point value -0.231225 */
+#define CS_MIDDLE_44100_A2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_44100_B1                       -32294         /* Floating point value -0.985545 */
+#define CS_MIDDLE_44100_B2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_44100_SCALE                        15
+#define CS_SIDE_44100_A0                           4662         /* Floating point value 0.284573 */
+#define CS_SIDE_44100_A1                          -4242         /* Floating point value -0.258910 */
+#define CS_SIDE_44100_A2                           -420         /* Floating point value -0.025662 */
+#define CS_SIDE_44100_B1                         -25760         /* Floating point value -1.572248 */
+#define CS_SIDE_44100_B2                           9640         /* Floating point value 0.588399 */
+#define CS_SIDE_44100_SCALE                          14
+
+/* Stereo Enhancer coefficients for 48000Hz sample rate, scaled with 0.164402 */
+#define CS_MIDDLE_48000_A0                         7682         /* Floating point value 0.234445 */
+#define CS_MIDDLE_48000_A1                        -7611         /* Floating point value -0.232261 */
+#define CS_MIDDLE_48000_A2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_48000_B1                       -32333         /* Floating point value -0.986713 */
+#define CS_MIDDLE_48000_B2                            0         /* Floating point value 0.000000 */
+#define CS_MIDDLE_48000_SCALE                        15
+#define CS_SIDE_48000_A0                           4466         /* Floating point value 0.272606 */
+#define CS_SIDE_48000_A1                          -4374         /* Floating point value -0.266952 */
+#define CS_SIDE_48000_A2                            -93         /* Floating point value -0.005654 */
+#define CS_SIDE_48000_B1                         -26495         /* Floating point value -1.617141 */
+#define CS_SIDE_48000_B2                          10329         /* Floating point value 0.630405 */
+#define CS_SIDE_48000_SCALE                          14
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* The Reverb Unit                                                                  */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Reverb delay settings in samples */
+#define LVCS_STEREODELAY_CS_8KHZ                     93         /* Sample rate 8kS/s */
+#define LVCS_STEREODELAY_CS_11KHZ                   128         /* Sample rate 11kS/s */
+#define LVCS_STEREODELAY_CS_12KHZ                   139         /* Sample rate 12kS/s */
+#define LVCS_STEREODELAY_CS_16KHZ                   186         /* Sample rate 16kS/s */
+#define LVCS_STEREODELAY_CS_22KHZ                   256         /* Sample rate 22kS/s */
+#define LVCS_STEREODELAY_CS_24KHZ                   279         /* Sample rate 24kS/s */
+#define LVCS_STEREODELAY_CS_32KHZ                   372         /* Sample rate 32kS/s */
+#define LVCS_STEREODELAY_CS_44KHZ                   512         /* Sample rate 44kS/s */
+#define LVCS_STEREODELAY_CS_48KHZ                   512         /* Sample rate 48kS/s */
+
+/* Reverb coefficients for 8000 Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_8000_A0                         21865         /* Floating point value 0.667271 */
+#define CS_REVERB_8000_A1                        -21865         /* Floating point value -0.667271 */
+#define CS_REVERB_8000_A2                             0         /* Floating point value 0.000000 */
+#define CS_REVERB_8000_B1                        -21895         /* Floating point value -0.668179 */
+#define CS_REVERB_8000_B2                             0         /* Floating point value 0.000000 */
+#define CS_REVERB_8000_SCALE                         15
+
+/* Reverb coefficients for 11025Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_11025_A0                        22926         /* Floating point value 0.699638 */
+#define CS_REVERB_11025_A1                       -22926         /* Floating point value -0.699638 */
+#define CS_REVERB_11025_A2                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_11025_B1                       -24546         /* Floating point value -0.749096 */
+#define CS_REVERB_11025_B2                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_11025_SCALE                        15
+
+/* Reverb coefficients for 12000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_12000_A0                        23165         /* Floating point value 0.706931 */
+#define CS_REVERB_12000_A1                       -23165         /* Floating point value -0.706931 */
+#define CS_REVERB_12000_A2                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_12000_B1                       -25144         /* Floating point value -0.767327 */
+#define CS_REVERB_12000_B2                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_12000_SCALE                        15
+
+/* Reverb coefficients for 16000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_16000_A0                        23864         /* Floating point value 0.728272 */
+#define CS_REVERB_16000_A1                       -23864         /* Floating point value -0.728272 */
+#define CS_REVERB_16000_A2                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_16000_B1                       -26892         /* Floating point value -0.820679 */
+#define CS_REVERB_16000_B2                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_16000_SCALE                        15
+
+/* Reverb coefficients for 22050Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_22050_A0                        16921         /* Floating point value 0.516396 */
+#define CS_REVERB_22050_A1                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_22050_A2                       -16921         /* Floating point value -0.516396 */
+#define CS_REVERB_22050_B1                       -16991         /* Floating point value -0.518512 */
+#define CS_REVERB_22050_B2                        -9535         /* Floating point value -0.290990 */
+#define CS_REVERB_22050_SCALE                        15
+
+/* Reverb coefficients for 24000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_24000_A0                        15714         /* Floating point value 0.479565 */
+#define CS_REVERB_24000_A1                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_24000_A2                       -15714         /* Floating point value -0.479565 */
+#define CS_REVERB_24000_B1                       -20898         /* Floating point value -0.637745 */
+#define CS_REVERB_24000_B2                        -6518         /* Floating point value -0.198912 */
+#define CS_REVERB_24000_SCALE                        15
+
+/* Reverb coefficients for 32000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_32000_A0                        12463         /* Floating point value 0.380349 */
+#define CS_REVERB_32000_A1                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_32000_A2                       -12463         /* Floating point value -0.380349 */
+#define CS_REVERB_32000_B1                       -31158         /* Floating point value -0.950873 */
+#define CS_REVERB_32000_B2                         1610         /* Floating point value 0.049127 */
+#define CS_REVERB_32000_SCALE                        15
+
+/* Reverb coefficients for 44100Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_44100_A0                         4872         /* Floating point value 0.297389 */
+#define CS_REVERB_44100_A1                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_44100_A2                        -4872         /* Floating point value -0.297389 */
+#define CS_REVERB_44100_B1                       -19668         /* Floating point value -1.200423 */
+#define CS_REVERB_44100_B2                         4203         /* Floating point value 0.256529 */
+#define CS_REVERB_44100_SCALE                        14
+
+/* Reverb coefficients for 48000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_48000_A0                         4566         /* Floating point value 0.278661 */
+#define CS_REVERB_48000_A1                            0         /* Floating point value 0.000000 */
+#define CS_REVERB_48000_A2                        -4566         /* Floating point value -0.278661 */
+#define CS_REVERB_48000_B1                       -20562         /* Floating point value -1.254993 */
+#define CS_REVERB_48000_B2                         4970         /* Floating point value 0.303347 */
+#define CS_REVERB_48000_SCALE                        14
+
+/* Reverb Gain Settings */
+#define LVCS_HEADPHONE_DELAYGAIN               0.800000         /* Algorithm delay path gain */
+#define LVCS_HEADPHONE_OUTPUTGAIN              1.000000         /* Algorithm output gain */
+#define LVCS_HEADPHONE_PROCGAIN                   18403         /* Processed path gain */
+#define LVCS_HEADPHONE_UNPROCGAIN                 18403         /* Unprocessed path gain */
+#define LVCS_HEADPHONE_GAINCORRECT             1.009343         /* Delay mixer gain correction */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* The Equaliser                                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Equaliser coefficients for 8000 Hz sample rate, CS scaled with 1.038497 and CSEX scaled with 0.775480 */
+#define CS_EQUALISER_8000_A0                      20698         /* Floating point value 1.263312 */
+#define CS_EQUALISER_8000_A1                      -9859         /* Floating point value -0.601748 */
+#define CS_EQUALISER_8000_A2                      -4599         /* Floating point value -0.280681 */
+#define CS_EQUALISER_8000_B1                      -7797         /* Floating point value -0.475865 */
+#define CS_EQUALISER_8000_B2                      -6687         /* Floating point value -0.408154 */
+#define CS_EQUALISER_8000_SCALE                      14
+#define CSEX_EQUALISER_8000_A0                    30912         /* Floating point value 0.943357 */
+#define CSEX_EQUALISER_8000_A1                   -14724         /* Floating point value -0.449345 */
+#define CSEX_EQUALISER_8000_A2                    -6868         /* Floating point value -0.209594 */
+#define CSEX_EQUALISER_8000_B1                   -15593         /* Floating point value -0.475865 */
+#define CSEX_EQUALISER_8000_B2                   -13374         /* Floating point value -0.408154 */
+#define CSEX_EQUALISER_8000_SCALE                    15
+
+/* Equaliser coefficients for 11025Hz sample rate, CS scaled with 1.027761 and CSEX scaled with 0.767463 */
+#define CS_EQUALISER_11025_A0                     18041         /* Floating point value 1.101145 */
+#define CS_EQUALISER_11025_A1                      2278         /* Floating point value 0.139020 */
+#define CS_EQUALISER_11025_A2                    -14163         /* Floating point value -0.864423 */
+#define CS_EQUALISER_11025_B1                       402         /* Floating point value 0.024541 */
+#define CS_EQUALISER_11025_B2                    -14892         /* Floating point value -0.908930 */
+#define CS_EQUALISER_11025_SCALE                     14
+#define CSEX_EQUALISER_11025_A0                   31983         /* Floating point value 0.976058 */
+#define CSEX_EQUALISER_11025_A1                  -22784         /* Floating point value -0.695326 */
+#define CSEX_EQUALISER_11025_A2                   -2976         /* Floating point value -0.090809 */
+#define CSEX_EQUALISER_11025_B1                  -20008         /* Floating point value -0.610594 */
+#define CSEX_EQUALISER_11025_B2                  -10196         /* Floating point value -0.311149 */
+#define CSEX_EQUALISER_11025_SCALE                   15
+
+/* Equaliser coefficients for 12000Hz sample rate, CS scaled with 1.032521 and CSEX scaled with 0.771017 */
+#define CS_EQUALISER_12000_A0                     20917         /* Floating point value 1.276661 */
+#define CS_EQUALISER_12000_A1                    -16671         /* Floating point value -1.017519 */
+#define CS_EQUALISER_12000_A2                      -723         /* Floating point value -0.044128 */
+#define CS_EQUALISER_12000_B1                    -11954         /* Floating point value -0.729616 */
+#define CS_EQUALISER_12000_B2                     -3351         /* Floating point value -0.204532 */
+#define CS_EQUALISER_12000_SCALE                     14
+#define CSEX_EQUALISER_12000_A0                   16500         /* Floating point value 1.007095 */
+#define CSEX_EQUALISER_12000_A1                  -14285         /* Floating point value -0.871912 */
+#define CSEX_EQUALISER_12000_A2                     381         /* Floating point value 0.023232 */
+#define CSEX_EQUALISER_12000_B1                  -12220         /* Floating point value -0.745857 */
+#define CSEX_EQUALISER_12000_B2                   -3099         /* Floating point value -0.189171 */
+#define CSEX_EQUALISER_12000_SCALE                   14
+
+/* Equaliser coefficients for 16000Hz sample rate, CS scaled with 1.031378 and CSEX scaled with 0.770164 */
+#define CS_EQUALISER_16000_A0                     20998         /* Floating point value 1.281629 */
+#define CS_EQUALISER_16000_A1                    -17627         /* Floating point value -1.075872 */
+#define CS_EQUALISER_16000_A2                      -678         /* Floating point value -0.041365 */
+#define CS_EQUALISER_16000_B1                    -11882         /* Floating point value -0.725239 */
+#define CS_EQUALISER_16000_B2                     -3676         /* Floating point value -0.224358 */
+#define CS_EQUALISER_16000_SCALE                     14
+#define CSEX_EQUALISER_16000_A0                   17713         /* Floating point value 1.081091 */
+#define CSEX_EQUALISER_16000_A1                  -14208         /* Floating point value -0.867183 */
+#define CSEX_EQUALISER_16000_A2                   -1151         /* Floating point value -0.070247 */
+#define CSEX_EQUALISER_16000_B1                   -8440         /* Floating point value -0.515121 */
+#define CSEX_EQUALISER_16000_B2                   -6978         /* Floating point value -0.425893 */
+#define CSEX_EQUALISER_16000_SCALE                   14
+
+/* Equaliser coefficients for 22050Hz sample rate, CS scaled with 1.041576 and CSEX scaled with 0.777779 */
+#define CS_EQUALISER_22050_A0                     22751         /* Floating point value 1.388605 */
+#define CS_EQUALISER_22050_A1                    -21394         /* Floating point value -1.305799 */
+#define CS_EQUALISER_22050_A2                       654         /* Floating point value 0.039922 */
+#define CS_EQUALISER_22050_B1                    -11788         /* Floating point value -0.719494 */
+#define CS_EQUALISER_22050_B2                     -3985         /* Floating point value -0.243245 */
+#define CS_EQUALISER_22050_SCALE                     14
+#define CSEX_EQUALISER_22050_A0                   20855         /* Floating point value 1.272910 */
+#define CSEX_EQUALISER_22050_A1                  -21971         /* Floating point value -1.341014 */
+#define CSEX_EQUALISER_22050_A2                    2744         /* Floating point value 0.167462 */
+#define CSEX_EQUALISER_22050_B1                  -10063         /* Floating point value -0.614219 */
+#define CSEX_EQUALISER_22050_B2                   -5659         /* Floating point value -0.345384 */
+#define CSEX_EQUALISER_22050_SCALE                   14
+
+/* Equaliser coefficients for 24000Hz sample rate, CS scaled with 1.034495 and CSEX scaled with 0.772491 */
+#define CS_EQUALISER_24000_A0                     23099         /* Floating point value 1.409832 */
+#define CS_EQUALISER_24000_A1                    -23863         /* Floating point value -1.456506 */
+#define CS_EQUALISER_24000_A2                      2481         /* Floating point value 0.151410 */
+#define CS_EQUALISER_24000_B1                    -13176         /* Floating point value -0.804201 */
+#define CS_EQUALISER_24000_B2                     -2683         /* Floating point value -0.163783 */
+#define CS_EQUALISER_24000_SCALE                     14
+#define CSEX_EQUALISER_24000_A0                   21286         /* Floating point value 1.299198 */
+#define CSEX_EQUALISER_24000_A1                  -23797         /* Floating point value -1.452447 */
+#define CSEX_EQUALISER_24000_A2                    3940         /* Floating point value 0.240489 */
+#define CSEX_EQUALISER_24000_B1                  -10966         /* Floating point value -0.669303 */
+#define CSEX_EQUALISER_24000_B2                   -4833         /* Floating point value -0.294984 */
+#define CSEX_EQUALISER_24000_SCALE                   14
+
+/* Equaliser coefficients for 32000Hz sample rate, CS scaled with 1.044559 and CSEX scaled with 0.780006 */
+#define CS_EQUALISER_32000_A0                     25575         /* Floating point value 1.560988 */
+#define CS_EQUALISER_32000_A1                    -30765         /* Floating point value -1.877724 */
+#define CS_EQUALISER_32000_A2                      6386         /* Floating point value 0.389741 */
+#define CS_EQUALISER_32000_B1                    -14867         /* Floating point value -0.907410 */
+#define CS_EQUALISER_32000_B2                     -1155         /* Floating point value -0.070489 */
+#define CS_EQUALISER_32000_SCALE                     14
+#define CSEX_EQUALISER_32000_A0                   14623         /* Floating point value 1.785049 */
+#define CSEX_EQUALISER_32000_A1                  -18297         /* Floating point value -2.233497 */
+#define CSEX_EQUALISER_32000_A2                    4313         /* Floating point value 0.526431 */
+#define CSEX_EQUALISER_32000_B1                   -3653         /* Floating point value -0.445939 */
+#define CSEX_EQUALISER_32000_B2                   -4280         /* Floating point value -0.522446 */
+#define CSEX_EQUALISER_32000_SCALE                   13
+
+/* Equaliser coefficients for 44100Hz sample rate, CS scaled with 1.022170 and CSEX scaled with 0.763288 */
+#define CS_EQUALISER_44100_A0                     13304         /* Floating point value 1.623993 */
+#define CS_EQUALISER_44100_A1                    -18602         /* Floating point value -2.270743 */
+#define CS_EQUALISER_44100_A2                      5643         /* Floating point value 0.688829 */
+#define CS_EQUALISER_44100_B1                     -9152         /* Floating point value -1.117190 */
+#define CS_EQUALISER_44100_B2                      1067         /* Floating point value 0.130208 */
+#define CS_EQUALISER_44100_SCALE                     13
+#define CSEX_EQUALISER_44100_A0                   16616         /* Floating point value 2.028315 */
+#define CSEX_EQUALISER_44100_A1                  -23613         /* Floating point value -2.882459 */
+#define CSEX_EQUALISER_44100_A2                    7410         /* Floating point value 0.904535 */
+#define CSEX_EQUALISER_44100_B1                   -4860         /* Floating point value -0.593308 */
+#define CSEX_EQUALISER_44100_B2                   -3161         /* Floating point value -0.385816 */
+#define CSEX_EQUALISER_44100_SCALE                   13
+
+/* Equaliser coefficients for 48000Hz sample rate, CS scaled with 1.018635 and CSEX scaled with 0.760648 */
+#define CS_EQUALISER_48000_A0                     13445         /* Floating point value 1.641177 */
+#define CS_EQUALISER_48000_A1                    -19372         /* Floating point value -2.364687 */
+#define CS_EQUALISER_48000_A2                      6225         /* Floating point value 0.759910 */
+#define CS_EQUALISER_48000_B1                     -9558         /* Floating point value -1.166774 */
+#define CS_EQUALISER_48000_B2                      1459         /* Floating point value 0.178074 */
+#define CS_EQUALISER_48000_SCALE                     13
+#define CSEX_EQUALISER_48000_A0                   17200         /* Floating point value 2.099655 */
+#define CSEX_EQUALISER_48000_A1                  -25110         /* Floating point value -3.065220 */
+#define CSEX_EQUALISER_48000_A2                    8277         /* Floating point value 1.010417 */
+#define CSEX_EQUALISER_48000_B1                   -5194         /* Floating point value -0.634021 */
+#define CSEX_EQUALISER_48000_B2                   -2845         /* Floating point value -0.347332 */
+#define CSEX_EQUALISER_48000_SCALE                   13
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* The Output Gain Correction                                                       */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVCS_HEADPHONE_SHIFT                          2              /* Output Shift */
+#define LVCS_HEADPHONE_SHIFTLOSS                  27779              /* Output Shift loss */
+#define LVCS_HEADPHONE_GAIN                        6840              /* Unprocessed path gain */
+#define LVCS_EX_HEADPHONE_SHIFT                       3              /* EX Output Shift */
+#define LVCS_EX_HEADPHONE_SHIFTLOSS               18600              /* EX Output Shift loss */
+#define LVCS_EX_HEADPHONE_GAIN                     5108              /* EX Unprocessed path gain */
+
+#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
new file mode 100755
index 0000000..f5f7cd0
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq06068 $
+     $Revision: 1307 $
+     $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Tables.h"
+
+/****************************************************************************************/
+/*                                                                                      */
+/* FUNCTION:                LVCS_Memory                                                 */
+/*                                                                                      */
+/* DESCRIPTION:                                                                         */
+/*  This function is used for memory allocation and free. It can be called in           */
+/*  two ways:                                                                           */
+/*                                                                                      */
+/*      hInstance = NULL                Returns the memory requirements                 */
+/*      hInstance = Instance handle     Returns the memory requirements and             */
+/*                                      allocated base addresses for the instance       */
+/*                                                                                      */
+/*  When this function is called for memory allocation (hInstance=NULL) it is           */
+/*  passed the default capabilities.                                                    */
+/*                                                                                      */
+/*  When called for memory allocation the memory base address pointers are NULL on      */
+/*  return.                                                                             */
+/*                                                                                      */
+/*  When the function is called for free (hInstance = Instance Handle) the              */
+/*  capabilities are ignored and the memory table returns the allocated memory and      */
+/*  base addresses used during initialisation.                                          */
+/*                                                                                      */
+/* PARAMETERS:                                                                          */
+/*  hInstance               Instance Handle                                             */
+/*  pMemoryTable            Pointer to an empty memory definition table                 */
+/*  pCapabilities           Pointer to the default capabilites                          */
+/*                                                                                      */
+/* RETURNS:                                                                             */
+/*  LVCS_Success            Succeeded                                                   */
+/*                                                                                      */
+/* NOTES:                                                                               */
+/*  1.  This function may be interrupted by the LVCS_Process function                   */
+/*                                                                                      */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Memory(LVCS_Handle_t          hInstance,
+                                 LVCS_MemTab_t          *pMemoryTable,
+                                 LVCS_Capabilities_t    *pCapabilities)
+{
+
+    LVM_UINT32          ScratchSize;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t *)hInstance;
+
+
+    /*
+     * Fill in the memory table
+     */
+    if (hInstance == LVM_NULL)
+    {
+        /*
+         * Instance memory
+         */
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].Size         = (LVM_UINT32)sizeof(LVCS_Instance_t);
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].Type         = LVCS_PERSISTENT;
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Data memory
+         */
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Size         = (LVM_UINT32)sizeof(LVCS_Data_t);
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Type         = LVCS_DATA;
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+        /*
+         * Coefficient memory
+         */
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Size         = (LVM_UINT32)sizeof(LVCS_Coefficient_t);
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Type         = LVCS_COEFFICIENT;
+        pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+        /*
+         * Scratch memory
+         */
+        ScratchSize = (LVM_UINT32)(LVCS_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);     /* Inplace processing */
+        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Size         = ScratchSize;
+        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Type         = LVCS_SCRATCH;
+        pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
+    }
+    else
+    {
+        /* Read back memory allocation table */
+        *pMemoryTable = pInstance->MemoryTable;
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Init                                               */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Create and initialisation function for the Concert Sound module                 */
+/*                                                                                  */
+/*  This function can be used to create an algorithm instance by calling with       */
+/*  hInstance set to LVM_NULL. In this case the algorithm returns the new instance  */
+/*  handle.                                                                         */
+/*                                                                                  */
+/*  This function can be used to force a full re-initialisation of the algorithm    */
+/*  by calling with hInstance = Instance Handle. In this case the memory table      */
+/*  should be correct for the instance, this can be ensured by calling the function */
+/*  LVCS_Memory before calling this function.                                       */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance handle                                         */
+/*  pMemoryTable            Pointer to the memory definition table                  */
+/*  pCapabilities           Pointer to the capabilities structure                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Initialisation succeeded                                */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  The instance handle is the pointer to the base address of the first memory  */
+/*      region.                                                                     */
+/*  2.  This function must not be interrupted by the LVCS_Process function          */
+/*  3.  This function must be called with the same capabilities as used for the     */
+/*      call to the memory function                                                 */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Init(LVCS_Handle_t         *phInstance,
+                               LVCS_MemTab_t         *pMemoryTable,
+                               LVCS_Capabilities_t   *pCapabilities)
+{
+
+    LVCS_Instance_t                 *pInstance;
+    LVCS_VolCorrect_t               *pLVCS_VolCorrectTable;
+
+
+    /*
+     * Set the instance handle if not already initialised
+     */
+    if (*phInstance == LVM_NULL)
+    {
+        *phInstance = (LVCS_Handle_t)pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress;
+    }
+    pInstance =(LVCS_Instance_t  *)*phInstance;
+
+
+    /*
+     * Save the capabilities in the instance structure
+     */
+    pInstance->Capabilities = *pCapabilities;
+
+    /*
+     * Save the memory table in the instance structure
+     */
+    pInstance->MemoryTable = *pMemoryTable;
+
+
+    /*
+     * Set all initial parameters to invalid to force a full initialisation
+     */
+    pInstance->Params.OperatingMode  = LVCS_OFF;
+    pInstance->Params.SpeakerType    = LVCS_SPEAKERTYPE_MAX;
+    pInstance->OutputDevice          = LVCS_HEADPHONE;
+    pInstance->Params.SourceFormat   = LVCS_SOURCEMAX;
+    pInstance->Params.CompressorMode = LVM_MODE_OFF;
+    pInstance->Params.SampleRate     = LVM_FS_INVALID;
+    pInstance->Params.EffectLevel    = 0;
+    pInstance->Params.ReverbLevel    = (LVM_UINT16)0x8000;
+    pLVCS_VolCorrectTable            = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+    pInstance->VolCorrect            = pLVCS_VolCorrectTable[0];
+    pInstance->TransitionGain        = 0;
+    /* These current and target values are intialized again in LVCS_Control.c */
+    LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
+    /* These current and target values are intialized again in LVCS_Control.c */
+    LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],0,0);
+
+    /*
+     * Initialise the bypass variables
+     */
+    pInstance->MSTarget0=0;
+    pInstance->MSTarget1=0;
+    pInstance->bInOperatingModeTransition          = LVM_FALSE;
+    pInstance->bTimerDone                        = LVM_FALSE;
+    pInstance->TimerParams.CallBackParam         = 0;
+    pInstance->TimerParams.pCallBack             = LVCS_TimerCallBack;
+    pInstance->TimerParams.pCallbackInstance     = pInstance;
+    pInstance->TimerParams.pCallBackParams       = LVM_NULL;
+
+    return(LVCS_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
new file mode 100755
index 0000000..a977690
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq06068 $
+     $Revision: 1307 $
+     $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Header file for the private layer interface of concert sound.                   */
+/*                                                                                  */
+/*  This files includes all definitions, types, structures and function             */
+/*  prototypes required by the execution layer.                                     */
+/*                                                                                  */
+/************************************************************************************/
+
+#ifndef __LVCS_PRIVATE_H__
+#define __LVCS_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"                               /* Calling or Application layer definitions */
+#include "LVCS_StereoEnhancer.h"                /* Stereo enhancer module definitions */
+#include "LVCS_ReverbGenerator.h"               /* Reverberation module definitions */
+#include "LVCS_Equaliser.h"                     /* Equaliser module definitions */
+#include "LVCS_BypassMix.h"                     /* Bypass Mixer module definitions */
+#include "LVM_Timer.h"
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Defines                                                                         */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Configuration switch controls */
+#define LVCS_STEREOENHANCESWITCH    0x0001      /* Stereo enhancement enable control */
+#define LVCS_REVERBSWITCH           0x0002      /* Reverberation enable control */
+#define LVCS_EQUALISERSWITCH        0x0004      /* Equaliser enable control */
+#define LVCS_BYPASSMIXSWITCH        0x0008      /* Bypass mixer enable control */
+
+/* Memory */
+#define LVCS_SCRATCHBUFFERS              6      /* Number of buffers required for inplace processing */
+
+/* General */
+#define LVCS_INVALID                0xFFFF      /* Invalid init parameter */
+#define LVCS_BYPASS_MIXER_TC        100         /* Bypass mixer time */
+
+/* Access to external coefficients table */
+#define LVCS_NR_OF_FS                    9
+#define LVCS_NR_OF_CHAN_CFG              2
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Types                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+typedef LVM_UINT16  LVCS_Configuration_t;       /* Internal algorithm configuration */
+
+typedef enum
+{
+    LVCS_HEADPHONE  = 0,
+    LVCS_DEVICE_MAX = LVM_MAXENUM
+} LVCS_OutputDevice_en;
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Structures                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Volume correction structure */
+typedef struct
+{
+    LVM_INT16   CompFull;                       /* Post CS compression 100% effect */
+    LVM_INT16   CompMin;                        /* Post CS compression 0% effect */
+    LVM_INT16   GainFull;                       /* CS gain correct 100% effect */
+    LVM_INT16   GainMin;                        /* CS gain correct 0% effect */
+} LVCS_VolCorrect_t;
+
+/* Instance structure */
+typedef struct
+{
+    /* Public parameters */
+    LVCS_MemTab_t           MemoryTable;        /* Instance memory allocation table */
+    LVCS_Params_t           Params;             /* Instance parameters */
+    LVCS_Capabilities_t     Capabilities;       /* Initialisation capabilities */
+
+    /* Private parameters */
+    LVCS_OutputDevice_en    OutputDevice;       /* Selected output device type */
+    LVCS_VolCorrect_t       VolCorrect;         /* Volume correction settings */
+    LVM_INT16               TransitionGain;     /* Transition gain */
+
+    /* Sub-block configurations */
+    LVCS_StereoEnhancer_t   StereoEnhancer;     /* Stereo enhancer configuration */
+    LVCS_ReverbGenerator_t  Reverberation;      /* Reverberation configuration */
+    LVCS_Equaliser_t        Equaliser;          /* Equaliser configuration */
+    LVCS_BypassMix_t        BypassMix;          /* Bypass mixer configuration */
+
+    /* Bypass variable */
+    LVM_INT16               MSTarget0;                          /* Mixer state control variable for smooth transtion */
+    LVM_INT16               MSTarget1;                          /* Mixer state control variable for smooth transtion */
+    LVM_INT16               bInOperatingModeTransition;         /* Operating mode transition flag */
+    LVM_INT16               bTimerDone;                         /* Timer completion flag */
+    LVM_Timer_Params_t      TimerParams;                        /* Timer parameters */
+    LVM_Timer_Instance_t    TimerInstance;                      /* Timer instance */
+
+} LVCS_Instance_t;
+
+/* Coefficient Structure */
+typedef struct
+{
+    Biquad_Instance_t       EqualiserBiquadInstance;
+    Biquad_Instance_t       ReverbBiquadInstance;
+    Biquad_Instance_t       SEBiquadInstanceMid;
+    Biquad_Instance_t       SEBiquadInstanceSide;
+
+} LVCS_Coefficient_t;
+
+/* Data Structure */
+typedef struct
+{
+    Biquad_2I_Order2_Taps_t EqualiserBiquadTaps;
+    Biquad_2I_Order2_Taps_t ReverbBiquadTaps;
+    Biquad_1I_Order1_Taps_t SEBiquadTapsMid;
+    Biquad_1I_Order2_Taps_t SEBiquadTapsSide;
+
+} LVCS_Data_t;
+
+
+void LVCS_TimerCallBack (   void* hInstance,
+                            void* pCallBackParams,
+                            LVM_INT32 CallbackParam);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif      /* PRIVATE_H */
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
new file mode 100755
index 0000000..999b8bb
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1001 $
+     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "VectorArithmetic.h"
+#include "CompLim.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Process_CS                                         */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Process function for the Concert Sound module based on the following block      */
+/*  diagram:                                                                        */
+/*            _________    ________    _____    _______     ___   ______            */
+/*           |         |  |        |  |     |  |       |   |   | |      |           */
+/*     ----->| Stereo  |->| Reverb |->| Equ |->| Alpha |-->| + |-| Gain |---->      */
+/*        |  | Enhance |  |________|  |_____|  |_______|   |___| |______|           */
+/*        |  |_________|                                     |                      */
+/*        |                                 ___________      |                      */
+/*        |                                |           |     |                      */
+/*        |------------------------------->| 1 - Alpha |-----|                      */
+/*                                         |___________|                            */
+/*                                                                                  */
+/*  The Stereo Enhancer, Reverb and Equaliser blocks are each configured to have    */
+/*  their gain to give a near peak to peak output (-0.1dBFS) with a worst case      */
+/*  input signal. The gains of these blocks are re-combined in the Alpha mixer and  */
+/*  the gain block folloing the sum.                                                */
+/*                                                                                  */
+/*  The processing uses the output buffer for data storage after each processing    */
+/*  block. When processing is inplace a copy of the input signal is made in scratch */
+/*  memory for the 1-Alpha path.                                                    */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance handle                                         */
+/*  pInData                 Pointer to the input data                               */
+/*  pOutData                Pointer to the output data                              */
+/*  NumSamples              Number of samples in the input buffer                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Succeeded                                               */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
+                                     const LVM_INT16            *pInData,
+                                     LVM_INT16                  *pOutData,
+                                     LVM_UINT16                 NumSamples)
+{
+    const LVM_INT16     *pInput;
+    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVM_INT16           *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+    LVCS_ReturnStatus_en err;
+
+    /*
+     * Check if the processing is inplace
+     */
+    if (pInData == pOutData)
+    {
+        /* Processing inplace */
+        pInput = pScratch + (2*NumSamples);
+        Copy_16((LVM_INT16 *)pInData,           /* Source */
+                (LVM_INT16 *)pInput,            /* Destination */
+                (LVM_INT16)(2*NumSamples));     /* Left and right */
+    }
+    else
+    {
+        /* Processing outplace */
+        pInput = pInData;
+    }
+
+    /*
+     * Call the stereo enhancer
+     */
+    err=LVCS_StereoEnhancer(hInstance,              /* Instance handle */
+                        pInData,                    /* Pointer to the input data */
+                        pOutData,                   /* Pointer to the output data */
+                        NumSamples);                /* Number of samples to process */
+
+    /*
+     * Call the reverb generator
+     */
+    err=LVCS_ReverbGenerator(hInstance,             /* Instance handle */
+                         pOutData,                  /* Pointer to the input data */
+                         pOutData,                  /* Pointer to the output data */
+                         NumSamples);               /* Number of samples to process */
+
+    /*
+     * Call the equaliser
+     */
+    err=LVCS_Equaliser(hInstance,                   /* Instance handle */
+                   pOutData,                        /* Pointer to the input data */
+                   NumSamples);                     /* Number of samples to process */
+
+    /*
+     * Call the bypass mixer
+     */
+    err=LVCS_BypassMixer(hInstance,                 /* Instance handle */
+                     pOutData,                      /* Pointer to the processed data */
+                     pInput,                        /* Pointer to the input (unprocessed) data */
+                     pOutData,                      /* Pointer to the output data */
+                     NumSamples);                   /* Number of samples to process */
+
+    if(err !=LVCS_SUCCESS)
+    {
+        return err;
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Process                                            */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Process function for the Concert Sound module. The implementation supports two  */
+/*  variants of the algorithm, one for headphones and one for mobile speakers.      */
+/*                                                                                  */
+/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono    */
+/*  format is not supported, the calling routine must convert the mono stream to    */
+/*  mono-in-stereo.                                                                 */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance handle                                         */
+/*  pInData                 Pointer to the input data                               */
+/*  pOutData                Pointer to the output data                              */
+/*  NumSamples              Number of samples in the input buffer                   */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Succeeded                                               */
+/*  LVCS_TooManySamples     NumSamples was larger than the maximum block size       */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
+                                  const LVM_INT16           *pInData,
+                                  LVM_INT16                 *pOutData,
+                                  LVM_UINT16                NumSamples)
+{
+
+    LVCS_Instance_t *pInstance =(LVCS_Instance_t  *)hInstance;
+    LVCS_ReturnStatus_en err;
+
+    /*
+     * Check the number of samples is not too large
+     */
+    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+    {
+        return(LVCS_TOOMANYSAMPLES);
+    }
+
+    /*
+     * Check if the algorithm is enabled
+     */
+    if (pInstance->Params.OperatingMode != LVCS_OFF)
+    {
+        /*
+         * Call CS process function
+         */
+            err=LVCS_Process_CS(hInstance,
+                            pInData,
+                            pOutData,
+                            NumSamples);
+
+        /*
+         * Compress to reduce expansion effect of Concert Sound and correct volume
+         * differences for difference settings. Not applied in test modes
+         */
+        if ((pInstance->Params.OperatingMode == LVCS_ON)&&(pInstance->Params.CompressorMode == LVM_MODE_ON))
+        {
+            LVM_INT16 Gain = pInstance->VolCorrect.CompMin;
+            LVM_INT32 Current1;
+
+            Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
+            Gain = (LVM_INT16)(  pInstance->VolCorrect.CompMin
+                               - (((LVM_INT32)pInstance->VolCorrect.CompMin  * (Current1)) >> 15)
+                               + (((LVM_INT32)pInstance->VolCorrect.CompFull * (Current1)) >> 15) );
+
+            NonLinComp_D16(Gain,                    /* Compressor gain setting */
+                           pOutData,
+                           pOutData,
+                           (LVM_INT32)(2*NumSamples));
+        }
+
+
+        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+
+            /*
+             * Re-init bypass mix when timer has completed
+             */
+            if ((pInstance->bTimerDone == LVM_TRUE) &&
+                (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
+            {
+                err=LVCS_BypassMixInit(hInstance,
+                                   &pInstance->Params);
+
+                if(err != LVCS_SUCCESS)
+                {
+                    return err;
+                }
+
+            }
+            else{
+                LVM_Timer ( &pInstance->TimerInstance,
+                            (LVM_INT16)NumSamples);
+            }
+        }
+    }
+    else
+    {
+        if (pInData != pOutData)
+        {
+            /*
+             * The algorithm is disabled so just copy the data
+             */
+            Copy_16((LVM_INT16 *)pInData,               /* Source */
+                (LVM_INT16 *)pOutData,                  /* Destination */
+                (LVM_INT16)(2*NumSamples));             /* Left and right */
+        }
+    }
+
+
+    return(LVCS_SUCCESS);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
new file mode 100755
index 0000000..861bde6
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1315 $
+     $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_ReverbGenerator.h"
+#include "LVC_Mixer.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_ReverbGeneratorInit                                */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialises the reverb module. The delay buffer size is configured for the      */
+/*  sample rate and the speaker type.                                               */
+/*                                                                                  */
+/*  The routine may also be called for re-initialisation, i.e. when one of the      */
+/*  control parameters has changed. In this case the delay and filters are only     */
+/*  re-initialised if one of the following two conditions is met:                   */
+/*      -   the sample rate has changed                                             */
+/*      -   the speaker type changes to/from the mobile speaker                     */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pParams                 Pointer to the inialisation parameters                  */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  In the delay settings 'Samples' is the number of samples to the end of the  */
+/*      buffer.                                                                     */
+/*  2.  The numerator coefficients of the filter are negated to cause an inversion. */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
+                                              LVCS_Params_t     *pParams)
+{
+
+    LVM_UINT16              Delay;
+    LVM_UINT16              Offset;
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
+    LVCS_Data_t             *pData     = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+    LVCS_Coefficient_t      *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+    BQ_C16_Coefs_t          Coeffs;
+    const BiquadA012B12CoefsSP_t  *pReverbCoefTable;
+
+    /*
+     * Initialise the delay and filters if:
+     *  - the sample rate has changed
+     *  - the speaker type has changed to or from the mobile speaker
+     */
+    if(pInstance->Params.SampleRate != pParams->SampleRate )      /* Sample rate change test */
+
+    {
+        /*
+         * Setup the delay
+         */
+        Delay = (LVM_UINT16)LVCS_StereoDelayCS[(LVM_UINT16)pParams->SampleRate];
+
+
+        pConfig->DelaySize      = (LVM_INT16)(2 * Delay);
+        pConfig->DelayOffset    = 0;
+        LoadConst_16(0,                                                                 /* Value */
+                     (LVM_INT16 *)&pConfig->StereoSamples[0],                           /* Destination */
+                     (LVM_UINT16)(sizeof(pConfig->StereoSamples)/sizeof(LVM_INT16)));   /* Number of words */
+
+        /*
+         * Setup the filters
+         */
+        Offset = (LVM_UINT16)pParams->SampleRate;
+        pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
+
+        /* Convert incoming coefficients to the required format/ordering */
+        Coeffs.A0 = (LVM_INT16)pReverbCoefTable[Offset].A0;
+        Coeffs.A1 = (LVM_INT16)pReverbCoefTable[Offset].A1;
+        Coeffs.A2 = (LVM_INT16)pReverbCoefTable[Offset].A2;
+        Coeffs.B1 = (LVM_INT16)-pReverbCoefTable[Offset].B1;
+        Coeffs.B2 = (LVM_INT16)-pReverbCoefTable[Offset].B2;
+
+        LoadConst_16(0,                                                                 /* Value */
+                     (void *)&pData->ReverbBiquadTaps,                             /* Destination Cast to void: no dereferencing in function*/
+                     (LVM_UINT16)(sizeof(pData->ReverbBiquadTaps)/sizeof(LVM_INT16)));  /* Number of words */
+
+        BQ_2I_D16F16Css_TRC_WRA_01_Init(&pCoefficients->ReverbBiquadInstance,
+                                        &pData->ReverbBiquadTaps,
+                                        &Coeffs);
+
+        /* Callbacks */
+        switch(pReverbCoefTable[Offset].Scale)
+        {
+            case 14:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F16C14_TRC_WRA_01;
+                break;
+            case 15:
+                pConfig->pBiquadCallBack  = BQ_2I_D16F16C15_TRC_WRA_01;
+                break;
+        }
+
+
+        /*
+         * Setup the mixer
+         */
+        pConfig->ProcGain = (LVM_UINT16)(HEADPHONEGAINPROC);
+        pConfig->UnprocGain  = (LVM_UINT16)(HEADPHONEGAINUNPROC);
+    }
+
+    if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
+    {
+        LVM_INT32   ReverbPercentage=83886;                     // 1 Percent Reverb i.e 1/100 in Q 23 format
+        ReverbPercentage*=pParams->ReverbLevel;                 // Actual Reverb Level in Q 23 format
+        pConfig->ReverbLevel=(LVM_INT16)(ReverbPercentage>>8);  // Reverb Level in Q 15 format
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_Reverb                                             */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Create reverb using the block of input samples based on the following block     */
+/*  diagram:                                                                        */
+/*                           ________              ________                         */
+/*                          |        |            |        |                        */
+/*     _____     _______    |        |----------->|        |    ______     ___      */
+/*    |     |   |       |   | Stereo |            | L & R  |   |      |   |   |     */
+/* -->| LPF |-->| Delay |-->|   to   |    ____    |   to   |-->| Gain |-->| + |-->  */
+/*  | |_____|   |_______|   | L & R  |   |    |   | Stereo |   |______|   |___|     */
+/*  |                       |        |-->| -1 |-->|        |                |       */
+/*  |                       |________|   |____|   |________|                |       */
+/*  |                                                                       |       */
+/*  |-----------------------------------------------------------------------|       */
+/*                                                                                  */
+/*  The input buffer is broken in to sub-blocks of the size of the delay or less.   */
+/*  This allows the delay buffer to be treated as a circular buffer but processed   */
+/*  as a linear buffer.                                                             */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pInData                 Pointer to the input buffer                             */
+/*  pOutData                Pointer to the output buffer                            */
+/*  NumSamples              Number of samples to process                            */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  Process in blocks of samples the size of the delay where possible, if not   */
+/*      the number of samples left over                                             */
+/*  2.  The Gain is combined with the LPF and incorporated in to the coefficients   */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
+                                          const LVM_INT16       *pInData,
+                                          LVM_INT16             *pOutData,
+                                          LVM_UINT16            NumSamples)
+{
+
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_ReverbGenerator_t  *pConfig   = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
+    LVCS_Coefficient_t      *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+    LVM_INT16               *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+
+
+    /*
+     * Copy the data to the output in outplace processing
+     */
+    if (pInData != pOutData)
+    {
+        /*
+         * Reverb not required so just copy the data
+         */
+        Copy_16((LVM_INT16 *)pInData,                                       /* Source */
+                (LVM_INT16 *)pOutData,                                      /* Destination */
+                (LVM_INT16)(2*NumSamples));                                 /* Left and right */
+    }
+
+
+    /*
+     * Check if the reverb is required
+     */
+    if (((pInstance->Params.SpeakerType == LVCS_HEADPHONE) ||           /* Disable when CS4MS in stereo mode */
+         (pInstance->Params.SpeakerType == LVCS_EX_HEADPHONES) ||
+         (pInstance->Params.SourceFormat != LVCS_STEREO))  &&
+        ((pInstance->Params.OperatingMode & LVCS_REVERBSWITCH) !=0))    /* For validation testing */
+    {
+        /********************************************************************************/
+        /*                                                                              */
+        /* Copy the input data to scratch memory and filter it                          */
+        /*                                                                              */
+        /********************************************************************************/
+
+        /*
+         * Copy the input data to the scratch memory
+         */
+        Copy_16((LVM_INT16 *)pInData,                                     /* Source */
+                (LVM_INT16 *)pScratch,                                    /* Destination */
+                (LVM_INT16)(2*NumSamples));                               /* Left and right */
+
+
+        /*
+         * Filter the data
+         */
+        (pConfig->pBiquadCallBack)((Biquad_Instance_t*)&pCoefficients->ReverbBiquadInstance,
+                                   (LVM_INT16 *)pScratch,
+                                   (LVM_INT16 *)pScratch,
+                                   (LVM_INT16)NumSamples);
+
+        Mult3s_16x16( (LVM_INT16 *)pScratch,
+                      pConfig->ReverbLevel,
+                      (LVM_INT16 *)pScratch,
+                      (LVM_INT16)(2*NumSamples));
+
+
+        /*
+         * Apply the delay mix
+         */
+        DelayMix_16x16((LVM_INT16 *)pScratch,
+                       &pConfig->StereoSamples[0],
+                       pConfig->DelaySize,
+                       pOutData,
+                       &pConfig->DelayOffset,
+                       (LVM_INT16)NumSamples);
+
+
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
new file mode 100755
index 0000000..1164bce
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1001 $
+     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVCS_REVERBGENERATOR_H__
+#define __LVCS_REVERBGENERATOR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVC_Mixer.h"
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Defines                                                                       */
+/*                                                                                  */
+/************************************************************************************/
+
+#define     HEADPHONEGAINPROC           LVCS_HEADPHONE_PROCGAIN
+#define     HEADPHONEGAINUNPROC         LVCS_HEADPHONE_UNPROCGAIN
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Structures                                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+
+/* Reverberation module structure */
+typedef struct
+{
+
+    /* Stereo delay */
+    LVM_INT16                   DelaySize;
+    LVM_INT16                   DelayOffset;
+    LVM_INT16                   ProcGain;
+    LVM_INT16                   UnprocGain;
+    LVM_INT16                    StereoSamples[2*LVCS_STEREODELAY_CS_48KHZ];
+
+    /* Reverb Level */
+    LVM_INT16                   ReverbLevel;
+
+    /* Filter */
+    void                        (*pBiquadCallBack) (Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+
+} LVCS_ReverbGenerator_t;
+
+
+/************************************************************************************/
+/*                                                                                    */
+/*    Function prototypes                                                                */
+/*                                                                                    */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t     hInstance,
+                                                 LVCS_Params_t  *pParams);
+
+LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t         hInstance,
+                                          const LVM_INT16       *pInput,
+                                          LVM_INT16             *pOutput,
+                                          LVM_UINT16            NumSamples);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* REVERB_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
new file mode 100755
index 0000000..b67d824
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: nxp007753 $
+     $Revision: 1315 $
+     $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_StereoEnhancer.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_StereoEnhanceInit                                  */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Initialises the stereo enhancement module based on the sample rate.             */
+/*                                                                                  */
+/*  The function selects the coefficients for the filters and clears the data       */
+/*  history. It is also used for re-initialisation when one of the system control   */
+/*  parameters changes but will only change the coefficients and clear the history  */
+/*  if the sample rate or speaker type has changed.                                 */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pParams                 Initialisation parameters                               */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t       hInstance,
+                                        LVCS_Params_t       *pParams)
+{
+
+    LVM_UINT16              Offset;
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
+    LVCS_Data_t             *pData     = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+    LVCS_Coefficient_t      *pCoefficient = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+    FO_C16_Coefs_t          CoeffsMid;
+    BQ_C16_Coefs_t          CoeffsSide;
+    const BiquadA012B12CoefsSP_t *pSESideCoefs;
+
+    /*
+     * If the sample rate or speaker type has changed update the filters
+     */
+    if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+        (pInstance->Params.SpeakerType != pParams->SpeakerType))
+    {
+        /*
+         * Set the filter coefficients based on the sample rate
+         */
+        /* Mid filter */
+        Offset = (LVM_UINT16)pParams->SampleRate;
+
+        /* Convert incoming coefficients to the required format/ordering */
+        CoeffsMid.A0 = (LVM_INT16) LVCS_SEMidCoefTable[Offset].A0;
+        CoeffsMid.A1 = (LVM_INT16) LVCS_SEMidCoefTable[Offset].A1;
+        CoeffsMid.B1 = (LVM_INT16)-LVCS_SEMidCoefTable[Offset].B1;
+
+        /* Clear the taps */
+        LoadConst_16(0,                                                                 /* Value */
+                     (void *)&pData->SEBiquadTapsMid,              /* Destination Cast to void:\
+                                                                      no dereferencing in function*/
+                     (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid)/sizeof(LVM_UINT16)));  /* Number of words */
+
+        FO_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceMid,
+                                        &pData->SEBiquadTapsMid,
+                                        &CoeffsMid);
+
+        /* Callbacks */
+        if(LVCS_SEMidCoefTable[Offset].Scale==15)
+        {
+            pConfig->pBiquadCallBack_Mid  = FO_1I_D16F16C15_TRC_WRA_01;
+        }
+
+        Offset = (LVM_UINT16)(pParams->SampleRate);
+        pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
+
+        /* Side filter */
+        /* Convert incoming coefficients to the required format/ordering */
+        CoeffsSide.A0 = (LVM_INT16) pSESideCoefs[Offset].A0;
+        CoeffsSide.A1 = (LVM_INT16) pSESideCoefs[Offset].A1;
+        CoeffsSide.A2 = (LVM_INT16) pSESideCoefs[Offset].A2;
+        CoeffsSide.B1 = (LVM_INT16)-pSESideCoefs[Offset].B1;
+        CoeffsSide.B2 = (LVM_INT16)-pSESideCoefs[Offset].B2;
+
+        /* Clear the taps */
+        LoadConst_16(0,                                                                 /* Value */
+                     (void *)&pData->SEBiquadTapsSide,             /* Destination Cast to void:\
+                                                                      no dereferencing in function*/
+                     (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide)/sizeof(LVM_UINT16))); /* Number of words */
+
+
+        /* Callbacks */
+        switch(pSESideCoefs[Offset].Scale)
+        {
+            case 14:
+                BQ_1I_D16F32Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
+                                                &pData->SEBiquadTapsSide,
+                                                &CoeffsSide);
+
+                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F32C14_TRC_WRA_01;
+                break;
+            case 15:
+                BQ_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
+                                                &pData->SEBiquadTapsSide,
+                                                &CoeffsSide);
+
+                pConfig->pBiquadCallBack_Side  = BQ_1I_D16F16C15_TRC_WRA_01;
+                break;
+        }
+
+    }
+
+
+    return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/*                                                                                  */
+/* FUNCTION:                LVCS_StereoEnhance                                      */
+/*                                                                                  */
+/* DESCRIPTION:                                                                     */
+/*  Enhance the stereo image in the input samples based on the following block      */
+/*  diagram:                                                                        */
+/*                                                                                  */
+/*                               ________                                           */
+/*          ________            |        |          ________                        */
+/*         |        |  Middle   | Treble |         |        |                       */
+/*         |        |---------->| Boost  |-------->|        |                       */
+/*         | Stereo |           |________|         | M & S  |                       */
+/*      -->|   to   |            ________          |   to   |-->                    */
+/*         | M & S  |  Side     |        |         | Stereo |                       */
+/*         |        |---------->| Side   |-------->|        |                       */
+/*         |________|           | Boost  |         |________|                       */
+/*                              |________|                                          */
+/*                                                                                  */
+/*                                                                                  */
+/*  If the input signal is a mono signal there will be no side signal and hence     */
+/*  the side filter will not be run. In mobile speaker mode the middle filter is    */
+/*  not required and the Trebble boost filter is replaced by a simple gain block.   */
+/*                                                                                  */
+/*                                                                                  */
+/* PARAMETERS:                                                                      */
+/*  hInstance               Instance Handle                                         */
+/*  pInData                 Pointer to the input data                               */
+/*  pOutData                Pointer to the output data                              */
+/*  NumSamples              Number of samples to process                            */
+/*                                                                                  */
+/* RETURNS:                                                                         */
+/*  LVCS_Success            Always succeeds                                         */
+/*                                                                                  */
+/* NOTES:                                                                           */
+/*  1.  The side filter is not used in Mobile Speaker mode                          */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t          hInstance,
+                                         const LVM_INT16        *pInData,
+                                         LVM_INT16              *pOutData,
+                                         LVM_UINT16             NumSamples)
+{
+
+    LVCS_Instance_t         *pInstance = (LVCS_Instance_t  *)hInstance;
+    LVCS_StereoEnhancer_t   *pConfig   = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
+    LVCS_Coefficient_t      *pCoefficient = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+    LVM_INT16               *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+
+    /*
+     * Check if the Stereo Enhancer is enabled
+     */
+    if ((pInstance->Params.OperatingMode & LVCS_STEREOENHANCESWITCH) != 0)
+        {
+        /*
+         * Convert from stereo to middle and side
+         */
+        From2iToMS_16x16(pInData,
+                         pScratch,
+                         pScratch+NumSamples,
+                         (LVM_INT16)NumSamples);
+
+        /*
+         * Apply filter to the middle signal
+         */
+        if (pInstance->OutputDevice == LVCS_HEADPHONE)
+        {
+            (pConfig->pBiquadCallBack_Mid)((Biquad_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
+                                           (LVM_INT16 *)pScratch,
+                                           (LVM_INT16 *)pScratch,
+                                           (LVM_INT16)NumSamples);
+        }
+        else
+        {
+            Mult3s_16x16(pScratch,              /* Source */
+                         (LVM_INT16)pConfig->MidGain,      /* Gain */
+                         pScratch,              /* Destination */
+                         (LVM_INT16)NumSamples);           /* Number of samples */
+        }
+
+        /*
+         * Apply the filter the side signal only in stereo mode for headphones
+         * and in all modes for mobile speakers
+         */
+        if (pInstance->Params.SourceFormat == LVCS_STEREO)
+        {
+            (pConfig->pBiquadCallBack_Side)((Biquad_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
+                                            (LVM_INT16 *)(pScratch + NumSamples),
+                                            (LVM_INT16 *)(pScratch + NumSamples),
+                                            (LVM_INT16)NumSamples);
+        }
+
+        /*
+         * Convert from middle and side to stereo
+         */
+        MSTo2i_Sat_16x16(pScratch,
+                         pScratch+NumSamples,
+                         pOutData,
+                         (LVM_INT16)NumSamples);
+
+    }
+    else
+    {
+        /*
+         * The stereo enhancer is disabled so just copy the data
+         */
+        Copy_16((LVM_INT16 *)pInData,           /* Source */
+                (LVM_INT16 *)pOutData,          /* Destination */
+                (LVM_INT16)(2*NumSamples));     /* Left and right */
+
+    }
+
+    return(LVCS_SUCCESS);
+}
+
+
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
new file mode 100755
index 0000000..c3f6296
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1001 $
+     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVCS_STEREOENHANCER_H__
+#define __LVCS_STEREOENHANCER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Includes                                                                      */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "Filters.h"                        /* Filter definitions */
+#include "LVCS_Headphone_Coeffs.h"          /* Headphone coefficients */
+#include "BIQUAD.h"
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Structures                                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Stereo enhancer structure */
+typedef struct
+{
+    /*
+     * Middle filter
+     */
+    void                    (*pBiquadCallBack_Mid)(Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+
+    /*
+     * Side filter
+     */
+    void                    (*pBiquadCallBack_Side)(Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+
+      LVM_UINT16              MidGain;            /* Middle gain in mobile speaker mode */
+
+} LVCS_StereoEnhancer_t;
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*    Function prototypes                                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t        hInstance,
+                                        LVCS_Params_t        *pParams);
+
+LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t        hInstance,
+                                         const LVM_INT16    *pInData,
+                                         LVM_INT16            *pOutData,
+                                         LVM_UINT16            NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif  /* STEREOENHANCE_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
new file mode 100755
index 0000000..ad4eb1e
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: beq07716 $
+     $Revision: 1001 $
+     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "LVCS_Private.h"
+#include "Filters.h"                            /* Filter definitions */
+#include "BIQUAD.h"                             /* Biquad definitions */
+#include "LVCS_Headphone_Coeffs.h"              /* Headphone coefficients */
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Stereo Enhancer coefficient constant tables                                     */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Coefficient table for the middle filter */
+const BiquadA01B1CoefsSP_t LVCS_SEMidCoefTable[] = {
+    {CS_MIDDLE_8000_A0,         /* 8kS/s coefficients */
+     CS_MIDDLE_8000_A1,
+     CS_MIDDLE_8000_B1,
+     (LVM_UINT16 )CS_MIDDLE_8000_SCALE},
+    {CS_MIDDLE_11025_A0,        /* 11kS/s coefficients */
+     CS_MIDDLE_11025_A1,
+     CS_MIDDLE_11025_B1,
+     (LVM_UINT16 )CS_MIDDLE_11025_SCALE},
+    {CS_MIDDLE_12000_A0,        /* 12kS/s coefficients */
+     CS_MIDDLE_12000_A1,
+     CS_MIDDLE_12000_B1,
+     (LVM_UINT16 )CS_MIDDLE_12000_SCALE},
+    {CS_MIDDLE_16000_A0,        /* 16kS/s coefficients */
+     CS_MIDDLE_16000_A1,
+     CS_MIDDLE_16000_B1,
+     (LVM_UINT16 )CS_MIDDLE_16000_SCALE},
+    {CS_MIDDLE_22050_A0,        /* 22kS/s coefficients */
+     CS_MIDDLE_22050_A1,
+     CS_MIDDLE_22050_B1,
+     (LVM_UINT16 )CS_MIDDLE_22050_SCALE},
+    {CS_MIDDLE_24000_A0,        /* 24kS/s coefficients */
+     CS_MIDDLE_24000_A1,
+     CS_MIDDLE_24000_B1,
+     (LVM_UINT16 )CS_MIDDLE_24000_SCALE},
+    {CS_MIDDLE_32000_A0,        /* 32kS/s coefficients */
+     CS_MIDDLE_32000_A1,
+     CS_MIDDLE_32000_B1,
+     (LVM_UINT16 )CS_MIDDLE_32000_SCALE},
+    {CS_MIDDLE_44100_A0,        /* 44kS/s coefficients */
+     CS_MIDDLE_44100_A1,
+     CS_MIDDLE_44100_B1,
+     (LVM_UINT16 )CS_MIDDLE_44100_SCALE},
+    {CS_MIDDLE_48000_A0,        /* 48kS/s coefficients */
+     CS_MIDDLE_48000_A1,
+     CS_MIDDLE_48000_B1,
+     (LVM_UINT16 )CS_MIDDLE_48000_SCALE}};
+
+/* Coefficient table for the side filter */
+const BiquadA012B12CoefsSP_t LVCS_SESideCoefTable[] = {
+    /* Headphone Side coefficients */
+    {CS_SIDE_8000_A0,           /* 8kS/s coefficients */
+     CS_SIDE_8000_A1,
+     CS_SIDE_8000_A2,
+     CS_SIDE_8000_B1,
+     CS_SIDE_8000_B2,
+     (LVM_UINT16 )CS_SIDE_8000_SCALE},
+    {CS_SIDE_11025_A0,          /* 11kS/s coefficients */
+     CS_SIDE_11025_A1,
+     CS_SIDE_11025_A2,
+     CS_SIDE_11025_B1,
+     CS_SIDE_11025_B2,
+     (LVM_UINT16 )CS_SIDE_11025_SCALE},
+    {CS_SIDE_12000_A0,          /* 12kS/s coefficients */
+     CS_SIDE_12000_A1,
+     CS_SIDE_12000_A2,
+     CS_SIDE_12000_B1,
+     CS_SIDE_12000_B2,
+     (LVM_UINT16 )CS_SIDE_12000_SCALE},
+    {CS_SIDE_16000_A0,          /* 16kS/s coefficients */
+     CS_SIDE_16000_A1,
+     CS_SIDE_16000_A2,
+     CS_SIDE_16000_B1,
+     CS_SIDE_16000_B2,
+     (LVM_UINT16 )CS_SIDE_16000_SCALE},
+    {CS_SIDE_22050_A0,          /* 22kS/s coefficients */
+     CS_SIDE_22050_A1,
+     CS_SIDE_22050_A2,
+     CS_SIDE_22050_B1,
+     CS_SIDE_22050_B2,
+     (LVM_UINT16 )CS_SIDE_22050_SCALE},
+    {CS_SIDE_24000_A0,          /* 24kS/s coefficients */
+     CS_SIDE_24000_A1,
+     CS_SIDE_24000_A2,
+     CS_SIDE_24000_B1,
+     CS_SIDE_24000_B2,
+     (LVM_UINT16 )CS_SIDE_24000_SCALE},
+    {CS_SIDE_32000_A0,          /* 32kS/s coefficients */
+     CS_SIDE_32000_A1,
+     CS_SIDE_32000_A2,
+     CS_SIDE_32000_B1,
+     CS_SIDE_32000_B2,
+     (LVM_UINT16 )CS_SIDE_32000_SCALE},
+    {CS_SIDE_44100_A0,          /* 44kS/s coefficients */
+     CS_SIDE_44100_A1,
+     CS_SIDE_44100_A2,
+     CS_SIDE_44100_B1,
+     CS_SIDE_44100_B2,
+     (LVM_UINT16 )CS_SIDE_44100_SCALE},
+    {CS_SIDE_48000_A0,          /* 48kS/s coefficients */
+     CS_SIDE_48000_A1,
+     CS_SIDE_48000_A2,
+     CS_SIDE_48000_B1,
+     CS_SIDE_48000_B2,
+     (LVM_UINT16 )CS_SIDE_48000_SCALE}
+};
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Equaliser coefficient constant tables                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+const BiquadA012B12CoefsSP_t LVCS_EqualiserCoefTable[] = {
+    /* Headphone coefficients */
+    {CS_EQUALISER_8000_A0,      /* 8kS/s coefficients */
+     CS_EQUALISER_8000_A1,
+     CS_EQUALISER_8000_A2,
+     CS_EQUALISER_8000_B1,
+     CS_EQUALISER_8000_B2,
+     (LVM_UINT16 )CS_EQUALISER_8000_SCALE},
+    {CS_EQUALISER_11025_A0,     /* 11kS/s coefficients */
+     CS_EQUALISER_11025_A1,
+     CS_EQUALISER_11025_A2,
+     CS_EQUALISER_11025_B1,
+     CS_EQUALISER_11025_B2,
+     (LVM_UINT16 )CS_EQUALISER_11025_SCALE},
+    {CS_EQUALISER_12000_A0,     /* 12kS/s coefficients */
+     CS_EQUALISER_12000_A1,
+     CS_EQUALISER_12000_A2,
+     CS_EQUALISER_12000_B1,
+     CS_EQUALISER_12000_B2,
+     (LVM_UINT16 )CS_EQUALISER_12000_SCALE},
+    {CS_EQUALISER_16000_A0,     /* 16kS/s coefficients */
+     CS_EQUALISER_16000_A1,
+     CS_EQUALISER_16000_A2,
+     CS_EQUALISER_16000_B1,
+     CS_EQUALISER_16000_B2,
+     (LVM_UINT16 )CS_EQUALISER_16000_SCALE},
+    {CS_EQUALISER_22050_A0,     /* 22kS/s coefficients */
+     CS_EQUALISER_22050_A1,
+     CS_EQUALISER_22050_A2,
+     CS_EQUALISER_22050_B1,
+     CS_EQUALISER_22050_B2,
+     (LVM_UINT16 )CS_EQUALISER_22050_SCALE},
+    {CS_EQUALISER_24000_A0,     /* 24kS/s coefficients */
+     CS_EQUALISER_24000_A1,
+     CS_EQUALISER_24000_A2,
+     CS_EQUALISER_24000_B1,
+     CS_EQUALISER_24000_B2,
+     (LVM_UINT16 )CS_EQUALISER_24000_SCALE},
+    {CS_EQUALISER_32000_A0,     /* 32kS/s coefficients */
+     CS_EQUALISER_32000_A1,
+     CS_EQUALISER_32000_A2,
+     CS_EQUALISER_32000_B1,
+     CS_EQUALISER_32000_B2,
+     (LVM_UINT16 )CS_EQUALISER_32000_SCALE},
+    {CS_EQUALISER_44100_A0,     /* 44kS/s coefficients */
+     CS_EQUALISER_44100_A1,
+     CS_EQUALISER_44100_A2,
+     CS_EQUALISER_44100_B1,
+     CS_EQUALISER_44100_B2,
+     (LVM_UINT16 )CS_EQUALISER_44100_SCALE},
+    {CS_EQUALISER_48000_A0,     /* 48kS/s coefficients */
+     CS_EQUALISER_48000_A1,
+     CS_EQUALISER_48000_A2,
+     CS_EQUALISER_48000_B1,
+     CS_EQUALISER_48000_B2,
+     (LVM_UINT16 )CS_EQUALISER_48000_SCALE},
+
+    /* Concert Sound EX Headphone coefficients */
+    {CSEX_EQUALISER_8000_A0,    /* 8kS/s coefficients */
+     CSEX_EQUALISER_8000_A1,
+     CSEX_EQUALISER_8000_A2,
+     CSEX_EQUALISER_8000_B1,
+     CSEX_EQUALISER_8000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_8000_SCALE},
+    {CSEX_EQUALISER_11025_A0,   /* 11kS/s coefficients */
+     CSEX_EQUALISER_11025_A1,
+     CSEX_EQUALISER_11025_A2,
+     CSEX_EQUALISER_11025_B1,
+     CSEX_EQUALISER_11025_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_11025_SCALE},
+    {CSEX_EQUALISER_12000_A0,   /* 12kS/s coefficients */
+     CSEX_EQUALISER_12000_A1,
+     CSEX_EQUALISER_12000_A2,
+     CSEX_EQUALISER_12000_B1,
+     CSEX_EQUALISER_12000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_12000_SCALE},
+    {CSEX_EQUALISER_16000_A0,   /* 16kS/s coefficients */
+     CSEX_EQUALISER_16000_A1,
+     CSEX_EQUALISER_16000_A2,
+     CSEX_EQUALISER_16000_B1,
+     CSEX_EQUALISER_16000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_16000_SCALE},
+    {CSEX_EQUALISER_22050_A0,   /* 22kS/s coefficients */
+     CSEX_EQUALISER_22050_A1,
+     CSEX_EQUALISER_22050_A2,
+     CSEX_EQUALISER_22050_B1,
+     CSEX_EQUALISER_22050_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_22050_SCALE},
+    {CSEX_EQUALISER_24000_A0,   /* 24kS/s coefficients */
+     CSEX_EQUALISER_24000_A1,
+     CSEX_EQUALISER_24000_A2,
+     CSEX_EQUALISER_24000_B1,
+     CSEX_EQUALISER_24000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_24000_SCALE},
+    {CSEX_EQUALISER_32000_A0,   /* 32kS/s coefficients */
+     CSEX_EQUALISER_32000_A1,
+     CSEX_EQUALISER_32000_A2,
+     CSEX_EQUALISER_32000_B1,
+     CSEX_EQUALISER_32000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_32000_SCALE},
+    {CSEX_EQUALISER_44100_A0,   /* 44kS/s coefficients */
+     CSEX_EQUALISER_44100_A1,
+     CSEX_EQUALISER_44100_A2,
+     CSEX_EQUALISER_44100_B1,
+     CSEX_EQUALISER_44100_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_44100_SCALE},
+    {CSEX_EQUALISER_48000_A0,   /* 48kS/s coefficients */
+     CSEX_EQUALISER_48000_A1,
+     CSEX_EQUALISER_48000_A2,
+     CSEX_EQUALISER_48000_B1,
+     CSEX_EQUALISER_48000_B2,
+     (LVM_UINT16 )CSEX_EQUALISER_48000_SCALE}
+};
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Reverb delay constant tables                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Stereo delay table for Concert Sound */
+const LVM_UINT16    LVCS_StereoDelayCS[] = {
+    LVCS_STEREODELAY_CS_8KHZ,
+    LVCS_STEREODELAY_CS_11KHZ,
+    LVCS_STEREODELAY_CS_12KHZ,
+    LVCS_STEREODELAY_CS_16KHZ,
+    LVCS_STEREODELAY_CS_22KHZ,
+    LVCS_STEREODELAY_CS_24KHZ,
+    LVCS_STEREODELAY_CS_32KHZ,
+    LVCS_STEREODELAY_CS_44KHZ,
+    LVCS_STEREODELAY_CS_48KHZ};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Reverb coefficients constant table                                              */
+/*                                                                                  */
+/************************************************************************************/
+
+const BiquadA012B12CoefsSP_t LVCS_ReverbCoefTable[] = {
+    /* Headphone coefficients */
+    {CS_REVERB_8000_A0,             /* 8kS/s coefficients */
+     CS_REVERB_8000_A1,
+     CS_REVERB_8000_A2,
+     CS_REVERB_8000_B1,
+     CS_REVERB_8000_B2,
+     (LVM_UINT16 )CS_REVERB_8000_SCALE},
+    {CS_REVERB_11025_A0,            /* 11kS/s coefficients */
+     CS_REVERB_11025_A1,
+     CS_REVERB_11025_A2,
+     CS_REVERB_11025_B1,
+     CS_REVERB_11025_B2,
+     (LVM_UINT16 )CS_REVERB_11025_SCALE},
+    {CS_REVERB_12000_A0,            /* 12kS/s coefficients */
+     CS_REVERB_12000_A1,
+     CS_REVERB_12000_A2,
+     CS_REVERB_12000_B1,
+     CS_REVERB_12000_B2,
+     (LVM_UINT16 )CS_REVERB_12000_SCALE},
+    {CS_REVERB_16000_A0,            /* 16kS/s coefficients */
+     CS_REVERB_16000_A1,
+     CS_REVERB_16000_A2,
+     CS_REVERB_16000_B1,
+     CS_REVERB_16000_B2,
+     (LVM_UINT16 )CS_REVERB_16000_SCALE},
+    {CS_REVERB_22050_A0,            /* 22kS/s coefficients */
+     CS_REVERB_22050_A1,
+     CS_REVERB_22050_A2,
+     CS_REVERB_22050_B1,
+     CS_REVERB_22050_B2,
+     (LVM_UINT16 )CS_REVERB_22050_SCALE},
+    {CS_REVERB_24000_A0,            /* 24kS/s coefficients */
+     CS_REVERB_24000_A1,
+     CS_REVERB_24000_A2,
+     CS_REVERB_24000_B1,
+     CS_REVERB_24000_B2,
+     (LVM_UINT16 )CS_REVERB_24000_SCALE},
+    {CS_REVERB_32000_A0,            /* 32kS/s coefficients */
+     CS_REVERB_32000_A1,
+     CS_REVERB_32000_A2,
+     CS_REVERB_32000_B1,
+     CS_REVERB_32000_B2,
+     (LVM_UINT16 )CS_REVERB_32000_SCALE},
+    {CS_REVERB_44100_A0,            /* 44kS/s coefficients */
+     CS_REVERB_44100_A1,
+     CS_REVERB_44100_A2,
+     CS_REVERB_44100_B1,
+     CS_REVERB_44100_B2,
+     (LVM_UINT16 )CS_REVERB_44100_SCALE},
+    {CS_REVERB_48000_A0,            /* 48kS/s coefficients */
+     CS_REVERB_48000_A1,
+     CS_REVERB_48000_A2,
+     CS_REVERB_48000_B1,
+     CS_REVERB_48000_B2,
+     (LVM_UINT16 )CS_REVERB_48000_SCALE}
+};
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Bypass mixer constant tables                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+const Gain_t LVCS_OutputGainTable[] = {
+    {LVCS_HEADPHONE_SHIFT,         /* Headphone, stereo mode */
+     LVCS_HEADPHONE_SHIFTLOSS,
+     LVCS_HEADPHONE_GAIN},
+    {LVCS_EX_HEADPHONE_SHIFT,      /* EX Headphone, stereo mode */
+     LVCS_EX_HEADPHONE_SHIFTLOSS,
+     LVCS_EX_HEADPHONE_GAIN},
+    {LVCS_HEADPHONE_SHIFT,         /* Headphone, mono mode */
+     LVCS_HEADPHONE_SHIFTLOSS,
+     LVCS_HEADPHONE_GAIN},
+    {LVCS_EX_HEADPHONE_SHIFT,      /* EX Headphone, mono mode */
+     LVCS_EX_HEADPHONE_SHIFTLOSS,
+     LVCS_EX_HEADPHONE_GAIN}
+};
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Volume correction table                                                         */
+/*                                                                                  */
+/*  Coefficient order:                                                              */
+/*      Compression 100% effect                                                     */
+/*      Compression 0% effect                                                       */
+/*      Gain 100% effect                                                            */
+/*      Gain 0% effect                                                              */
+/*                                                                                  */
+/*  The Compression gain is represented by a Q1.15 number to give a range of 0dB    */
+/*  to +6dB, E.g.:                                                                  */
+/*          0       is 0dB compression (no effect)                                  */
+/*          5461    is 1dB compression gain                                         */
+/*          10923   is 2dB compression gain                                         */
+/*          32767   is 6dB compression gain                                         */
+/*                                                                                  */
+/*  The Gain is represented as a Q3.13 number to give a range of +8 to -infinity    */
+/*  E.g.:                                                                           */
+/*          0       is -infinity                                                    */
+/*          32767   is +18dB (x8) gain                                              */
+/*          4096    is 0dB gain                                                     */
+/*          1024    is -12dB gain                                                   */
+/*                                                                                  */
+/************************************************************************************/
+const LVCS_VolCorrect_t LVCS_VolCorrectTable[] = {
+    {14200,          /* Headphone, stereo mode */
+     0,
+     4096,
+     5786},
+    {14200,          /* EX Headphone, stereo mode */
+     0,
+     4096,
+     5786},
+    {32767,         /* Headphone, mono mode */
+     0,
+     4096,
+     5786},
+    {32767,         /* EX Headphone, mono mode */
+     0,
+     4096,
+     5786}
+};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Mixer time constants, 100ms                                                     */
+/*                                                                                  */
+/************************************************************************************/
+
+#define LVCS_VOL_TC_Fs8000      32580       /* Floating point value 0.994262695 */
+#define LVCS_VOL_TC_Fs11025     32632       /* Floating point value 0.995849609 */
+#define LVCS_VOL_TC_Fs12000     32643       /* Floating point value 0.996185303 */
+#define LVCS_VOL_TC_Fs16000     32674       /* Floating point value 0.997131348 */
+#define LVCS_VOL_TC_Fs22050     32700       /* Floating point value 0.997924805 */
+#define LVCS_VOL_TC_Fs24000     32705       /* Floating point value 0.998077393 */
+#define LVCS_VOL_TC_Fs32000     32721       /* Floating point value 0.998565674 */
+#define LVCS_VOL_TC_Fs44100     32734       /* Floating point value 0.998962402 */
+#define LVCS_VOL_TC_Fs48000     32737       /* Floating point value 0.999053955 */
+
+
+const LVM_INT16 LVCS_VolumeTCTable[9] = {LVCS_VOL_TC_Fs8000,
+                                        LVCS_VOL_TC_Fs11025,
+                                        LVCS_VOL_TC_Fs12000,
+                                        LVCS_VOL_TC_Fs16000,
+                                        LVCS_VOL_TC_Fs22050,
+                                        LVCS_VOL_TC_Fs24000,
+                                        LVCS_VOL_TC_Fs32000,
+                                        LVCS_VOL_TC_Fs44100,
+                                        LVCS_VOL_TC_Fs48000};
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rate table                                                               */
+/*                                                                                  */
+/************************************************************************************/
+
+const LVM_INT32   LVCS_SampleRateTable[9] = {8000,
+                                            11025,
+                                            12000,
+                                            16000,
+                                            22050,
+                                            24000,
+                                            32000,
+                                            44100,
+                                            48000};
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h
new file mode 100755
index 0000000..72d6855
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ */
+
+/************************************************************************************
+
+     $Author: nxp27078 $
+     $Revision: 672 $
+     $Date: 2010-06-08 19:39:38 +0200 (Tue, 08 Jun 2010) $
+
+*************************************************************************************/
+#ifndef __LVCS_TABLES_H__
+#define __LVCS_TABLES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Includes                                                                        */
+/*                                                                                  */
+/************************************************************************************/
+
+#include "BIQUAD.h"                             /* Biquad definitions */
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Stereo Enhancer coefficient constant tables                                     */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Coefficient table for the middle filter */
+extern const BiquadA01B1CoefsSP_t LVCS_SEMidCoefTable[];
+
+/* Coefficient table for the side filter */
+extern const BiquadA012B12CoefsSP_t LVCS_SESideCoefTable[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Equaliser coefficient constant tables                                           */
+/*                                                                                  */
+/************************************************************************************/
+
+extern const BiquadA012B12CoefsSP_t LVCS_EqualiserCoefTable[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Reverb delay constant tables                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+/* Stereo delay table for Concert Sound */
+extern const LVM_UINT16 LVCS_StereoDelayCS[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Reverb coefficients constant table                                              */
+/*                                                                                  */
+/************************************************************************************/
+
+extern const BiquadA012B12CoefsSP_t LVCS_ReverbCoefTable[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Bypass mixer constant tables                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+extern const Gain_t LVCS_OutputGainTable[];
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Volume correction table                                                         */
+/*                                                                                  */
+/*  Coefficient order:                                                              */
+/*      Compression 100% effect                                                     */
+/*      Compression 0% effect                                                       */
+/*      Gain 100% effect                                                            */
+/*      Gain 0% effect                                                              */
+/*                                                                                  */
+/*  The Compression gain is represented by a Q1.15 number to give a range of 0dB    */
+/*  to +6dB, E.g.:                                                                  */
+/*          0       is 0dB compression (no effect)                                  */
+/*          5461    is 1dB compression gain                                         */
+/*          10923   is 2dB compression gain                                         */
+/*          32767   is 6dB compression gain                                         */
+/*                                                                                  */
+/*  The Gain is represented as a Q3.13 number to give a range of +8 to -infinity    */
+/*  E.g.:                                                                           */
+/*          0       is -infinity                                                    */
+/*          32767   is +18dB (x8) gain                                              */
+/*          4096    is 0dB gain                                                     */
+/*          1024    is -12dB gain                                                   */
+/*                                                                                  */
+/************************************************************************************/
+
+extern const LVCS_VolCorrect_t LVCS_VolCorrectTable[];
+extern const LVM_INT16 LVCS_VolumeTCTable[];
+
+
+/************************************************************************************/
+/*                                                                                  */
+/*  Sample rates                                                                    */
+/*                                                                                  */
+/************************************************************************************/
+
+extern LVM_INT32                LVCS_SampleRateTable[];
+
+
+/*Speaker coeffient tables*/
+extern LVM_UINT16               LVCS_MS_Small_SEMiddleGainTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Small_SESideCoefTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Small_EqualiserCoefTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Small_ReverbCoefTable[] ;
+extern LVM_UINT16               LVCS_MS_Small_StereoDelayCS4MS[];
+extern Gain_t                   LVCS_MS_Small_OutputGainTable[];
+extern LVCS_VolCorrect_t        LVCS_MS_Small_VolCorrectTable[];
+extern LVM_UINT16               LVCS_MS_Small_ReverbGainTable[];
+
+extern LVM_UINT16               LVCS_MS_Medium_SEMiddleGainTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Medium_SESideCoefTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Medium_EqualiserCoefTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Medium_ReverbCoefTable[] ;
+extern LVM_UINT16               LVCS_MS_Medium_StereoDelayCS4MS[];
+extern Gain_t                   LVCS_MS_Medium_OutputGainTable[];
+extern LVCS_VolCorrect_t        LVCS_MS_Medium_VolCorrectTable[];
+extern LVM_UINT16               LVCS_MS_Medium_ReverbGainTable[];
+
+extern LVM_UINT16               LVCS_MS_Large_SEMiddleGainTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Large_SESideCoefTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Large_EqualiserCoefTable[];
+extern BiquadA012B12CoefsSP_t   LVCS_MS_Large_ReverbCoefTable[] ;
+extern LVM_UINT16               LVCS_MS_Large_StereoDelayCS4MS[];
+extern Gain_t                   LVCS_MS_Large_OutputGainTable[];
+extern LVCS_VolCorrect_t        LVCS_MS_Large_VolCorrectTable[];
+extern LVM_UINT16               LVCS_MS_Large_ReverbGainTable[];
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVCS_TABLES_H__ */
+
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
new file mode 100644
index 0000000..7855dcd
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+# music bundle wrapper
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES:= \
+	Bundle/EffectBundle.cpp
+
+LOCAL_MODULE:= libbundlewrapper
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_STATIC_LIBRARIES += libmusicbundle
+
+LOCAL_SHARED_LIBRARIES := \
+     libcutils \
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_LDLIBS += -ldl
+else
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH)/Bundle \
+	$(LOCAL_PATH)/../lib/Common/lib/ \
+	$(LOCAL_PATH)/../lib/Bundle/lib/
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
new file mode 100644
index 0000000..a70bdff
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -0,0 +1,2937 @@
+/*
+ * Copyright (C) 2010-2010 NXP Software
+ * Copyright (C) 2009 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_TAG "Bundle"
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+#define LOG_NDEBUG 0
+
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <EffectBundle.h>
+
+#define LVM_MAX_SESSIONS        32
+#define MAX_NUM_BANDS           5
+#define MAX_CALL_SIZE           256
+
+// effect_interface_t interface implementation for bass boost
+extern "C" const struct effect_interface_s gLvmEffectInterface;
+
+#define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc){\
+        if (LvmStatus == LVM_NULLADDRESS){\
+            LOGV("\tLVM_ERROR : Parameter error - "\
+                    "null pointer returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+        }\
+        if (LvmStatus == LVM_ALIGNMENTERROR){\
+            LOGV("\tLVM_ERROR : Parameter error - "\
+                    "bad alignment returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+        }\
+        if (LvmStatus == LVM_INVALIDNUMSAMPLES){\
+            LOGV("\tLVM_ERROR : Parameter error - "\
+                    "bad number of samples returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+        }\
+        if (LvmStatus == LVM_OUTOFRANGE){\
+            LOGV("\tLVM_ERROR : Parameter error - "\
+                    "out of range returned by %s in %s\n", callingFunc, calledFunc);\
+        }\
+    }
+
+// Namespaces
+namespace android {
+namespace {
+
+/* local functions */
+#define CHECK_ARG(cond) {                     \
+    if (!(cond)) {                            \
+        LOGV("\tLVM_ERROR : Invalid argument: "#cond);      \
+        return -EINVAL;                       \
+    }                                         \
+}
+
+// Flag to allow a one time init of global memory, only happens on first call ever
+int LvmInitFlag = LVM_FALSE;
+SessionContext GlobalSessionMemory[32];
+
+// NXP SW BassBoost UUID
+const effect_descriptor_t gBassBoostDescriptor = {
+        {0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }},
+        {0x8631f300, 0x72e2, 0x11df, 0xb57e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+        EFFECT_API_VERSION,
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_DEVICE_IND
+        | EFFECT_FLAG_VOLUME_CTRL),
+        0, // TODO
+        1,
+        "Dynamic Bass Boost",
+        "NXP Software Ltd.",
+};
+
+// NXP SW Virtualizer UUID
+const effect_descriptor_t gVirtualizerDescriptor = {
+        {0x37cc2c00, 0xdddd, 0x11db, 0x8577, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        {0x1d4033c0, 0x8557, 0x11df, 0x9f2d, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_DEVICE_IND
+        | EFFECT_FLAG_VOLUME_CTRL),
+        0, // TODO
+        1,
+        "Virtualizer",
+        "NXP Software Ltd.",
+};
+
+// NXP SW Equalizer UUID
+const effect_descriptor_t gEqualizerDescriptor = {
+        {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+        {0xce772f20, 0x847d, 0x11df, 0xbb17, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid Eq NXP
+        EFFECT_API_VERSION,
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_VOLUME_CTRL),
+        0, // TODO
+        1,
+        "Equalizer",
+        "NXP Software Ltd.",
+};
+
+// NXP SW Volume UUID
+const effect_descriptor_t gVolumeDescriptor = {
+        {0x09e8ede0, 0xddde, 0x11db, 0xb4f6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }},
+        {0x119341a0, 0x8469, 0x11df, 0x81f9, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }}, //uuid VOL NXP
+        EFFECT_API_VERSION,
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_VOLUME_CTRL),
+        0, // TODO
+        1,
+        "Volume",
+        "NXP Software Ltd.",
+};
+
+//--- local function prototypes
+void LvmGlobalBundle_init      (void);
+int  LvmBundle_init            (EffectContext *pContext);
+int  LvmEffect_enable          (EffectContext *pContext);
+int  LvmEffect_disable         (EffectContext *pContext);
+void LvmEffect_free            (EffectContext *pContext);
+int  Effect_configure          (EffectContext *pContext, effect_config_t *pConfig);
+int  BassBoost_setParameter    (EffectContext *pContext, int32_t *pParam, void *pValue);
+int  BassBoost_getParameter    (EffectContext *pContext,
+                               int32_t        *pParam,
+                               size_t         *pValueSize,
+                               void           *pValue);
+int  Virtualizer_setParameter  (EffectContext *pContext, int32_t *pParam, void *pValue);
+int  Virtualizer_getParameter  (EffectContext *pContext,
+                               int32_t        *pParam,
+                               size_t         *pValueSize,
+                               void           *pValue);
+int  Equalizer_setParameter    (EffectContext *pContext, int32_t *pParam, void *pValue);
+int  Equalizer_getParameter    (EffectContext *pContext,
+                                int32_t       *pParam,
+                                size_t        *pValueSize,
+                                void          *pValue);
+int  Volume_setParameter       (EffectContext *pContext, int32_t *pParam, void *pValue);
+int  Volume_getParameter       (EffectContext *pContext,
+                                int32_t       *pParam,
+                                size_t        *pValueSize,
+                                void          *pValue);
+
+/* Effect Library Interface Implementation */
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects){
+    LOGV("\n\tEffectQueryNumberEffects start");
+    *pNumEffects = 4;
+    LOGV("\tEffectQueryNumberEffects creating %d effects", *pNumEffects);
+    LOGV("\tEffectQueryNumberEffects end\n");
+    return 0;
+}     /* end EffectQueryNumberEffects */
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor){
+    LOGV("\n\tEffectQueryEffect start");
+    LOGV("\tEffectQueryEffect processing index %d", index);
+
+    if (pDescriptor == NULL){
+        LOGV("\tLVM_ERROR : EffectQueryEffect was passed NULL pointer");
+        return -EINVAL;
+    }
+    if (index > 3){
+        LOGV("\tLVM_ERROR : EffectQueryEffect index out of range %d", index);
+        return -ENOENT;
+    }
+    if(index == LVM_BASS_BOOST){
+        LOGV("\tEffectQueryEffect processing LVM_BASS_BOOST");
+        memcpy(pDescriptor, &gBassBoostDescriptor,   sizeof(effect_descriptor_t));
+    }else if(index == LVM_VIRTUALIZER){
+        LOGV("\tEffectQueryEffect processing LVM_VIRTUALIZER");
+        memcpy(pDescriptor, &gVirtualizerDescriptor, sizeof(effect_descriptor_t));
+    } else if(index == LVM_EQUALIZER){
+        LOGV("\tEffectQueryEffect processing LVM_EQUALIZER");
+        memcpy(pDescriptor, &gEqualizerDescriptor,   sizeof(effect_descriptor_t));
+    } else if(index == LVM_VOLUME){
+        LOGV("\tEffectQueryEffect processing LVM_VOLUME");
+        memcpy(pDescriptor, &gVolumeDescriptor, sizeof(effect_descriptor_t));
+    }
+    LOGV("\tEffectQueryEffect end\n");
+    return 0;
+}     /* end EffectQueryEffect */
+
+extern "C" int EffectCreate(effect_uuid_t       *uuid,
+                            int32_t             sessionId,
+                            int32_t             ioId,
+                            effect_interface_t  *pInterface){
+    int ret;
+    int i;
+    EffectContext *pContext = new EffectContext;
+
+    LOGV("\n\tEffectCreate start session %d", sessionId);
+
+    if (pInterface == NULL || uuid == NULL){
+        LOGV("\tLVM_ERROR : EffectCreate() called with NULL pointer");
+        return -EINVAL;
+    }
+
+    if((sessionId < 0)||(sessionId >= LVM_MAX_SESSIONS)){
+        LOGV("\tLVM_ERROR : EffectCreate sessionId is less than 0");
+        return -EINVAL;
+    }
+
+    if(LvmInitFlag == LVM_FALSE){
+        LvmInitFlag = LVM_TRUE;
+        LOGV("\tEffectCreate - Initializing all global memory");
+        LvmGlobalBundle_init();
+    }
+
+    // If this is the first create in this session
+    if(GlobalSessionMemory[sessionId].bBundledEffectsEnabled == LVM_FALSE){
+        LOGV("\tEffectCreate - This is the first effect in current session %d", sessionId);
+        LOGV("\tEffectCreate - Setting up Bundled Effects Instance for session %d", sessionId);
+
+        GlobalSessionMemory[sessionId].bBundledEffectsEnabled = LVM_TRUE;
+        GlobalSessionMemory[sessionId].pBundledContext        = new BundledEffectContext;
+
+        pContext->pBundledContext = GlobalSessionMemory[sessionId].pBundledContext;
+        pContext->pBundledContext->SessionNo                = sessionId;
+        pContext->pBundledContext->hInstance                = NULL;
+        pContext->pBundledContext->bVolumeEnabled           = LVM_FALSE;
+        pContext->pBundledContext->bEqualizerEnabled        = LVM_FALSE;
+        pContext->pBundledContext->bBassEnabled             = LVM_FALSE;
+        pContext->pBundledContext->bBassTempDisabled        = LVM_FALSE;
+        pContext->pBundledContext->bVirtualizerEnabled      = LVM_FALSE;
+        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
+        pContext->pBundledContext->NumberEffectsEnabled     = 0;
+        pContext->pBundledContext->NumberEffectsCalled      = 0;
+        pContext->pBundledContext->frameCount               = 0;
+
+        #ifdef LVM_PCM
+        pContext->pBundledContext->PcmInPtr  = NULL;
+        pContext->pBundledContext->PcmOutPtr = NULL;
+
+        pContext->pBundledContext->PcmInPtr  = fopen("/data/tmp/bundle_pcm_in.pcm", "w");
+        pContext->pBundledContext->PcmOutPtr = fopen("/data/tmp/bundle_pcm_out.pcm", "w");
+
+        if((pContext->pBundledContext->PcmInPtr  == NULL)||
+           (pContext->pBundledContext->PcmOutPtr == NULL)){
+           return -EINVAL;
+        }
+        #endif
+
+        /* Saved strength is used to return the exact strength that was used in the set to the get
+         * because we map the original strength range of 0:1000 to 1:15, and this will avoid
+         * quantisation like effect when returning
+         */
+        pContext->pBundledContext->BassStrengthSaved        = 0;
+        pContext->pBundledContext->VirtStrengthSaved        = 0;
+        pContext->pBundledContext->CurPreset                = PRESET_CUSTOM;
+        pContext->pBundledContext->levelSaved               = 0;
+        pContext->pBundledContext->bMuteEnabled             = LVM_FALSE;
+        pContext->pBundledContext->bStereoPositionEnabled   = LVM_FALSE;
+        pContext->pBundledContext->positionSaved            = 0;
+
+        LOGV("\tEffectCreate - Calling LvmBundle_init");
+        ret = LvmBundle_init(pContext);
+
+        if (ret < 0){
+            LOGV("\tLVM_ERROR : EffectCreate() Bundle init failed");
+            delete pContext->pBundledContext;
+            delete pContext;
+            return ret;
+        }
+    }
+    else{
+        pContext->pBundledContext = GlobalSessionMemory[sessionId].pBundledContext;
+    }
+
+    LOGV("\tEffectCreate - pBundledContext is %p", pContext->pBundledContext);
+
+    // Create each Effect
+    if (memcmp(uuid, &gBassBoostDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+        // Create Bass Boost
+        LOGV("\tEffectCreate - Effect to be created is LVM_BASS_BOOST");
+        GlobalSessionMemory[sessionId].bBassInstantiated = LVM_TRUE;
+
+        pContext->itfe       = &gLvmEffectInterface;
+        pContext->EffectType = LVM_BASS_BOOST;
+    } else if (memcmp(uuid, &gVirtualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+        // Create Virtualizer
+        LOGV("\tEffectCreate - Effect to be created is LVM_VIRTUALIZER");
+        GlobalSessionMemory[sessionId].bVirtualizerInstantiated = LVM_TRUE;
+
+        pContext->itfe       = &gLvmEffectInterface;
+        pContext->EffectType = LVM_VIRTUALIZER;
+    } else if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+        // Create Equalizer
+        LOGV("\tEffectCreate - Effect to be created is LVM_EQUALIZER");
+        GlobalSessionMemory[sessionId].bEqualizerInstantiated = LVM_TRUE;
+
+        pContext->itfe       = &gLvmEffectInterface;
+        pContext->EffectType = LVM_EQUALIZER;
+    } else if (memcmp(uuid, &gVolumeDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+        // Create Volume
+        LOGV("\tEffectCreate - Effect to be created is LVM_VOLUME");
+        GlobalSessionMemory[sessionId].bVolumeInstantiated = LVM_TRUE;
+
+        pContext->itfe       = &gLvmEffectInterface;
+        pContext->EffectType = LVM_VOLUME;
+    }
+    else{
+        LOGV("\tLVM_ERROR : EffectCreate() invalid UUID");
+        return -EINVAL;
+    }
+
+    *pInterface = (effect_interface_t)pContext;
+    LOGV("\tEffectCreate end..\n\n");
+    return 0;
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_interface_t interface){
+    LOGV("\n\tEffectRelease start %p", interface);
+    EffectContext * pContext = (EffectContext *)interface;
+
+    if (pContext == NULL){
+        LOGV("\tLVM_ERROR : EffectRelease called with NULL pointer");
+        return -EINVAL;
+    }
+
+    // Clear the instantiated flag for the effect
+    if(pContext->EffectType == LVM_BASS_BOOST) {
+        LOGV("\tEffectRelease LVM_BASS_BOOST Clearing global intstantiated flag");
+        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBassInstantiated = LVM_FALSE;
+    } else if(pContext->EffectType == LVM_VIRTUALIZER) {
+        LOGV("\tEffectRelease LVM_VIRTUALIZER Clearing global intstantiated flag");
+        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated
+            = LVM_FALSE;
+    } else if(pContext->EffectType == LVM_EQUALIZER) {
+        LOGV("\tEffectRelease LVM_EQUALIZER Clearing global intstantiated flag");
+        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bEqualizerInstantiated =LVM_FALSE;
+    } else if(pContext->EffectType == LVM_VOLUME) {
+        LOGV("\tEffectRelease LVM_VOLUME Clearing global intstantiated flag");
+        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVolumeInstantiated = LVM_FALSE;
+    } else {
+        LOGV("\tLVM_ERROR : EffectRelease : Unsupported effect\n\n\n\n\n\n\n");
+    }
+
+    // if all effects are no longer instantiaed free the lvm memory and delete BundledEffectContext
+    if((GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBassInstantiated == LVM_FALSE)&&
+    (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVolumeInstantiated == LVM_FALSE)&&
+    (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bEqualizerInstantiated ==LVM_FALSE)&&
+    (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated==LVM_FALSE))
+    {
+        #ifdef LVM_PCM
+        fclose(pContext->pBundledContext->PcmInPtr);
+        fclose(pContext->pBundledContext->PcmOutPtr);
+        #endif
+        LOGV("\tEffectRelease: All effects are no longer instantiated\n");
+        GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBundledEffectsEnabled =LVM_FALSE;
+        GlobalSessionMemory[pContext->pBundledContext->SessionNo].pBundledContext = LVM_NULL;
+        LOGV("\tEffectRelease: Freeing LVM Bundle memory\n");
+        LvmEffect_free(pContext);
+        LOGV("\tEffectRelease: Deleting LVM Bundle context\n");
+        delete pContext->pBundledContext;
+    }
+    // free the effect context for current effect
+    delete pContext;
+
+    LOGV("\tEffectRelease end\n");
+    return 0;
+
+} /* end EffectRelease */
+
+void LvmGlobalBundle_init(){
+    LOGV("\tLvmGlobalBundle_init start");
+    for(int i=0; i<LVM_MAX_SESSIONS; i++){
+        GlobalSessionMemory[i].bBundledEffectsEnabled   = LVM_FALSE;
+        GlobalSessionMemory[i].bVolumeInstantiated      = LVM_FALSE;
+        GlobalSessionMemory[i].bEqualizerInstantiated   = LVM_FALSE;
+        GlobalSessionMemory[i].bBassInstantiated        = LVM_FALSE;
+        GlobalSessionMemory[i].bVirtualizerInstantiated = LVM_FALSE;
+        GlobalSessionMemory[i].pBundledContext          = LVM_NULL;
+    }
+    return;
+}
+//----------------------------------------------------------------------------
+// LvmBundle_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration, creates instance
+// with all effects disabled.
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int LvmBundle_init(EffectContext *pContext){
+    int status;
+
+    LOGV("\tLvmBundle_init start");
+
+    pContext->config.inputCfg.accessMode                    = EFFECT_BUFFER_ACCESS_READ;
+    pContext->config.inputCfg.channels                      = CHANNEL_STEREO;
+    pContext->config.inputCfg.format                        = SAMPLE_FORMAT_PCM_S15;
+    pContext->config.inputCfg.samplingRate                  = 44100;
+    pContext->config.inputCfg.bufferProvider.getBuffer      = NULL;
+    pContext->config.inputCfg.bufferProvider.releaseBuffer  = NULL;
+    pContext->config.inputCfg.bufferProvider.cookie         = NULL;
+    pContext->config.inputCfg.mask                          = EFFECT_CONFIG_ALL;
+    pContext->config.outputCfg.accessMode                   = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+    pContext->config.outputCfg.channels                     = CHANNEL_STEREO;
+    pContext->config.outputCfg.format                       = SAMPLE_FORMAT_PCM_S15;
+    pContext->config.outputCfg.samplingRate                 = 44100;
+    pContext->config.outputCfg.bufferProvider.getBuffer     = NULL;
+    pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+    pContext->config.outputCfg.bufferProvider.cookie        = NULL;
+    pContext->config.outputCfg.mask                         = EFFECT_CONFIG_ALL;
+
+    CHECK_ARG(pContext != NULL);
+
+    if (pContext->pBundledContext->hInstance != NULL){
+        LOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
+                "-> Calling pContext->pBassBoost->free()");
+
+        LvmEffect_free(pContext);
+
+        LOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
+                "-> Called pContext->pBassBoost->free()");
+    }
+
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;          /* Function call status */
+    LVM_ControlParams_t     params;                         /* Control Parameters */
+    LVM_InstParams_t        InstParams;                     /* Instance parameters */
+    LVM_EQNB_BandDef_t      BandDefs[MAX_NUM_BANDS];        /* Equaliser band definitions */
+    LVM_HeadroomParams_t    HeadroomParams;                 /* Headroom parameters */
+    LVM_HeadroomBandDef_t   HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS];
+    LVM_MemTab_t            MemTab;                         /* Memory allocation table */
+    bool                    bMallocFailure = LVM_FALSE;
+
+    /* Set the capabilities */
+    InstParams.BufferMode       = LVM_UNMANAGED_BUFFERS;
+    InstParams.MaxBlockSize     = MAX_CALL_SIZE;
+    InstParams.EQNB_NumBands    = MAX_NUM_BANDS;
+    InstParams.PSA_Included     = LVM_PSA_ON;
+
+    /* Allocate memory, forcing alignment */
+    LvmStatus = LVM_GetMemoryTable(LVM_NULL,
+                                  &MemTab,
+                                  &InstParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "LvmBundle_init")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    LOGV("\tCreateInstance Succesfully called LVM_GetMemoryTable\n");
+
+    /* Allocate memory */
+    for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+        if (MemTab.Region[i].Size != 0){
+            MemTab.Region[i].pBaseAddress = malloc(MemTab.Region[i].Size);
+
+            if (MemTab.Region[i].pBaseAddress == LVM_NULL){
+                LOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate %ld bytes for region %u\n",
+                        MemTab.Region[i].Size, i );
+                bMallocFailure = LVM_TRUE;
+            }else{
+                LOGV("\tLvmBundle_init CreateInstance allocated %ld bytes for region %u at %p\n",
+                        MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+            }
+        }
+    }
+
+    /* If one or more of the memory regions failed to allocate, free the regions that were
+     * succesfully allocated and return with an error
+     */
+    if(bMallocFailure == LVM_TRUE){
+        for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+            if (MemTab.Region[i].pBaseAddress == LVM_NULL){
+                LOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate %ld bytes for region %u - +"
+                     "Not freeing\n", MemTab.Region[i].Size, i );
+            }else{
+                LOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed: but allocated %ld bytes "
+                     "for region %u at %p- free\n",
+                     MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+                free(MemTab.Region[i].pBaseAddress);
+            }
+        }
+        return -EINVAL;
+    }
+    LOGV("\tLvmBundle_init CreateInstance Succesfully malloc'd memory\n");
+
+    /* Initialise */
+    pContext->pBundledContext->hInstance = LVM_NULL;
+
+    /* Init sets the instance handle */
+    LvmStatus = LVM_GetInstanceHandle(&pContext->pBundledContext->hInstance,
+                                      &MemTab,
+                                      &InstParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "LvmBundle_init")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    LOGV("\tLvmBundle_init CreateInstance Succesfully called LVM_GetInstanceHandle\n");
+
+    /* Set the initial process parameters */
+    /* General parameters */
+    params.OperatingMode          = LVM_MODE_ON;
+    params.SampleRate             = LVM_FS_44100;
+    params.SourceFormat           = LVM_STEREO;
+    params.SpeakerType            = LVM_HEADPHONES;
+
+    pContext->pBundledContext->SampleRate = LVM_FS_44100;
+
+    /* Concert Sound parameters */
+    params.VirtualizerOperatingMode   = LVM_MODE_OFF;
+    params.VirtualizerType            = LVM_CONCERTSOUND;
+    params.VirtualizerReverbLevel     = 100;
+    params.CS_EffectLevel             = LVM_CS_EFFECT_HIGH;
+
+    /* N-Band Equaliser parameters */
+    params.EQNB_OperatingMode     = LVM_EQNB_OFF;
+    params.EQNB_NBands            = FIVEBAND_NUMBANDS;
+    params.pEQNB_BandDefinition   = &BandDefs[0];
+
+    for (int i=0; i<FIVEBAND_NUMBANDS; i++)
+    {
+        BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
+        BandDefs[i].QFactor   = EQNB_5BandPresetsQFactors[i];
+        BandDefs[i].Gain      = EQNB_5BandSoftPresets[i];
+    }
+
+    /* Volume Control parameters */
+    params.VC_EffectLevel         = 0;
+    params.VC_Balance             = 0;
+
+    /* Treble Enhancement parameters */
+    params.TE_OperatingMode       = LVM_TE_OFF;
+    params.TE_EffectLevel         = 0;
+
+    /* PSA Control parameters */
+    params.PSA_Enable             = LVM_PSA_OFF;
+    params.PSA_PeakDecayRate      = (LVM_PSA_DecaySpeed_en)0;
+
+    /* Bass Enhancement parameters */
+    params.BE_OperatingMode       = LVM_BE_OFF;
+    params.BE_EffectLevel         = 0;
+    params.BE_CentreFreq          = LVM_BE_CENTRE_90Hz;
+    params.BE_HPF                 = LVM_BE_HPF_ON;
+
+    /* PSA Control parameters */
+    params.PSA_Enable             = LVM_PSA_OFF;
+    params.PSA_PeakDecayRate      = LVM_PSA_SPEED_MEDIUM;
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance,
+                                         &params);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    LOGV("\tLvmBundle_init CreateInstance Succesfully called LVM_SetControlParameters\n");
+
+    /* Set the headroom parameters */
+    HeadroomBandDef[0].Limit_Low          = 20;
+    HeadroomBandDef[0].Limit_High         = 4999;
+    HeadroomBandDef[0].Headroom_Offset    = 3;
+    HeadroomBandDef[1].Limit_Low          = 5000;
+    HeadroomBandDef[1].Limit_High         = 24000;
+    HeadroomBandDef[1].Headroom_Offset    = 4;
+    HeadroomParams.pHeadroomDefinition    = &HeadroomBandDef[0];
+    HeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
+    HeadroomParams.NHeadroomBands         = 2;
+
+    LvmStatus = LVM_SetHeadroomParams(pContext->pBundledContext->hInstance,
+                                      &HeadroomParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetHeadroomParams", "LvmBundle_init")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    LOGV("\tLvmBundle_init CreateInstance Succesfully called LVM_SetHeadroomParams\n");
+    LOGV("\tLvmBundle_init End");
+    return 0;
+}   /* end LvmBundle_init */
+
+//----------------------------------------------------------------------------
+// LvmBundle_process()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply LVM Bundle effects
+//
+// Inputs:
+//  pIn:        pointer to stereo 16 bit input data
+//  pOut:       pointer to stereo 16 bit output data
+//  frameCount: Frames to process
+//  pContext:   effect engine context
+//  strength    strength to be applied
+//
+//  Outputs:
+//  pOut:       pointer to updated stereo 16 bit output data
+//
+//----------------------------------------------------------------------------
+
+int LvmBundle_process(LVM_INT16        *pIn,
+                      LVM_INT16        *pOut,
+                      int              frameCount,
+                      EffectContext    *pContext){
+
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+
+    LVM_INT16               *pOutTmp;
+    if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
+        pOutTmp = pOut;
+    }else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+        pOutTmp = (LVM_INT16 *)malloc(frameCount * sizeof(LVM_INT16) * 2);
+        if(pOutTmp == NULL){
+            LOGV("\tLVM_ERROR : LvmBundle_process failed to allocate memory for "
+            "EFFECT_BUFFER_ACCESS_ACCUMULATE mode");
+            return -EINVAL;
+        }
+    }else{
+        LOGV("LVM_ERROR : LvmBundle_process invalid access mode");
+        return -EINVAL;
+    }
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+                                         &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmBundle_process")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    pContext->pBundledContext->frameCount++;
+    if(pContext->pBundledContext->frameCount == 100)
+    {
+        //LOGV("\tBB: %d VIRT: %d EQ: %d, session (%d), context is %p\n",
+        //ActiveParams.BE_OperatingMode,
+        //ActiveParams.VirtualizerOperatingMode, ActiveParams.EQNB_OperatingMode,
+        //pContext->pBundledContext->SessionNo, pContext->pBundledContext);
+        pContext->pBundledContext->frameCount = 0;
+    }
+
+    #ifdef LVM_PCM
+    fwrite(pIn, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmInPtr);
+    fflush(pContext->pBundledContext->PcmInPtr);
+    #endif
+
+    /* Process the samples */
+    LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
+                            pIn,                                  /* Input buffer */
+                            pOutTmp,                              /* Output buffer */
+                            (LVM_UINT16)frameCount,               /* Number of samples to read */
+                            0);                                   /* Audo Time */
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_Process", "LvmBundle_process")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    #ifdef LVM_PCM
+    fwrite(pOutTmp, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmOutPtr);
+    fflush(pContext->pBundledContext->PcmOutPtr);
+    #endif
+
+    if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+        for (int i=0; i<frameCount*2; i++){
+            pOut[i] +=  pOutTmp[i];
+        }
+        free(pOutTmp);
+    }
+    return 0;
+}    /* end LvmBundle_process */
+
+//----------------------------------------------------------------------------
+// LvmEffect_enable()
+//----------------------------------------------------------------------------
+// Purpose: Enable the effect in the bundle
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int LvmEffect_enable(EffectContext *pContext){
+    //LOGV("\tLvmEffect_enable start");
+
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+                                         &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmEffect_enable")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+    //LOGV("\tLvmEffect_enable Succesfully called LVM_GetControlParameters\n");
+
+    if(pContext->EffectType == LVM_BASS_BOOST) {
+        LOGV("\tLvmEffect_enable : Enabling LVM_BASS_BOOST");
+        ActiveParams.BE_OperatingMode       = LVM_BE_ON;
+    }
+    if(pContext->EffectType == LVM_VIRTUALIZER) {
+        LOGV("\tLvmEffect_enable : Enabling LVM_VIRTUALIZER");
+        ActiveParams.VirtualizerOperatingMode   = LVM_MODE_ON;
+    }
+    if(pContext->EffectType == LVM_EQUALIZER) {
+        LOGV("\tLvmEffect_enable : Enabling LVM_EQUALIZER");
+        ActiveParams.EQNB_OperatingMode     = LVM_EQNB_ON;
+    }
+    if(pContext->EffectType == LVM_VOLUME) {
+        LOGV("\tLvmEffect_enable : Enabling LVM_VOLUME");
+    }
+
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_enable")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tLvmEffect_enable Succesfully called LVM_SetControlParameters\n");
+    //LOGV("\tLvmEffect_enable end");
+    return 0;
+}
+
+//----------------------------------------------------------------------------
+// LvmEffect_disable()
+//----------------------------------------------------------------------------
+// Purpose: Disable the effect in the bundle
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int LvmEffect_disable(EffectContext *pContext){
+    //LOGV("\tLvmEffect_disable start");
+
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+                                         &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmEffect_disable")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+    //LOGV("\tLvmEffect_disable Succesfully called LVM_GetControlParameters\n");
+
+    if(pContext->EffectType == LVM_BASS_BOOST) {
+        LOGV("\tLvmEffect_disable : Disabling LVM_BASS_BOOST");
+        ActiveParams.BE_OperatingMode       = LVM_BE_OFF;
+    }
+    if(pContext->EffectType == LVM_VIRTUALIZER) {
+        LOGV("\tLvmEffect_disable : Enabling LVM_VIRTUALIZER");
+        ActiveParams.VirtualizerOperatingMode   = LVM_MODE_OFF;
+    }
+    if(pContext->EffectType == LVM_EQUALIZER) {
+        LOGV("\tLvmEffect_disable : Enabling LVM_EQUALIZER");
+        ActiveParams.EQNB_OperatingMode     = LVM_EQNB_OFF;
+    }
+    if(pContext->EffectType == LVM_VOLUME) {
+        LOGV("\tLvmEffect_disable : Enabling LVM_VOLUME");
+    }
+
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_disable")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tLvmEffect_disable Succesfully called LVM_SetControlParameters\n");
+    //LOGV("\tLvmEffect_disable end");
+    return 0;
+}
+
+//----------------------------------------------------------------------------
+// LvmEffect_free()
+//----------------------------------------------------------------------------
+// Purpose: Free all memory associated with the Bundle.
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+void LvmEffect_free(EffectContext *pContext){
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;         /* Function call status */
+    LVM_ControlParams_t     params;                        /* Control Parameters */
+    LVM_MemTab_t            MemTab;
+
+    /* Free the algorithm memory */
+    LvmStatus = LVM_GetMemoryTable(pContext->pBundledContext->hInstance,
+                                   &MemTab,
+                                   LVM_NULL);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "LvmEffect_free")
+
+    for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+        if (MemTab.Region[i].Size != 0){
+            if (MemTab.Region[i].pBaseAddress != NULL){
+                LOGV("\tLvmEffect_free - START freeing %ld bytes for region %u at %p\n",
+                        MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+
+                free(MemTab.Region[i].pBaseAddress);
+
+                LOGV("\tLvmEffect_free - END   freeing %ld bytes for region %u at %p\n",
+                        MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+            }else{
+                LOGV("\tLVM_ERROR : LvmEffect_free - trying to free with NULL pointer %ld bytes "
+                        "for region %u at %p ERROR\n",
+                        MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+            }
+        }
+    }
+}    /* end LvmEffect_free */
+
+//----------------------------------------------------------------------------
+// Effect_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+//  pContext:   effect engine context
+//  pConfig:    pointer to effect_config_t structure holding input and output
+//      configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Effect_configure(EffectContext *pContext, effect_config_t *pConfig){
+    LVM_Fs_en   SampleRate;
+    //LOGV("\tEffect_configure start");
+
+    CHECK_ARG(pContext != NULL);
+    CHECK_ARG(pConfig != NULL);
+
+    CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
+    CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
+    CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+    CHECK_ARG(pConfig->inputCfg.channels == CHANNEL_STEREO);
+    CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+              || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+    CHECK_ARG(pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S15);
+
+    memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
+
+    switch (pConfig->inputCfg.samplingRate) {
+    case 8000:
+        SampleRate = LVM_FS_8000;
+        break;
+    case 16000:
+        SampleRate = LVM_FS_16000;
+        break;
+    case 22050:
+        SampleRate = LVM_FS_22050;
+        break;
+    case 32000:
+        SampleRate = LVM_FS_32000;
+        break;
+    case 44100:
+        SampleRate = LVM_FS_44100;
+        break;
+    case 48000:
+        SampleRate = LVM_FS_48000;
+        break;
+    default:
+        LOGV("\tEffect_Configure invalid sampling rate %d", pConfig->inputCfg.samplingRate);
+        return -EINVAL;
+    }
+
+    if(pContext->pBundledContext->SampleRate != SampleRate){
+
+        LVM_ControlParams_t     ActiveParams;
+        LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;
+
+        LOGV("\tEffect_configure change sampling rate to %d", SampleRate);
+
+        /* Get the current settings */
+        LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+                                         &ActiveParams);
+
+        LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "Effect_configure")
+        if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+        LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+
+        LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_configure")
+        LOGV("\tEffect_configure Succesfully called LVM_SetControlParameters\n");
+
+    }else{
+        //LOGV("\tEffect_configure keep sampling rate at %d", SampleRate);
+    }
+
+    //LOGV("\tEffect_configure End....");
+    return 0;
+}   /* end Effect_configure */
+
+//----------------------------------------------------------------------------
+// BassGetStrength()
+//----------------------------------------------------------------------------
+// Purpose:
+// get the effect strength currently being used, what is actually returned is the strengh that was
+// previously used in the set, this is because the app uses a strength in the range 0-1000 while
+// the bassboost uses 1-15, so to avoid a quantisation the original set value is used. However the
+// actual used value is checked to make sure it corresponds to the one being returned
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+//----------------------------------------------------------------------------
+
+uint32_t BassGetStrength(EffectContext *pContext){
+    //LOGV("\tBassGetStrength() (0-1000) -> %d\n", pContext->pBundledContext->BassStrengthSaved);
+
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+                                         &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "BassGetStrength")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tBassGetStrength Succesfully returned from LVM_GetControlParameters\n");
+
+    /* Check that the strength returned matches the strength that was set earlier */
+    if(ActiveParams.BE_EffectLevel !=
+       (LVM_INT16)((15*pContext->pBundledContext->BassStrengthSaved)/1000)){
+        LOGV("\tLVM_ERROR : BassGetStrength module strength does not match savedStrength %d %d\n",
+                ActiveParams.BE_EffectLevel, pContext->pBundledContext->BassStrengthSaved);
+        return -EINVAL;
+    }
+
+    //LOGV("\tBassGetStrength() (0-15)   -> %d\n", ActiveParams.BE_EffectLevel );
+    //LOGV("\tBassGetStrength() (saved)  -> %d\n", pContext->pBundledContext->BassStrengthSaved );
+    return pContext->pBundledContext->BassStrengthSaved;
+}    /* end BassGetStrength */
+
+//----------------------------------------------------------------------------
+// BassSetStrength()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the strength to the BassBosst. Must first be converted from the range 0-1000 to 1-15
+//
+// Inputs:
+//  pContext:   effect engine context
+//  strength    strength to be applied
+//
+//----------------------------------------------------------------------------
+
+void BassSetStrength(EffectContext *pContext, uint32_t strength){
+    //LOGV("\tBassSetStrength(%d)", strength);
+
+    pContext->pBundledContext->BassStrengthSaved = (int)strength;
+
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+                                         &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "BassSetStrength")
+    //LOGV("\tBassSetStrength Succesfully returned from LVM_GetControlParameters\n");
+
+    /* Bass Enhancement parameters */
+    ActiveParams.BE_EffectLevel    = (LVM_INT16)((15*strength)/1000);
+    ActiveParams.BE_CentreFreq     = LVM_BE_CENTRE_90Hz;
+
+    //LOGV("\tBassSetStrength() (0-15)   -> %d\n", ActiveParams.BE_EffectLevel );
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "BassSetStrength")
+    //LOGV("\tBassSetStrength Succesfully called LVM_SetControlParameters\n");
+}    /* end BassSetStrength */
+
+//----------------------------------------------------------------------------
+// VirtualizerGetStrength()
+//----------------------------------------------------------------------------
+// Purpose:
+// get the effect strength currently being used, what is actually returned is the strengh that was
+// previously used in the set, this is because the app uses a strength in the range 0-1000 while
+// the Virtualizer uses 1-100, so to avoid a quantisation the original set value is used.However the
+// actual used value is checked to make sure it corresponds to the one being returned
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+//----------------------------------------------------------------------------
+
+uint32_t VirtualizerGetStrength(EffectContext *pContext){
+    //LOGV("\tVirtualizerGetStrength (0-1000) -> %d\n",pContext->pBundledContext->VirtStrengthSaved);
+
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VirtualizerGetStrength")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVirtualizerGetStrength Succesfully returned from LVM_GetControlParameters\n");
+    //LOGV("\tVirtualizerGetStrength() (0-100)   -> %d\n", ActiveParams.VirtualizerReverbLevel*10);
+    return ActiveParams.VirtualizerReverbLevel*10;
+}    /* end getStrength */
+
+//----------------------------------------------------------------------------
+// VirtualizerSetStrength()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the strength to the Virtualizer. Must first be converted from the range 0-1000 to 1-15
+//
+// Inputs:
+//  pContext:   effect engine context
+//  strength    strength to be applied
+//
+//----------------------------------------------------------------------------
+
+void VirtualizerSetStrength(EffectContext *pContext, uint32_t strength){
+    //LOGV("\tVirtualizerSetStrength(%d)", strength);
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    pContext->pBundledContext->VirtStrengthSaved = (int)strength;
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,&ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VirtualizerSetStrength")
+    //LOGV("\tVirtualizerSetStrength Succesfully returned from LVM_GetControlParameters\n");
+
+    /* Virtualizer parameters */
+    ActiveParams.VirtualizerReverbLevel    = (LVM_INT16)(strength/10);
+
+    //LOGV("\tVirtualizerSetStrength() (0-1000)   -> %d\n", strength );
+    //LOGV("\tVirtualizerSetStrength() (0- 100)   -> %d\n", ActiveParams.VirtualizerReverbLevel );
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VirtualizerSetStrength")
+    //LOGV("\tVirtualizerSetStrength Succesfully called LVM_SetControlParameters\n");
+}    /* end setStrength */
+
+//----------------------------------------------------------------------------
+// EqualizerGetBandLevel()
+//----------------------------------------------------------------------------
+// Purpose: Retrieve the gain currently being used for the band passed in
+//
+// Inputs:
+//  band:       band number
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+int32_t EqualizerGetBandLevel(EffectContext *pContext, int32_t band){
+
+    int32_t Gain =0;
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+    LVM_EQNB_BandDef_t      *BandDef;
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+                                         &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerGetBandLevel")
+
+    BandDef = ActiveParams.pEQNB_BandDefinition;
+    Gain    = (int32_t)BandDef[band].Gain*100;    // Convert to millibels
+
+    //LOGV("\tEqualizerGetBandLevel -> %d\n", Gain );
+    //LOGV("\tEqualizerGetBandLevel Succesfully returned from LVM_GetControlParameters\n");
+    return Gain;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerSetBandLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+//  Sets gain value for the given band.
+//
+// Inputs:
+//  band:       band number
+//  Gain:       Gain to be applied in millibels
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//---------------------------------------------------------------------------
+void EqualizerSetBandLevel(EffectContext *pContext, int band, int Gain){
+    int gainRounded;
+    if(Gain > 0){
+        gainRounded = (int)((Gain+50)/100);
+    }else{
+        gainRounded = (int)((Gain-50)/100);
+    }
+    //LOGV("\tEqualizerSetBandLevel(%d)->(%d)", Gain, gainRounded);
+
+
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+    LVM_EQNB_BandDef_t      *BandDef;
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerSetBandLevel")
+    //LOGV("\tEqualizerSetBandLevel Succesfully returned from LVM_GetControlParameters\n");
+    //LOGV("\tEqualizerSetBandLevel just Got -> %d\n", ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+    /* Set local EQ parameters */
+    BandDef = ActiveParams.pEQNB_BandDefinition;
+    ActiveParams.pEQNB_BandDefinition[band].Gain = gainRounded;
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerSetBandLevel")
+    //LOGV("\tEqualizerSetBandLevel just Set -> %d\n", ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+    pContext->pBundledContext->CurPreset = PRESET_CUSTOM;
+    return;
+}
+//----------------------------------------------------------------------------
+// EqualizerGetCentreFrequency()
+//----------------------------------------------------------------------------
+// Purpose: Retrieve the frequency being used for the band passed in
+//
+// Inputs:
+//  band:       band number
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+int32_t EqualizerGetCentreFrequency(EffectContext *pContext, int32_t band){
+    int32_t Frequency =0;
+
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+    LVM_EQNB_BandDef_t      *BandDef;
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+                                         &ActiveParams);
+
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerGetCentreFrequency")
+
+    BandDef   = ActiveParams.pEQNB_BandDefinition;
+    Frequency = (int32_t)BandDef[band].Frequency*1000;     // Convert to millibels
+
+    //LOGV("\tEqualizerGetCentreFrequency -> %d\n", Frequency );
+    //LOGV("\tEqualizerGetCentreFrequency Succesfully returned from LVM_GetControlParameters\n");
+    return Frequency;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerGetBandFreqRange(
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Gets lower and upper boundaries of a band.
+// For the high shelf, the low bound is the band frequency and the high
+// bound is Nyquist.
+// For the peaking filters, they are the gain[dB]/2 points.
+//
+// Inputs:
+//  band:       band number
+//  pContext:   effect engine context
+//
+// Outputs:
+//  pLow:       lower band range
+//  pLow:       upper band range
+//----------------------------------------------------------------------------
+int32_t EqualizerGetBandFreqRange(EffectContext *pContext, int32_t band, uint32_t *pLow,
+                                  uint32_t *pHi){
+    *pLow = bandFreqRange[band][0];
+    *pHi  = bandFreqRange[band][1];
+    return 0;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerGetBand(
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Returns the band with the maximum influence on a given frequency.
+// Result is unaffected by whether EQ is enabled or not, or by whether
+// changes have been committed or not.
+//
+// Inputs:
+//  targetFreq   The target frequency, in millihertz.
+//  pContext:    effect engine context
+//
+// Outputs:
+//  pLow:       lower band range
+//  pLow:       upper band range
+//----------------------------------------------------------------------------
+int32_t EqualizerGetBand(EffectContext *pContext, uint32_t targetFreq){
+    int band = 0;
+
+    if(targetFreq < bandFreqRange[0][0]){
+        return -EINVAL;
+    }else if(targetFreq == bandFreqRange[0][0]){
+        return 0;
+    }
+    for(int i=0; i<FIVEBAND_NUMBANDS;i++){
+        if((targetFreq > bandFreqRange[i][0])&&(targetFreq <= bandFreqRange[i][1])){
+            band = i;
+        }
+    }
+    return band;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerGetPreset(
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Gets the currently set preset ID.
+// Will return PRESET_CUSTOM in case the EQ parameters have been modified
+// manually since a preset was set.
+//
+// Inputs:
+//  pContext:    effect engine context
+//
+//----------------------------------------------------------------------------
+int32_t EqualizerGetPreset(EffectContext *pContext){
+    return pContext->pBundledContext->CurPreset;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerSetPreset(
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Sets the current preset by ID.
+// All the band parameters will be overridden.
+//
+// Inputs:
+//  pContext:    effect engine context
+//  preset       The preset ID.
+//
+//----------------------------------------------------------------------------
+void EqualizerSetPreset(EffectContext *pContext, int preset){
+
+    //LOGV("\tEqualizerSetPreset(%d)", preset);
+    pContext->pBundledContext->CurPreset = preset;
+
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerSetPreset")
+    //LOGV("\tEqualizerSetPreset Succesfully returned from LVM_GetControlParameters\n");
+
+    //ActiveParams.pEQNB_BandDefinition = &BandDefs[0];
+    for (int i=0; i<FIVEBAND_NUMBANDS; i++)
+    {
+        ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
+        ActiveParams.pEQNB_BandDefinition[i].QFactor   = EQNB_5BandPresetsQFactors[i];
+        ActiveParams.pEQNB_BandDefinition[i].Gain
+        = EQNB_5BandSoftPresets[i + preset * FIVEBAND_NUMBANDS];
+    }
+    /* Activate the new settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerSetPreset")
+
+    //LOGV("\tEqualizerSetPreset Succesfully called LVM_SetControlParameters\n");
+    return;
+}
+
+int32_t EqualizerGetNumPresets(){
+    return sizeof(gEqualizerPresets) / sizeof(PresetConfig);
+}
+
+//----------------------------------------------------------------------------
+// EqualizerGetPresetName(
+//----------------------------------------------------------------------------
+// Purpose:
+// Gets a human-readable name for a preset ID. Will return "Custom" if
+// PRESET_CUSTOM is passed.
+//
+// Inputs:
+// preset       The preset ID. Must be less than number of presets.
+//
+//-------------------------------------------------------------------------
+const char * EqualizerGetPresetName(int32_t preset){
+    //LOGV("\tEqualizerGetPresetName start(%d)", preset);
+    if (preset == PRESET_CUSTOM) {
+        return "Custom";
+    } else {
+        return gEqualizerPresets[preset].name;
+    }
+    //LOGV("\tEqualizerGetPresetName end(%d)", preset);
+    return 0;
+}
+
+//----------------------------------------------------------------------------
+// VolumeSetVolumeLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+//  pContext:   effect engine context
+//  level       level to be applied
+//
+//----------------------------------------------------------------------------
+
+int VolumeSetVolumeLevel(EffectContext *pContext, int16_t level){
+
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    //LOGV("\tVolumeSetVolumeLevel Level to be set is %d %d\n", level, (LVM_INT16)(level/100));
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetVolumeLevel")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+    //LOGV("\tVolumeSetVolumeLevel Succesfully returned from LVM_GetControlParameters got: %d\n",
+    //ActiveParams.VC_EffectLevel);
+
+    /* Volume parameters */
+    ActiveParams.VC_EffectLevel  = (LVM_INT16)(level/100);
+    //LOGV("\tVolumeSetVolumeLevel() (-96dB -> 0dB)   -> %d\n", ActiveParams.VC_EffectLevel );
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetVolumeLevel")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVolumeSetVolumeLevel Succesfully called LVM_SetControlParameters\n");
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetVolumeLevel")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVolumeSetVolumeLevel just set (-96dB -> 0dB)   -> %d\n", ActiveParams.VC_EffectLevel );
+    return 0;
+}    /* end setVolumeLevel */
+
+//----------------------------------------------------------------------------
+// VolumeGetVolumeLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+//----------------------------------------------------------------------------
+
+int VolumeGetVolumeLevel(EffectContext *pContext, int16_t *level){
+
+    //LOGV("\tVolumeGetVolumeLevel start");
+
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeGetVolumeLevel")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVolumeGetVolumeLevel() (-96dB -> 0dB) -> %d\n", ActiveParams.VC_EffectLevel );
+    //LOGV("\tVolumeGetVolumeLevel Succesfully returned from LVM_GetControlParameters\n");
+
+    *level = ActiveParams.VC_EffectLevel*100;     // Convert dB to millibels
+    //LOGV("\tVolumeGetVolumeLevel end");
+    return 0;
+}    /* end VolumeGetVolumeLevel */
+
+//----------------------------------------------------------------------------
+// VolumeSetMute()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+//  pContext:   effect engine context
+//  mute:       enable/disable flag
+//
+//----------------------------------------------------------------------------
+
+int32_t VolumeSetMute(EffectContext *pContext, uint32_t mute){
+    //LOGV("\tVolumeSetMute start(%d)", mute);
+
+    pContext->pBundledContext->bMuteEnabled = mute;
+
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetMute")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVolumeSetMute Succesfully returned from LVM_GetControlParameters\n");
+    //LOGV("\tVolumeSetMute to %d, level was %d\n", mute, ActiveParams.VC_EffectLevel );
+
+    /* Set appropriate volume level */
+    if(pContext->pBundledContext->bMuteEnabled == LVM_TRUE){
+        pContext->pBundledContext->levelSaved = ActiveParams.VC_EffectLevel;
+        ActiveParams.VC_EffectLevel           = -96;
+    }else{
+        ActiveParams.VC_EffectLevel  = pContext->pBundledContext->levelSaved;
+    }
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetMute")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVolumeSetMute Succesfully called LVM_SetControlParameters\n");
+    //LOGV("\tVolumeSetMute end");
+    return 0;
+}    /* end setMute */
+
+//----------------------------------------------------------------------------
+// VolumeGetMute()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Ourputs:
+//  mute:       enable/disable flag
+//----------------------------------------------------------------------------
+
+int32_t VolumeGetMute(EffectContext *pContext, uint32_t *mute){
+    //LOGV("\tVolumeGetMute start");
+    if((pContext->pBundledContext->bMuteEnabled == LVM_FALSE)||
+       (pContext->pBundledContext->bMuteEnabled == LVM_TRUE)){
+        *mute = pContext->pBundledContext->bMuteEnabled;
+        return 0;
+    }else{
+        LOGV("\tLVM_ERROR : VolumeGetMute read an invalid value from context %d",
+              pContext->pBundledContext->bMuteEnabled);
+        return -EINVAL;
+    }
+    //LOGV("\tVolumeGetMute end");
+}    /* end getMute */
+
+int16_t VolumeConvertStereoPosition(int16_t position){
+    int16_t convertedPosition = 0;
+
+    convertedPosition = (int16_t)(((float)position/1000)*96);
+    return convertedPosition;
+
+}
+
+//----------------------------------------------------------------------------
+// VolumeSetStereoPosition()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+//  pContext:       effect engine context
+//  position:       stereo position
+//
+// Outputs:
+//----------------------------------------------------------------------------
+
+int VolumeSetStereoPosition(EffectContext *pContext, int16_t position){
+
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+    LVM_INT16               Balance = 0;
+
+    
+
+    pContext->pBundledContext->positionSaved = position;
+    Balance = VolumeConvertStereoPosition(pContext->pBundledContext->positionSaved);
+
+    //LOGV("\tVolumeSetStereoPosition start pContext->pBundledContext->positionSaved = %d", pContext->pBundledContext->positionSaved);
+
+    if(pContext->pBundledContext->bStereoPositionEnabled == LVM_TRUE){
+
+        //LOGV("\tVolumeSetStereoPosition Position to be set is %d %d\n", position, Balance);
+        pContext->pBundledContext->positionSaved = position;
+        /* Get the current settings */
+        LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+        LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetStereoPosition")
+        if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+        //LOGV("\tVolumeSetStereoPosition Succesfully returned from LVM_GetControlParameters got:"
+        //     " %d\n", ActiveParams.VC_Balance);
+
+        /* Volume parameters */
+        ActiveParams.VC_Balance  = Balance;
+        //LOGV("\tVolumeSetStereoPosition() (-96dB -> +96dB)   -> %d\n", ActiveParams.VC_Balance );
+
+        /* Activate the initial settings */
+        LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+        LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetStereoPosition")
+        if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+        //LOGV("\tVolumeSetStereoPosition Succesfully called LVM_SetControlParameters\n");
+
+        /* Get the current settings */
+        LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+        LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetStereoPosition")
+        if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+        //LOGV("\tVolumeSetStereoPosition Succesfully returned from LVM_GetControlParameters got: "
+        //     "%d\n", ActiveParams.VC_Balance);
+    }
+    else{
+        //LOGV("\tVolumeSetStereoPosition Position attempting to set, but not enabled %d %d\n",
+        //position, Balance);
+    }
+    //LOGV("\tVolumeSetStereoPosition end pContext->pBundledContext->positionSaved = %d\n", pContext->pBundledContext->positionSaved);
+    return 0;
+}    /* end VolumeSetStereoPosition */
+
+
+//----------------------------------------------------------------------------
+// VolumeGetStereoPosition()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+//  pContext:       effect engine context
+//
+// Outputs:
+//  position:       stereo position
+//----------------------------------------------------------------------------
+
+int32_t VolumeGetStereoPosition(EffectContext *pContext, int16_t *position){
+    //LOGV("\tVolumeGetStereoPosition start");
+
+    LVM_ControlParams_t     ActiveParams;                           /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus = LVM_SUCCESS;                /* Function call status */
+    LVM_INT16               balance;
+
+    //LOGV("\tVolumeGetStereoPosition start pContext->pBundledContext->positionSaved = %d", pContext->pBundledContext->positionSaved);
+
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeGetStereoPosition")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVolumeGetStereoPosition -> %d\n", ActiveParams.VC_Balance);
+    //LOGV("\tVolumeGetStereoPosition Succesfully returned from LVM_GetControlParameters\n");
+
+    balance = VolumeConvertStereoPosition(pContext->pBundledContext->positionSaved);
+
+    if(pContext->pBundledContext->bStereoPositionEnabled == LVM_TRUE){
+        if(balance != ActiveParams.VC_Balance){
+            return -EINVAL;
+        }
+    }
+    *position = (LVM_INT16)pContext->pBundledContext->positionSaved;     // Convert dB to millibels
+    //LOGV("\tVolumeGetStereoPosition end returning pContext->pBundledContext->positionSaved = %d\n", pContext->pBundledContext->positionSaved);
+    return 0;
+}    /* end VolumeGetStereoPosition */
+
+//----------------------------------------------------------------------------
+// VolumeEnableStereoPosition()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+//  pContext:   effect engine context
+//  mute:       enable/disable flag
+//
+//----------------------------------------------------------------------------
+
+int32_t VolumeEnableStereoPosition(EffectContext *pContext, uint32_t enabled){
+    //LOGV("\tVolumeEnableStereoPosition start()");
+
+    pContext->pBundledContext->bStereoPositionEnabled = enabled;
+
+    LVM_ControlParams_t     ActiveParams;              /* Current control Parameters */
+    LVM_ReturnStatus_en     LvmStatus=LVM_SUCCESS;     /* Function call status */
+
+    /* Get the current settings */
+    LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeEnableStereoPosition")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVolumeEnableStereoPosition Succesfully returned from LVM_GetControlParameters\n");
+    //LOGV("\tVolumeEnableStereoPosition to %d, position was %d\n",
+    //     enabled, ActiveParams.VC_Balance );
+
+    /* Set appropriate stereo position */
+    if(pContext->pBundledContext->bStereoPositionEnabled == LVM_FALSE){
+        ActiveParams.VC_Balance = 0;
+    }else{
+        ActiveParams.VC_Balance  =
+                            VolumeConvertStereoPosition(pContext->pBundledContext->positionSaved);
+    }
+
+    /* Activate the initial settings */
+    LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+    LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeEnableStereoPosition")
+    if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+    //LOGV("\tVolumeEnableStereoPosition Succesfully called LVM_SetControlParameters\n");
+    //LOGV("\tVolumeEnableStereoPosition end()\n");
+    return 0;
+}    /* end VolumeEnableStereoPosition */
+
+//----------------------------------------------------------------------------
+// BassBoost_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a BassBoost parameter
+//
+// Inputs:
+//  pBassBoost       - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to variable to hold retrieved value
+//  pValueSize       - pointer to value size: maximum size as input
+//
+// Outputs:
+//  *pValue updated with parameter value
+//  *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int BassBoost_getParameter(EffectContext     *pContext,
+                           int32_t           *pParam,
+                           size_t            *pValueSize,
+                           void              *pValue){
+    int status = 0;
+    int32_t param = *pParam++;
+    int32_t param2;
+    char *name;
+
+    //LOGV("\tBassBoost_getParameter start");
+
+    switch (param){
+        case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
+        case BASSBOOST_PARAM_STRENGTH:
+            if (*pValueSize != sizeof(int16_t)){
+                LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize2 %d", *pValueSize);
+                return -EINVAL;
+            }
+            *pValueSize = sizeof(int16_t);
+            break;
+
+        default:
+            LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
+            return -EINVAL;
+    }
+
+    switch (param){
+        case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
+            *(uint32_t *)pValue = 1;
+
+            //LOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH_SUPPORTED Value is %d",
+            //        *(uint32_t *)pValue);
+            break;
+
+        case BASSBOOST_PARAM_STRENGTH:
+            *(int16_t *)pValue = BassGetStrength(pContext);
+
+            //LOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH Value is %d",
+            //        *(int16_t *)pValue);
+            break;
+
+        default:
+            LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
+            status = -EINVAL;
+            break;
+    }
+
+    //LOGV("\tBassBoost_getParameter end");
+    return status;
+} /* end BassBoost_getParameter */
+
+//----------------------------------------------------------------------------
+// BassBoost_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a BassBoost parameter
+//
+// Inputs:
+//  pBassBoost       - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int BassBoost_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+    int status = 0;
+    int16_t strength;
+
+    //LOGV("\tBassBoost_setParameter start");
+
+    switch (*pParam){
+        case BASSBOOST_PARAM_STRENGTH:
+            strength = *(int16_t *)pValue;
+            //LOGV("\tBassBoost_setParameter() BASSBOOST_PARAM_STRENGTH value is %d", strength);
+            //LOGV("\tBassBoost_setParameter() Calling pBassBoost->BassSetStrength");
+            BassSetStrength(pContext, (int32_t)strength);
+            //LOGV("\tBassBoost_setParameter() Called pBassBoost->BassSetStrength");
+           break;
+        default:
+            LOGV("\tLVM_ERROR : BassBoost_setParameter() invalid param %d", *pParam);
+            break;
+    }
+
+    //LOGV("\tBassBoost_setParameter end");
+    return status;
+} /* end BassBoost_setParameter */
+
+//----------------------------------------------------------------------------
+// Virtualizer_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Virtualizer parameter
+//
+// Inputs:
+//  pVirtualizer     - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to variable to hold retrieved value
+//  pValueSize       - pointer to value size: maximum size as input
+//
+// Outputs:
+//  *pValue updated with parameter value
+//  *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Virtualizer_getParameter(EffectContext        *pContext,
+                             int32_t              *pParam,
+                             size_t               *pValueSize,
+                             void                 *pValue){
+    int status = 0;
+    int32_t param = *pParam++;
+    int32_t param2;
+    char *name;
+
+    //LOGV("\tVirtualizer_getParameter start");
+
+    switch (param){
+        case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
+        case VIRTUALIZER_PARAM_STRENGTH:
+            if (*pValueSize != sizeof(int16_t)){
+                LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize2 %d",*pValueSize);
+                return -EINVAL;
+            }
+            *pValueSize = sizeof(int16_t);
+            break;
+
+        default:
+            LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
+            return -EINVAL;
+    }
+
+    switch (param){
+        case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
+            *(uint32_t *)pValue = 1;
+
+            //LOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH_SUPPORTED Value is %d",
+            //        *(uint32_t *)pValue);
+            break;
+
+        case VIRTUALIZER_PARAM_STRENGTH:
+            *(int16_t *)pValue = VirtualizerGetStrength(pContext);
+
+            //LOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH Value is %d",
+            //        *(int16_t *)pValue);
+            break;
+
+        default:
+            LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
+            status = -EINVAL;
+            break;
+    }
+
+    //LOGV("\tVirtualizer_getParameter end");
+    return status;
+} /* end Virtualizer_getParameter */
+
+//----------------------------------------------------------------------------
+// Virtualizer_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Virtualizer parameter
+//
+// Inputs:
+//  pVirtualizer     - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Virtualizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+    int status = 0;
+    int16_t strength;
+
+    //LOGV("\tVirtualizer_setParameter start");
+
+    switch (*pParam){
+        case VIRTUALIZER_PARAM_STRENGTH:
+            strength = *(int16_t *)pValue;
+            //LOGV("\tVirtualizer_setParameter() VIRTUALIZER_PARAM_STRENGTH value is %d", strength);
+            //LOGV("\tVirtualizer_setParameter() Calling pVirtualizer->setStrength");
+            VirtualizerSetStrength(pContext, (int32_t)strength);
+            //LOGV("\tVirtualizer_setParameter() Called pVirtualizer->setStrength");
+           break;
+        default:
+            LOGV("\tLVM_ERROR : Virtualizer_setParameter() invalid param %d", *pParam);
+            break;
+    }
+
+    //LOGV("\tVirtualizer_setParameter end");
+    return status;
+} /* end Virtualizer_setParameter */
+
+//----------------------------------------------------------------------------
+// Equalizer_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Equalizer parameter
+//
+// Inputs:
+//  pEqualizer       - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to variable to hold retrieved value
+//  pValueSize       - pointer to value size: maximum size as input
+//
+// Outputs:
+//  *pValue updated with parameter value
+//  *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+int Equalizer_getParameter(EffectContext     *pContext,
+                           int32_t           *pParam,
+                           size_t            *pValueSize,
+                           void              *pValue){
+    int status = 0;
+    int bMute = 0;
+    int32_t param = *pParam++;
+    int32_t param2;
+    char *name;
+
+    //LOGV("\tEqualizer_getParameter start");
+
+    switch (param) {
+    case EQ_PARAM_NUM_BANDS:
+    case EQ_PARAM_CUR_PRESET:
+    case EQ_PARAM_GET_NUM_OF_PRESETS:
+    case EQ_PARAM_BAND_LEVEL:
+    case EQ_PARAM_GET_BAND:
+        if (*pValueSize < sizeof(int16_t)) {
+            LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1  %d", *pValueSize);
+            return -EINVAL;
+        }
+        *pValueSize = sizeof(int16_t);
+        break;
+
+    case EQ_PARAM_LEVEL_RANGE:
+        if (*pValueSize < 2 * sizeof(int16_t)) {
+            LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 2  %d", *pValueSize);
+            return -EINVAL;
+        }
+        *pValueSize = 2 * sizeof(int16_t);
+        break;
+
+    case EQ_PARAM_BAND_FREQ_RANGE:
+        if (*pValueSize < 2 * sizeof(int32_t)) {
+            LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 2  %d", *pValueSize);
+            return -EINVAL;
+        }
+        *pValueSize = 2 * sizeof(int32_t);
+        break;
+
+    case EQ_PARAM_CENTER_FREQ:
+        if (*pValueSize < sizeof(int32_t)) {
+            LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1  %d", *pValueSize);
+            return -EINVAL;
+        }
+        *pValueSize = sizeof(int32_t);
+        break;
+
+    case EQ_PARAM_GET_PRESET_NAME:
+        break;
+
+    case EQ_PARAM_PROPERTIES:
+        if (*pValueSize < (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t)) {
+            LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1  %d", *pValueSize);
+            return -EINVAL;
+        }
+        *pValueSize = (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t);
+        break;
+
+    default:
+        LOGV("\tLVM_ERROR : Equalizer_getParameter unknown param %d", param);
+        return -EINVAL;
+    }
+
+    switch (param) {
+    case EQ_PARAM_NUM_BANDS:
+        *(uint16_t *)pValue = (uint16_t)FIVEBAND_NUMBANDS;
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
+        break;
+
+    case EQ_PARAM_LEVEL_RANGE:
+        *(int16_t *)pValue = -1500;
+        *((int16_t *)pValue + 1) = 1500;
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
+        //      *(int32_t *)pValue, *((int32_t *)pValue + 1));
+        break;
+
+    case EQ_PARAM_BAND_LEVEL:
+        param2 = *pParam;
+        if (param2 >= FIVEBAND_NUMBANDS) {
+            status = -EINVAL;
+            break;
+        }
+        *(int16_t *)pValue = (int16_t)EqualizerGetBandLevel(pContext, param2);
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
+        //      param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_CENTER_FREQ:
+        param2 = *pParam;
+        if (param2 >= FIVEBAND_NUMBANDS) {
+            status = -EINVAL;
+            break;
+        }
+        *(int32_t *)pValue = EqualizerGetCentreFrequency(pContext, param2);
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
+        //      param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_BAND_FREQ_RANGE:
+        param2 = *pParam;
+        if (param2 >= FIVEBAND_NUMBANDS) {
+            status = -EINVAL;
+            break;
+        }
+        EqualizerGetBandFreqRange(pContext, param2, (uint32_t *)pValue, ((uint32_t *)pValue + 1));
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
+        //      param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
+        break;
+
+    case EQ_PARAM_GET_BAND:
+        param2 = *pParam;
+        *(uint16_t *)pValue = (uint16_t)EqualizerGetBand(pContext, param2);
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
+        //      param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_CUR_PRESET:
+        *(uint16_t *)pValue = (uint16_t)EqualizerGetPreset(pContext);
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_GET_NUM_OF_PRESETS:
+        *(uint16_t *)pValue = (uint16_t)EqualizerGetNumPresets();
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
+        break;
+
+    case EQ_PARAM_GET_PRESET_NAME:
+        param2 = *pParam;
+        if (param2 >= EqualizerGetNumPresets()) {
+        //if (param2 >= 20) {     // AGO FIX
+            status = -EINVAL;
+            break;
+        }
+        name = (char *)pValue;
+        strncpy(name, EqualizerGetPresetName(param2), *pValueSize - 1);
+        name[*pValueSize - 1] = 0;
+        *pValueSize = strlen(name) + 1;
+        //LOGV("\tEqualizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
+        //      param2, gEqualizerPresets[param2].name, *pValueSize);
+        break;
+
+    case EQ_PARAM_PROPERTIES: {
+        int16_t *p = (int16_t *)pValue;
+        LOGV("\tEqualizer_getParameter() EQ_PARAM_PROPERTIES");
+        p[0] = (int16_t)EqualizerGetPreset(pContext);
+        p[1] = (int16_t)FIVEBAND_NUMBANDS;
+        for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+            p[2 + i] = (int16_t)EqualizerGetBandLevel(pContext, i);
+        }
+    } break;
+
+    default:
+        LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid param %d", param);
+        status = -EINVAL;
+        break;
+    }
+
+    //LOGV("\tEqualizer_getParameter end");
+    return status;
+} /* end Equalizer_getParameter */
+
+//----------------------------------------------------------------------------
+// Equalizer_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Equalizer parameter
+//
+// Inputs:
+//  pEqualizer    - handle to instance data
+//  pParam        - pointer to parameter
+//  pValue        - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+int Equalizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+    int status = 0;
+    int32_t preset;
+    int32_t band;
+    int32_t level;
+    int32_t param = *pParam++;
+
+    //LOGV("\tEqualizer_setParameter start");
+    switch (param) {
+    case EQ_PARAM_CUR_PRESET:
+        preset = (int32_t)(*(uint16_t *)pValue);
+
+        //LOGV("\tEqualizer_setParameter() EQ_PARAM_CUR_PRESET %d", preset);
+        if ((preset >= EqualizerGetNumPresets())||(preset < 0)) {
+            status = -EINVAL;
+            break;
+        }
+        EqualizerSetPreset(pContext, preset);
+        break;
+    case EQ_PARAM_BAND_LEVEL:
+        band =  *pParam;
+        level = (int32_t)(*(int16_t *)pValue);
+        //LOGV("\tEqualizer_setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
+        if (band >= FIVEBAND_NUMBANDS) {
+            status = -EINVAL;
+            break;
+        }
+        EqualizerSetBandLevel(pContext, band, level);
+        break;
+    case EQ_PARAM_PROPERTIES: {
+        //LOGV("\tEqualizer_setParameter() EQ_PARAM_PROPERTIES");
+        int16_t *p = (int16_t *)pValue;
+        if ((int)p[0] >= EqualizerGetNumPresets()) {
+            status = -EINVAL;
+            break;
+        }
+        if (p[0] >= 0) {
+            EqualizerSetPreset(pContext, (int)p[0]);
+        } else {
+            if ((int)p[1] != FIVEBAND_NUMBANDS) {
+                status = -EINVAL;
+                break;
+            }
+            for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+                EqualizerSetBandLevel(pContext, i, (int)p[2 + i]);
+            }
+        }
+    } break;
+    default:
+        LOGV("\tLVM_ERROR : setParameter() invalid param %d", param);
+        status = -EINVAL;
+        break;
+    }
+
+    //LOGV("\tEqualizer_setParameter end");
+    return status;
+} /* end Equalizer_setParameter */
+
+//----------------------------------------------------------------------------
+// Volume_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Volume parameter
+//
+// Inputs:
+//  pVolume          - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to variable to hold retrieved value
+//  pValueSize       - pointer to value size: maximum size as input
+//
+// Outputs:
+//  *pValue updated with parameter value
+//  *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Volume_getParameter(EffectContext     *pContext,
+                        int32_t           *pParam,
+                        size_t            *pValueSize,
+                        void              *pValue){
+    int status = 0;
+    int bMute = 0;
+    int32_t param = *pParam++;
+    int32_t param2;
+    char *name;
+
+    LOGV("\tVolume_getParameter start");
+
+    switch (param){
+        case VOLUME_PARAM_LEVEL:
+        case VOLUME_PARAM_MAXLEVEL:
+        case VOLUME_PARAM_STEREOPOSITION:
+            if (*pValueSize != sizeof(int16_t)){
+                LOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 1  %d", *pValueSize);
+                return -EINVAL;
+            }
+            *pValueSize = sizeof(int16_t);
+            break;
+
+        case VOLUME_PARAM_MUTE:
+        case VOLUME_PARAM_ENABLESTEREOPOSITION:
+            if (*pValueSize < sizeof(int32_t)){
+                LOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 2  %d", *pValueSize);
+                return -EINVAL;
+            }
+            *pValueSize = sizeof(int32_t);
+            break;
+
+        default:
+            LOGV("\tLVM_ERROR : Volume_getParameter unknown param %d", param);
+            return -EINVAL;
+    }
+
+    switch (param){
+        case VOLUME_PARAM_LEVEL:
+            status = VolumeGetVolumeLevel(pContext, (int16_t *)(pValue));
+            LOGV("\tVolume_getParameter() VOLUME_PARAM_LEVEL Value is %d",
+                    *(int16_t *)pValue);
+            break;
+
+        case VOLUME_PARAM_MAXLEVEL:
+            *(int16_t *)pValue = 0;
+            LOGV("\tVolume_getParameter() VOLUME_PARAM_MAXLEVEL Value is %d",
+                    *(int16_t *)pValue);
+            break;
+
+        case VOLUME_PARAM_STEREOPOSITION:
+            VolumeGetStereoPosition(pContext, (int16_t *)pValue);
+            LOGV("\tVolume_getParameter() VOLUME_PARAM_STEREOPOSITION Value is %d",
+                    *(int16_t *)pValue);
+            break;
+
+        case VOLUME_PARAM_MUTE:
+            status = VolumeGetMute(pContext, (uint32_t *)pValue);
+            LOGV("\tVolume_getParameter() VOLUME_PARAM_MUTE Value is %d",
+                    *(uint32_t *)pValue);
+            break;
+
+        case VOLUME_PARAM_ENABLESTEREOPOSITION:
+            *(int32_t *)pValue = pContext->pBundledContext->bStereoPositionEnabled;
+            LOGV("\tVolume_getParameter() VOLUME_PARAM_ENABLESTEREOPOSITION Value is %d",
+                    *(uint32_t *)pValue);
+            break;
+
+        default:
+            LOGV("\tLVM_ERROR : Volume_getParameter() invalid param %d", param);
+            status = -EINVAL;
+            break;
+    }
+
+    //LOGV("\tVolume_getParameter end");
+    return status;
+} /* end Volume_getParameter */
+
+
+//----------------------------------------------------------------------------
+// Volume_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Volume parameter
+//
+// Inputs:
+//  pVolume       - handle to instance data
+//  pParam        - pointer to parameter
+//  pValue        - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Volume_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+    int      status = 0;
+    int16_t  level;
+    int16_t  position;
+    uint32_t mute;
+    uint32_t positionEnabled;
+
+    LOGV("\tVolume_setParameter start");
+
+    switch (*pParam){
+        case VOLUME_PARAM_LEVEL:
+            level = *(int16_t *)pValue;
+            LOGV("\tVolume_setParameter() VOLUME_PARAM_LEVEL value is %d", level);
+            LOGV("\tVolume_setParameter() Calling pVolume->setVolumeLevel");
+            status = VolumeSetVolumeLevel(pContext, (int16_t)level);
+            LOGV("\tVolume_setParameter() Called pVolume->setVolumeLevel");
+            break;
+
+        case VOLUME_PARAM_MUTE:
+            mute = *(uint32_t *)pValue;
+            LOGV("\tVolume_setParameter() Calling pVolume->setMute, mute is %d", mute);
+            LOGV("\tVolume_setParameter() Calling pVolume->setMute");
+            status = VolumeSetMute(pContext, mute);
+            LOGV("\tVolume_setParameter() Called pVolume->setMute");
+            break;
+
+        case VOLUME_PARAM_ENABLESTEREOPOSITION:
+            positionEnabled = *(uint32_t *)pValue;
+            status = VolumeEnableStereoPosition(pContext, positionEnabled);
+            status = VolumeSetStereoPosition(pContext, pContext->pBundledContext->positionSaved);
+            LOGV("\tVolume_setParameter() VOLUME_PARAM_ENABLESTEREOPOSITION called");
+            break;
+
+        case VOLUME_PARAM_STEREOPOSITION:
+            position = *(int16_t *)pValue;
+            LOGV("\tVolume_setParameter() VOLUME_PARAM_STEREOPOSITION value is %d", position);
+            LOGV("\tVolume_setParameter() Calling pVolume->VolumeSetStereoPosition");
+            status = VolumeSetStereoPosition(pContext, (int16_t)position);
+            LOGV("\tVolume_setParameter() Called pVolume->VolumeSetStereoPosition");
+            break;
+
+        default:
+            LOGV("\tLVM_ERROR : Volume_setParameter() invalid param %d", *pParam);
+            break;
+    }
+
+    //LOGV("\tVolume_setParameter end");
+    return status;
+} /* end Volume_setParameter */
+
+/****************************************************************************************
+ * Name : LVC_ToDB_s32Tos16()
+ *  Input       : Signed 32-bit integer
+ *  Output      : Signed 16-bit integer
+ *                  MSB (16) = sign bit
+ *                  (15->05) = integer part
+ *                  (04->01) = decimal part
+ *  Returns     : Db value with respect to full scale
+ *  Description :
+ *  Remarks     :
+ ****************************************************************************************/
+
+LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix)
+{
+    LVM_INT16   db_fix;
+    LVM_INT16   Shift;
+    LVM_INT16   SmallRemainder;
+    LVM_UINT32  Remainder = (LVM_UINT32)Lin_fix;
+
+    /* Count leading bits, 1 cycle in assembly*/
+    for (Shift = 0; Shift<32; Shift++)
+    {
+        if ((Remainder & 0x80000000U)!=0)
+        {
+            break;
+        }
+        Remainder = Remainder << 1;
+    }
+
+    /*
+     * Based on the approximation equation (for Q11.4 format):
+     *
+     * dB = -96 * Shift + 16 * (8 * Remainder - 2 * Remainder^2)
+     */
+    db_fix    = (LVM_INT16)(-96 * Shift);               /* Six dB steps in Q11.4 format*/
+    SmallRemainder = (LVM_INT16)((Remainder & 0x7fffffff) >> 24);
+    db_fix = (LVM_INT16)(db_fix + SmallRemainder );
+    SmallRemainder = (LVM_INT16)(SmallRemainder * SmallRemainder);
+    db_fix = (LVM_INT16)(db_fix - (LVM_INT16)((LVM_UINT16)SmallRemainder >> 9));
+
+    /* Correct for small offset */
+    db_fix = (LVM_INT16)(db_fix - 5);
+
+    return db_fix;
+}
+
+} // namespace
+} // namespace
+
+/* Effect Control Interface Implementation: Process */
+extern "C" int Effect_process(effect_interface_t     self,
+                              audio_buffer_t         *inBuffer,
+                              audio_buffer_t         *outBuffer){
+    EffectContext * pContext = (EffectContext *) self;
+    int    status = 0;
+    int    lvmStatus = 0;
+    LVM_INT16   *in  = (LVM_INT16 *)inBuffer->raw;
+    LVM_INT16   *out = (LVM_INT16 *)outBuffer->raw;
+
+    //LOGV("\tEffect_process Start : Enabled = %d     Called = %d",
+    //pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled);
+
+    if (pContext == NULL){
+        LOGV("\tLVM_ERROR : Effect_process() ERROR pContext == NULL");
+        return -EINVAL;
+    }
+    if (inBuffer == NULL  || inBuffer->raw == NULL  ||
+            outBuffer == NULL || outBuffer->raw == NULL ||
+            inBuffer->frameCount != outBuffer->frameCount){
+        LOGV("\tLVM_ERROR : Effect_process() ERROR NULL INPUT POINTER OR FRAME COUNT IS WRONG");
+        return -EINVAL;
+    }
+    if ((pContext->pBundledContext->bBassEnabled == LVM_FALSE)&&
+        (pContext->EffectType == LVM_BASS_BOOST)){
+        LOGV("\tEffect_process() ERROR LVM_BASS_BOOST Effect is not enabled");
+        status = -ENODATA;
+    }
+    if ((pContext->pBundledContext->bVolumeEnabled == LVM_FALSE)&&
+        (pContext->EffectType == LVM_VOLUME)){
+        LOGV("\tEffect_process() ERROR LVM_VOLUME Effect is not enabled");
+        status = -ENODATA;
+    }
+    if ((pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE)&&
+        (pContext->EffectType == LVM_EQUALIZER)){
+        LOGV("\tEffect_process() ERROR LVM_EQUALIZER Effect is not enabled");
+        status = -ENODATA;
+    }
+    if ((pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE)&&
+        (pContext->EffectType == LVM_VIRTUALIZER)){
+        LOGV("\tEffect_process() ERROR LVM_VIRTUALIZER Effect is not enabled");
+        status = -ENODATA;
+    }
+
+    // If this is the last frame of an effect process its output with no effect
+    if(status == -ENODATA){
+        if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+            //LOGV("\tLVM_ERROR : Effect_process() accumulating last frame into output buffer");
+            //LOGV("\tLVM_ERROR : Effect_process() trying copying last frame into output buffer");
+            //LOGV("\tLVM_ERROR : Enabled = %d     Called = %d",
+            //pContext->pBundledContext->NumberEffectsEnabled,
+            //pContext->pBundledContext->NumberEffectsCalled);
+
+        }else{
+            //LOGV("\tLVM_ERROR : Effect_process() copying last frame into output buffer");
+        }
+    }
+
+    if(status != -ENODATA){
+        pContext->pBundledContext->NumberEffectsCalled++;
+    }
+
+    if(pContext->pBundledContext->NumberEffectsCalled ==
+       pContext->pBundledContext->NumberEffectsEnabled){
+        //LOGV("\tEffect_process Calling process with %d effects enabled, %d called: Effect %d",
+        //pContext->pBundledContext->NumberEffectsEnabled,
+        //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
+
+        if(status == -ENODATA){
+            //LOGV("\tLVM_ERROR : Effect_process() actually processing last frame");
+        }
+        pContext->pBundledContext->NumberEffectsCalled = 0;
+        /* Process all the available frames, block processing is
+           handled internalLY by the LVM bundle */
+        lvmStatus = android::LvmBundle_process(    (LVM_INT16 *)inBuffer->raw,
+                                                (LVM_INT16 *)outBuffer->raw,
+                                                outBuffer->frameCount,
+                                                pContext);
+        if(lvmStatus != LVM_SUCCESS){
+            LOGV("\tLVM_ERROR : LvmBundle_process returned error %d", lvmStatus);
+            return lvmStatus;
+        }
+    }else{
+        //LOGV("\tEffect_process Not Calling process with %d effects enabled, %d called: Effect %d",
+        //pContext->pBundledContext->NumberEffectsEnabled,
+        //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
+        // 2 is for stereo input
+        memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount*sizeof(LVM_INT16)*2);
+    }
+
+    return status;
+}   /* end Effect_process */
+
+/* Effect Control Interface Implementation: Command */
+extern "C" int Effect_command(effect_interface_t  self,
+                              uint32_t            cmdCode,
+                              uint32_t            cmdSize,
+                              void                *pCmdData,
+                              uint32_t            *replySize,
+                              void                *pReplyData){
+    EffectContext * pContext = (EffectContext *) self;
+    int retsize;
+
+    //LOGV("\t\nEffect_command start");
+
+    if(pContext->EffectType == LVM_BASS_BOOST){
+        //LOGV("\tEffect_command setting command for LVM_BASS_BOOST");
+    }
+    if(pContext->EffectType == LVM_VIRTUALIZER){
+        //LOGV("\tEffect_command setting command for LVM_VIRTUALIZER");
+    }
+    if(pContext->EffectType == LVM_EQUALIZER){
+        //LOGV("\tEffect_command setting command for LVM_EQUALIZER");
+    }
+    if(pContext->EffectType == LVM_VOLUME){
+        //LOGV("\tEffect_command setting command for LVM_VOLUME");
+    }
+
+    if (pContext == NULL){
+        LOGV("\tLVM_ERROR : Effect_command ERROR pContext == NULL");
+        return -EINVAL;
+    }
+
+    //LOGV("\tEffect_command INPUTS are: command %d cmdSize %d",cmdCode, cmdSize);
+
+    // Incase we disable an effect, next time process is
+    // called the number of effect called could be greater
+    // pContext->pBundledContext->NumberEffectsCalled = 0;
+
+    //LOGV("\tEffect_command NumberEffectsCalled = %d, NumberEffectsEnabled = %d",
+    //        pContext->pBundledContext->NumberEffectsCalled,
+    //        pContext->pBundledContext->NumberEffectsEnabled);
+
+    switch (cmdCode){
+        case EFFECT_CMD_INIT:
+            if (pReplyData == NULL || *replySize != sizeof(int)){
+                LOGV("\tLVM_ERROR, EFFECT_CMD_INIT: ERROR for effect type %d",
+                        pContext->EffectType);
+                return -EINVAL;
+            }
+            *(int *) pReplyData = 0;
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT start");
+            if(pContext->EffectType == LVM_BASS_BOOST){
+                //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_BASS_BOOST");
+                android::BassSetStrength(pContext, 0);
+            }
+            if(pContext->EffectType == LVM_VIRTUALIZER){
+                //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_VIRTUALIZER");
+                android::VirtualizerSetStrength(pContext, 0);
+            }
+            if(pContext->EffectType == LVM_EQUALIZER){
+                //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_EQUALIZER");
+                android::EqualizerSetPreset(pContext, 0);
+            }
+            if(pContext->EffectType == LVM_VOLUME){
+                //LOGV("\tEffect_command cmdCode Case: "
+                //        "EFFECT_CMD_INIT start");
+                *(int *) pReplyData = android::VolumeSetVolumeLevel(pContext, 0);
+            }
+            break;
+
+        case EFFECT_CMD_CONFIGURE:
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_CONFIGURE start");
+            if (pCmdData    == NULL||
+                cmdSize     != sizeof(effect_config_t)||
+                pReplyData  == NULL||
+                *replySize  != sizeof(int)){
+                LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+                        "EFFECT_CMD_CONFIGURE: ERROR");
+                return -EINVAL;
+            }
+            *(int *) pReplyData = android::Effect_configure(pContext, (effect_config_t *) pCmdData);
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_CONFIGURE end");
+            break;
+
+        case EFFECT_CMD_RESET:
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_RESET start");
+            android::Effect_configure(pContext, &pContext->config);
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_RESET end");
+            break;
+
+        case EFFECT_CMD_GET_PARAM:{
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM start");
+
+            if(pContext->EffectType == LVM_BASS_BOOST){
+                if (pCmdData == NULL ||
+                        cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                        pReplyData == NULL ||
+                        *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+                    LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+                            "EFFECT_CMD_GET_PARAM: ERROR");
+                    return -EINVAL;
+                }
+                effect_param_t *p = (effect_param_t *)pCmdData;
+
+                memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+                p = (effect_param_t *)pReplyData;
+
+                int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+                p->status = android::BassBoost_getParameter(pContext,
+                                                            (int32_t *)p->data,
+                                                            (size_t  *)&p->vsize,
+                                                            p->data + voffset);
+
+                *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+                //LOGV("\tBassBoost_command EFFECT_CMD_GET_PARAM "
+                //        "*pCmdData %d, *replySize %d, *pReplyData %d ",
+                //        *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+                //        *replySize,
+                //        *(int16_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset));
+            }
+
+            if(pContext->EffectType == LVM_VIRTUALIZER){
+                if (pCmdData == NULL ||
+                        cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                        pReplyData == NULL ||
+                        *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+                    LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+                            "EFFECT_CMD_GET_PARAM: ERROR");
+                    return -EINVAL;
+                }
+                effect_param_t *p = (effect_param_t *)pCmdData;
+
+                memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+                p = (effect_param_t *)pReplyData;
+
+                int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+                p->status = android::Virtualizer_getParameter(pContext,
+                                                             (int32_t *)p->data,
+                                                             (size_t  *)&p->vsize,
+                                                              p->data + voffset);
+
+                *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+                //LOGV("\tVirtualizer_command EFFECT_CMD_GET_PARAM "
+                //        "*pCmdData %d, *replySize %d, *pReplyData %d ",
+                //        *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+                //        *replySize,
+                //        *(int16_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset));
+            }
+            if(pContext->EffectType == LVM_EQUALIZER){
+                //LOGV("\tEqualizer_command cmdCode Case: "
+                //        "EFFECT_CMD_GET_PARAM start");
+                if (pCmdData == NULL ||
+                    cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                    pReplyData == NULL ||
+                    *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
+                    LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
+                            "EFFECT_CMD_GET_PARAM");
+                    return -EINVAL;
+                }
+                effect_param_t *p = (effect_param_t *)pCmdData;
+
+                memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+                p = (effect_param_t *)pReplyData;
+
+                int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+                p->status = android::Equalizer_getParameter(pContext, (int32_t *)p->data, &p->vsize,
+                        p->data + voffset);
+
+                *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+                //LOGV("\tEqualizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, "
+                //       "*pReplyData %08x %08x",
+                //        *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
+                //        *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
+                //        *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset +
+                //        sizeof(int32_t)));
+            }
+            if(pContext->EffectType == LVM_VOLUME){
+                //LOGV("\tVolume_command cmdCode Case: "
+                //        "EFFECT_CMD_GET_PARAM start");
+                if (pCmdData == NULL ||
+                        cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                        pReplyData == NULL ||
+                        *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+                    LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
+                            "EFFECT_CMD_GET_PARAM: ERROR");
+                    return -EINVAL;
+                }
+                effect_param_t *p = (effect_param_t *)pCmdData;
+
+                memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+                p = (effect_param_t *)pReplyData;
+
+                int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+                p->status = android::Volume_getParameter(pContext,
+                                                         (int32_t *)p->data,
+                                                         (size_t  *)&p->vsize,
+                                                         p->data + voffset);
+
+                *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+                //LOGV("\tVolume_command EFFECT_CMD_GET_PARAM "
+                //        "*pCmdData %d, *replySize %d, *pReplyData %d ",
+                //        *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+                //        *replySize,
+                //        *(int16_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset));
+            }
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM end");
+        } break;
+        case EFFECT_CMD_SET_PARAM:{
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM start");
+            if(pContext->EffectType == LVM_BASS_BOOST){
+                //LOGV("\tBassBoost_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d ",
+                //        *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+                //        *replySize,
+                //        *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+                if (pCmdData   == NULL||
+                    cmdSize    != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
+                    pReplyData == NULL||
+                    *replySize != sizeof(int32_t)){
+                    LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+                            "EFFECT_CMD_SET_PARAM: ERROR");
+                    return -EINVAL;
+                }
+                effect_param_t *p = (effect_param_t *) pCmdData;
+
+                if (p->psize != sizeof(int32_t)){
+                    LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+                            "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+                    return -EINVAL;
+                }
+
+                //LOGV("\tnBassBoost_command cmdSize is %d\n"
+                //        "\tsizeof(effect_param_t) is  %d\n"
+                //        "\tp->psize is %d\n"
+                //        "\tp->vsize is %d"
+                //        "\n",
+                //        cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
+
+                *(int *)pReplyData = android::BassBoost_setParameter(pContext,
+                                                                    (int32_t *)p->data,
+                                                                    p->data + p->psize);
+            }
+            if(pContext->EffectType == LVM_VIRTUALIZER){
+                //LOGV("\tVirtualizer_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d",
+                //        *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+                //        *replySize,
+                //        *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+                if (pCmdData   == NULL||
+                    cmdSize    != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
+                    pReplyData == NULL||
+                    *replySize != sizeof(int32_t)){
+                    LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+                            "EFFECT_CMD_SET_PARAM: ERROR");
+                    return -EINVAL;
+                }
+                effect_param_t *p = (effect_param_t *) pCmdData;
+
+                if (p->psize != sizeof(int32_t)){
+                    LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+                            "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+                    return -EINVAL;
+                }
+
+                //LOGV("\tnVirtualizer_command cmdSize is %d\n"
+                //        "\tsizeof(effect_param_t) is  %d\n"
+                //        "\tp->psize is %d\n"
+                //        "\tp->vsize is %d"
+                //        "\n",
+                //        cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
+
+                *(int *)pReplyData = android::Virtualizer_setParameter(pContext,
+                                                                      (int32_t *)p->data,
+                                                                       p->data + p->psize);
+            }
+            if(pContext->EffectType == LVM_EQUALIZER){
+                //LOGV("\tEqualizer_command cmdCode Case: "
+                //        "EFFECT_CMD_SET_PARAM start");
+                //LOGV("\tEqualizer_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d ",
+                //        *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+                //        *replySize,
+                //        *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+                if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                    pReplyData == NULL || *replySize != sizeof(int32_t)) {
+                    LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
+                            "EFFECT_CMD_SET_PARAM: ERROR");
+                    return -EINVAL;
+                }
+                effect_param_t *p = (effect_param_t *) pCmdData;
+
+                *(int *)pReplyData = android::Equalizer_setParameter(pContext,
+                                                                    (int32_t *)p->data,
+                                                                     p->data + p->psize);
+            }
+            if(pContext->EffectType == LVM_VOLUME){
+                //LOGV("\tVolume_command cmdCode Case: "
+                //        "EFFECT_CMD_SET_PARAM start");
+                //LOGV("\tVolume_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d ",
+                //        *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+                //        *replySize,
+                //        *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+                if (    pCmdData   == NULL||
+                        cmdSize    < (int)(sizeof(effect_param_t) + sizeof(int32_t))||
+                        pReplyData == NULL||
+                        *replySize != sizeof(int32_t)){
+                    LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
+                            "EFFECT_CMD_SET_PARAM: ERROR");
+                    return -EINVAL;
+                }
+                effect_param_t *p = (effect_param_t *) pCmdData;
+
+                *(int *)pReplyData = android::Volume_setParameter(pContext,
+                                                                 (int32_t *)p->data,
+                                                                 p->data + p->psize);
+            }
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM end");
+        } break;
+
+        case EFFECT_CMD_ENABLE:
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE start");
+            if (pReplyData == NULL || *replySize != sizeof(int)){
+                LOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
+                return -EINVAL;
+            }
+            switch (pContext->EffectType){
+                case LVM_BASS_BOOST:
+                    if(pContext->pBundledContext->bBassEnabled == LVM_TRUE){
+                         LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+                                 "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+                         return -EINVAL;
+                    }
+                    pContext->pBundledContext->bBassEnabled = LVM_TRUE;
+                    //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE LVM_BASS_BOOST enabled");
+                    break;
+                case LVM_EQUALIZER:
+                    if(pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE){
+                         LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
+                                 "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+                         return -EINVAL;
+                    }
+                    pContext->pBundledContext->bEqualizerEnabled = LVM_TRUE;
+                    //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE LVM_EQUALIZER enabled");
+                    break;
+                case LVM_VIRTUALIZER:
+                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
+                         LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+                                 "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+                         return -EINVAL;
+                    }
+                    pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
+                    //LOGV("\tEffect_command cmdCode Case:EFFECT_CMD_ENABLE LVM_VIRTUALIZER enabled");
+                    break;
+                case LVM_VOLUME:
+                    if(pContext->pBundledContext->bVolumeEnabled == LVM_TRUE){
+                         LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
+                                 "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+                         return -EINVAL;
+                    }
+                    pContext->pBundledContext->bVolumeEnabled = LVM_TRUE;
+                    //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE LVM_VOLUME enabled");
+                    break;
+                default:
+                    LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+                        "EFFECT_CMD_ENABLE: ERROR, invalid Effect Type");
+                    return -EINVAL;
+            }
+            *(int *)pReplyData = 0;
+            pContext->pBundledContext->NumberEffectsEnabled++;
+            android::LvmEffect_enable(pContext);
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE NumberEffectsEnabled = %d",
+            //        pContext->pBundledContext->NumberEffectsEnabled);
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE end");
+            break;
+
+        case EFFECT_CMD_DISABLE:
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE start");
+            if (pReplyData == NULL || *replySize != sizeof(int)){
+                LOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
+                return -EINVAL;
+            }
+            switch (pContext->EffectType){
+                case LVM_BASS_BOOST:
+                    if(pContext->pBundledContext->bBassEnabled == LVM_FALSE){
+                         LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+                                 "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+                         return -EINVAL;
+                    }
+                    pContext->pBundledContext->bBassEnabled      = LVM_FALSE;
+                    //LOGV("\tEffect_command cmdCode Case: "
+                    //       "EFFECT_CMD_DISABLE LVM_BASS_BOOST disabled");
+                    break;
+                case LVM_EQUALIZER:
+                    if(pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE){
+                         LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
+                                 "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+                         return -EINVAL;
+                    }
+                    pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
+                    //LOGV("\tEffect_command cmdCode Case: "
+                    //       "EFFECT_CMD_DISABLE LVM_EQUALIZER disabled");
+                    break;
+                case LVM_VIRTUALIZER:
+                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE){
+                         LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+                                 "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+                         return -EINVAL;
+                    }
+                    pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
+                    //LOGV("\tEffect_command cmdCode Case: "
+                    //     "EFFECT_CMD_DISABLE LVM_VIRTUALIZER disabled");
+                    break;
+                case LVM_VOLUME:
+                    if(pContext->pBundledContext->bVolumeEnabled == LVM_FALSE){
+                         LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
+                                 "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+                         return -EINVAL;
+                    }
+                    pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
+                    //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE LVM_VOLUME disabled");
+                    break;
+                default:
+                    LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+                        "EFFECT_CMD_DISABLE: ERROR, invalid Effect Type");
+                    return -EINVAL;
+            }
+            *(int *)pReplyData = 0;
+            pContext->pBundledContext->NumberEffectsEnabled--;
+            android::LvmEffect_disable(pContext);
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE NumberEffectsEnabled = %d",
+            //        pContext->pBundledContext->NumberEffectsEnabled);
+            //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE end");
+            break;
+
+        case EFFECT_CMD_SET_DEVICE:
+        {
+            LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE start");
+            audio_device_e device = *(audio_device_e *)pCmdData;
+
+            if(pContext->EffectType == LVM_BASS_BOOST){
+                if((device == DEVICE_SPEAKER)||(device == DEVICE_BLUETOOTH_SCO_CARKIT)||
+                   (device == DEVICE_BLUETOOTH_A2DP_SPEAKER)){
+                    LOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_BASS_BOOST %d",
+                          *(int32_t *)pCmdData);
+                    LOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_BAS_BOOST");
+
+                    // If a device doesnt support bassboost the effect must be temporarily disabled
+                    // the effect must still report its original state as this can only be changed
+                    // by the ENABLE/DISABLE command
+
+                    if(pContext->pBundledContext->bBassEnabled == LVM_TRUE){
+                        LOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_BASS_BOOST %d",
+                             *(int32_t *)pCmdData);
+                        android::LvmEffect_disable(pContext);
+                        pContext->pBundledContext->bBassTempDisabled = LVM_TRUE;
+                    }
+                }else{
+                    LOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_BASS_BOOST %d",
+                         *(int32_t *)pCmdData);
+
+                    // If a device supports bassboost and the effect has been temporarily disabled
+                    // previously then re-enable it
+
+                    if(pContext->pBundledContext->bBassTempDisabled == LVM_TRUE){
+                        LOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_BASS_BOOST %d",
+                             *(int32_t *)pCmdData);
+                        android::LvmEffect_enable(pContext);
+                        pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
+                    }
+                }
+            }
+            if(pContext->EffectType == LVM_VIRTUALIZER){
+                if((device == DEVICE_SPEAKER)||(device == DEVICE_BLUETOOTH_SCO_CARKIT)||
+                   (device == DEVICE_BLUETOOTH_A2DP_SPEAKER)){
+                    LOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_VIRTUALIZER %d",
+                          *(int32_t *)pCmdData);
+                    LOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_VIRTUALIZER");
+
+                    //If a device doesnt support virtualizer the effect must be temporarily disabled
+                    // the effect must still report its original state as this can only be changed
+                    // by the ENABLE/DISABLE command
+
+                    if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
+                        LOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_VIRTUALIZER %d",
+                              *(int32_t *)pCmdData);
+                        android::LvmEffect_disable(pContext);
+                        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_TRUE;
+                    }
+                }else{
+                    LOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_VIRTUALIZER %d",
+                          *(int32_t *)pCmdData);
+
+                    // If a device supports virtualizer and the effect has been temporarily disabled
+                    // previously then re-enable it
+
+                    if(pContext->pBundledContext->bVirtualizerTempDisabled == LVM_TRUE){
+                        LOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_VIRTUALIZER %d",
+                              *(int32_t *)pCmdData);
+                        android::LvmEffect_enable(pContext);
+                        pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
+                    }
+                }
+            }
+            LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE end");
+            break;
+        }
+        case EFFECT_CMD_SET_VOLUME:
+        {
+            int32_t channels = cmdSize/sizeof(int32_t);
+            int32_t vol     = *(int32_t *)pCmdData;
+            int16_t vol_db;
+            int16_t dB;
+            int16_t vol_db_rnd;
+            int32_t vol_ret[2] = {1<<24,1<<24}; // Apply no volume
+
+            // if pReplyData is NULL, VOL_CTRL is delegated to another effect
+            if(pReplyData == LVM_NULL){
+                break;
+            }
+
+            if(vol==0x1000000){
+                vol -= 1;
+            }
+            // Convert volume linear (Q8.24) to volume dB (0->-96)
+            dB = android::LVC_ToDB_s32Tos16(vol <<7);
+            dB = (dB +8)>>4;
+            dB = (dB <-96) ? -96 : dB ;
+
+            //LOGV("\tSession: %d, VOLUME is %d dB (%d), effect is %d",
+            //pContext->pBundledContext->SessionNo, (int32_t)dB, vol<<7, pContext->EffectType);
+            memcpy(pReplyData, vol_ret, sizeof(int32_t)*2);
+            android::VolumeSetVolumeLevel(pContext, (int16_t)(dB*100));
+            break;
+         }
+        case EFFECT_CMD_SET_AUDIO_MODE:
+            break;
+        default:
+            return -EINVAL;
+    }
+
+    //LOGV("\tEffect_command end...\n\n");
+    return 0;
+}    /* end Effect_command */
+
+// effect_interface_t interface implementation for effect
+const struct effect_interface_s gLvmEffectInterface = {
+    Effect_process,
+    Effect_command
+};    /* end gLvmEffectInterface */
+
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
new file mode 100644
index 0000000..d009bf9
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2010 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 ANDROID_EFFECTBUNDLE_H_
+#define ANDROID_EFFECTBUNDLE_H_
+
+#include <media/EffectEqualizerApi.h>
+#include <media/EffectBassBoostApi.h>
+#include <media/EffectVirtualizerApi.h>
+#include <LVM.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#define FIVEBAND_NUMBANDS       5
+#define MAX_NUM_BANDS           5
+#define MAX_CALL_SIZE           256
+//#define LVM_PCM
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
+                                            { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
+#endif //OPENSL_ES_H_
+
+typedef enum
+{
+    LVM_BASS_BOOST,
+    LVM_VIRTUALIZER,
+    LVM_EQUALIZER,
+    LVM_VOLUME
+} lvm_effect_en;
+
+// Preset configuration.
+struct PresetConfig {
+    // Human-readable name.
+    const char * name;
+    // An array of size nBands where each element is a configuration for the
+    // corresponding band.
+    //const BandConfig * bandConfigs;
+};
+
+/* BundledEffectContext : One per session */
+struct BundledEffectContext{
+    LVM_Handle_t                    hInstance;                /* Instance handle */
+    int                             SessionNo;                /* Current session number */
+    bool                            bVolumeEnabled;           /* Flag for Volume */
+    bool                            bEqualizerEnabled;        /* Flag for EQ */
+    bool                            bBassEnabled;             /* Flag for Bass */
+    bool                            bBassTempDisabled;        /* Flag for Bass to be re-enabled */
+    bool                            bVirtualizerEnabled;      /* Flag for Virtualizer */
+    bool                            bVirtualizerTempDisabled; /* Flag for effect to be re-enabled */
+    int                             NumberEffectsEnabled;     /* Effects in this session */
+    int                             NumberEffectsCalled;      /* Effects called so far */
+    // Saved parameters for each effect */
+    // Bass Boost
+    int                             BassStrengthSaved;        /* Conversion between Get/Set */
+    // Equalizer
+    int                             CurPreset;                /* Current preset being used */
+    // Virtualzer
+    int                             VirtStrengthSaved;        /* Conversion between Get/Set */
+    // Volume
+    int                             levelSaved;     /* for when mute is set, level must be saved */
+    int                             positionSaved;
+    bool                            bMuteEnabled;   /* Must store as mute = -96dB level */
+    bool                            bStereoPositionEnabled;
+    int                             frameCount;
+    LVM_Fs_en                       SampleRate;
+    #ifdef LVM_PCM
+    FILE                            *PcmInPtr;
+    FILE                            *PcmOutPtr;
+    #endif
+};
+
+/* SessionContext : One session */
+struct SessionContext{
+    bool                            bBundledEffectsEnabled;
+    bool                            bVolumeInstantiated;
+    bool                            bEqualizerInstantiated;
+    bool                            bBassInstantiated;
+    bool                            bVirtualizerInstantiated;
+    BundledEffectContext            *pBundledContext;
+};
+
+struct EffectContext{
+    const struct effect_interface_s *itfe;
+    effect_config_t                 config;
+    lvm_effect_en                   EffectType;
+    BundledEffectContext            *pBundledContext;
+};
+
+
+/* enumerated parameter settings for Volume effect */
+typedef enum
+{
+    VOLUME_PARAM_LEVEL,                       // type SLmillibel = typedef SLuint16 (set & get)
+    VOLUME_PARAM_MAXLEVEL,                    // type SLmillibel = typedef SLuint16 (get)
+    VOLUME_PARAM_MUTE,                        // type SLboolean  = typedef SLuint32 (set & get)
+    VOLUME_PARAM_ENABLESTEREOPOSITION,        // type SLboolean  = typedef SLuint32 (set & get)
+    VOLUME_PARAM_STEREOPOSITION,              // type SLpermille = typedef SLuint16 (set & get)
+} t_volume_params;
+
+static const int PRESET_CUSTOM = -1;
+
+static const uint32_t bandFreqRange[FIVEBAND_NUMBANDS][2] = {
+                                       {30000, 120000},
+                                       {120001, 460000},
+                                       {460001, 1800000},
+                                       {1800001, 7000000},
+                                       {7000001, 1}};
+
+static const LVM_UINT16  EQNB_5BandPresetsFrequencies[] = {
+                                       60,           /* Frequencies in Hz */
+                                       230,
+                                       910,
+                                       3600,
+                                       14000};
+
+static const LVM_UINT16 EQNB_5BandPresetsQFactors[] = {
+                                       96,               /* Q factor multiplied by 100 */
+                                       96,
+                                       96,
+                                       96,
+                                       96};
+
+static const LVM_INT16 EQNB_5BandNormalPresets[] = {
+                                       3, 0, 0, 0, 3,       /* Normal Preset */
+                                       8, 5, -3, 5, 6,      /* Classical Preset */
+                                       15, -6, 7, 13, 10,   /* Dance Preset */
+                                       0, 0, 0, 0, 0,       /* Flat Preset */
+                                       6, -2, -2, 6, -3,    /* Folk Preset */
+                                       8, -8, 13, -1, -4,   /* Heavy Metal Preset */
+                                       10, 6, -4, 5, 8,     /* Hip Hop Preset */
+                                       8, 5, -4, 5, 9,      /* Jazz Preset */
+                                      -6, 4, 9, 4, -5,      /* Pop Preset */
+                                       10, 6, -1, 8, 10};   /* Rock Preset */
+
+static const LVM_INT16 EQNB_5BandSoftPresets[] = {
+                                        3, 0, 0, 0, 3,      /* Normal Preset */
+                                        5, 3, -2, 4, 4,     /* Classical Preset */
+                                        6, 0, 2, 4, 1,      /* Dance Preset */
+                                        0, 0, 0, 0, 0,      /* Flat Preset */
+                                        3, 0, 0, 2, -1,     /* Folk Preset */
+                                        4, 1, 9, 3, 0,      /* Heavy Metal Preset */
+                                        5, 3, 0, 1, 3,      /* Hip Hop Preset */
+                                        4, 2, -2, 2, 5,     /* Jazz Preset */
+                                       -1, 2, 5, 1, -2,     /* Pop Preset */
+                                        5, 3, -1, 3, 5};    /* Rock Preset */
+
+static const PresetConfig gEqualizerPresets[] = {
+                                        {"Normal"},
+                                        {"Classical"},
+                                        {"Dance"},
+                                        {"Flat"},
+                                        {"Folk"},
+                                        {"Heavy Metal"},
+                                        {"Hip Hop"},
+                                        {"Jazz"},
+                                        {"Pop"},
+                                        {"Rock"}};
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTBUNDLE_H_*/
diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_
new file mode 100644
index 0000000..9ba71ed
--- /dev/null
+++ b/media/libeffects/testlibs/Android.mk_
@@ -0,0 +1,66 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Test Reverb library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectReverb.c.arm \
+	EffectsMath.c.arm
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libreverbtest
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+	$(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Test Equalizer library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectsMath.c.arm \
+	EffectEqualizer.cpp \
+	AudioBiquadFilter.cpp.arm \
+	AudioCoefInterpolator.cpp.arm \
+	AudioPeakingFilter.cpp.arm \
+	AudioShelvingFilter.cpp.arm \
+	AudioEqualizer.cpp.arm
+
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libequalizertest
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+	$(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/media/libeffects/testlibs/AudioBiquadFilter.cpp b/media/libeffects/testlibs/AudioBiquadFilter.cpp
new file mode 100644
index 0000000..72917a3
--- /dev/null
+++ b/media/libeffects/testlibs/AudioBiquadFilter.cpp
@@ -0,0 +1,260 @@
+/* //device/servers/AudioFlinger/AudioBiquadFilter.cpp
+**
+** Copyright 2009, 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.
+*/
+
+#include <string.h>
+#include <assert.h>
+
+#include "AudioBiquadFilter.h"
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+const audio_coef_t AudioBiquadFilter::IDENTITY_COEFS[AudioBiquadFilter::NUM_COEFS] = { AUDIO_COEF_ONE, 0, 0, 0, 0 };
+
+AudioBiquadFilter::AudioBiquadFilter(int nChannels, int sampleRate) {
+    configure(nChannels, sampleRate);
+    reset();
+}
+
+void AudioBiquadFilter::configure(int nChannels, int sampleRate) {
+    assert(nChannels > 0 && nChannels <= MAX_CHANNELS);
+    assert(sampleRate > 0);
+    mNumChannels  = nChannels;
+    mMaxDelta = static_cast<int64_t>(MAX_DELTA_PER_SEC)
+                * AUDIO_COEF_ONE
+                / sampleRate;
+    clear();
+}
+
+void AudioBiquadFilter::reset() {
+    memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs));
+    mCoefDirtyBits = 0;
+    setState(STATE_BYPASS);
+}
+
+void AudioBiquadFilter::clear() {
+    memset(mDelays, 0, sizeof(mDelays));
+}
+
+void AudioBiquadFilter::setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate) {
+    memcpy(mTargetCoefs, coefs, sizeof(mTargetCoefs));
+    if (mState & STATE_ENABLED_MASK) {
+        if (UNLIKELY(immediate)) {
+            memcpy(mCoefs, coefs, sizeof(mCoefs));
+            setState(STATE_NORMAL);
+        } else {
+            setState(STATE_TRANSITION_TO_NORMAL);
+        }
+    }
+}
+
+void AudioBiquadFilter::process(const audio_sample_t in[], audio_sample_t out[],
+                                int frameCount) {
+    (this->*mCurProcessFunc)(in, out, frameCount);
+}
+
+void AudioBiquadFilter::enable(bool immediate) {
+    if (UNLIKELY(immediate)) {
+        memcpy(mCoefs, mTargetCoefs, sizeof(mCoefs));
+        setState(STATE_NORMAL);
+    } else {
+        setState(STATE_TRANSITION_TO_NORMAL);
+    }
+}
+
+void AudioBiquadFilter::disable(bool immediate) {
+    if (UNLIKELY(immediate)) {
+        memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs));
+        setState(STATE_BYPASS);
+    } else {
+        setState(STATE_TRANSITION_TO_BYPASS);
+    }
+}
+
+void AudioBiquadFilter::setState(state_t state) {
+    switch (state) {
+    case STATE_BYPASS:
+      mCurProcessFunc = &AudioBiquadFilter::process_bypass;
+      break;
+    case STATE_TRANSITION_TO_BYPASS:
+      if (mNumChannels == 1) {
+        mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_mono;
+      } else {
+        mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_multi;
+      }
+      mCoefDirtyBits = (1 << NUM_COEFS) - 1;
+      break;
+    case STATE_TRANSITION_TO_NORMAL:
+      if (mNumChannels == 1) {
+        mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_mono;
+      } else {
+        mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_multi;
+      }
+      mCoefDirtyBits = (1 << NUM_COEFS) - 1;
+      break;
+    case STATE_NORMAL:
+      if (mNumChannels == 1) {
+        mCurProcessFunc = &AudioBiquadFilter::process_normal_mono;
+      } else {
+        mCurProcessFunc = &AudioBiquadFilter::process_normal_multi;
+      }
+      break;
+    }
+    mState = state;
+}
+
+bool AudioBiquadFilter::updateCoefs(const audio_coef_t coefs[NUM_COEFS],
+                                    int frameCount) {
+    int64_t maxDelta = mMaxDelta * frameCount;
+    for (int i = 0; i < NUM_COEFS; ++i) {
+        if (mCoefDirtyBits & (1<<i)) {
+            audio_coef_t diff = coefs[i] - mCoefs[i];
+            if (diff > maxDelta) {
+                mCoefs[i] += maxDelta;
+            } else if (diff < -maxDelta) {
+                mCoefs[i] -= maxDelta;
+            } else {
+                mCoefs[i] = coefs[i];
+                mCoefDirtyBits ^= (1<<i);
+            }
+        }
+    }
+    return mCoefDirtyBits == 0;
+}
+
+void AudioBiquadFilter::process_bypass(const audio_sample_t * in,
+                                       audio_sample_t * out,
+                                       int frameCount) {
+    // The common case is in-place processing, because this is what the EQ does.
+    if (UNLIKELY(in != out)) {
+        memcpy(out, in, frameCount * mNumChannels * sizeof(audio_sample_t));
+    }
+}
+
+void AudioBiquadFilter::process_normal_mono(const audio_sample_t * in,
+                                            audio_sample_t * out,
+                                            int frameCount) {
+    size_t nFrames = frameCount;
+    audio_sample_t x1 = mDelays[0][0];
+    audio_sample_t x2 = mDelays[0][1];
+    audio_sample_t y1 = mDelays[0][2];
+    audio_sample_t y2 = mDelays[0][3];
+    const audio_coef_t b0 = mCoefs[0];
+    const audio_coef_t b1 = mCoefs[1];
+    const audio_coef_t b2 = mCoefs[2];
+    const audio_coef_t a1 = mCoefs[3];
+    const audio_coef_t a2 = mCoefs[4];
+    while (nFrames-- > 0) {
+        audio_sample_t x0 = *(in++);
+        audio_coef_sample_acc_t acc;
+        acc = mul_coef_sample(b0, x0);
+        acc = mac_coef_sample(b1, x1, acc);
+        acc = mac_coef_sample(b2, x2, acc);
+        acc = mac_coef_sample(a1, y1, acc);
+        acc = mac_coef_sample(a2, y2, acc);
+        audio_sample_t y0 = coef_sample_acc_to_sample(acc);
+        y2 = y1;
+        y1 = y0;
+        x2 = x1;
+        x1 = x0;
+        (*out++) = y0;
+    }
+    mDelays[0][0] = x1;
+    mDelays[0][1] = x2;
+    mDelays[0][2] = y1;
+    mDelays[0][3] = y2;
+}
+
+void AudioBiquadFilter::process_transition_normal_mono(const audio_sample_t * in,
+                                                       audio_sample_t * out,
+                                                       int frameCount) {
+    if (updateCoefs(mTargetCoefs, frameCount)) {
+        setState(STATE_NORMAL);
+    }
+    process_normal_mono(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_transition_bypass_mono(const audio_sample_t * in,
+                                                       audio_sample_t * out,
+                                                       int frameCount)  {
+  if (updateCoefs(IDENTITY_COEFS, frameCount)) {
+      setState(STATE_NORMAL);
+  }
+  process_normal_mono(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_normal_multi(const audio_sample_t * in,
+                                             audio_sample_t * out,
+                                             int frameCount) {
+    const audio_coef_t b0 = mCoefs[0];
+    const audio_coef_t b1 = mCoefs[1];
+    const audio_coef_t b2 = mCoefs[2];
+    const audio_coef_t a1 = mCoefs[3];
+    const audio_coef_t a2 = mCoefs[4];
+    for (int ch = 0; ch < mNumChannels; ++ch) {
+        size_t nFrames = frameCount;
+        audio_sample_t x1 = mDelays[ch][0];
+        audio_sample_t x2 = mDelays[ch][1];
+        audio_sample_t y1 = mDelays[ch][2];
+        audio_sample_t y2 = mDelays[ch][3];
+        while (nFrames-- > 0) {
+            audio_sample_t x0 = *in;
+            audio_coef_sample_acc_t acc;
+            acc = mul_coef_sample(b0, x0);
+            acc = mac_coef_sample(b1, x1, acc);
+            acc = mac_coef_sample(b2, x2, acc);
+            acc = mac_coef_sample(a1, y1, acc);
+            acc = mac_coef_sample(a2, y2, acc);
+            audio_sample_t y0 = coef_sample_acc_to_sample(acc);
+            y2 = y1;
+            y1 = y0;
+            x2 = x1;
+            x1 = x0;
+            *out = y0;
+            in += mNumChannels;
+            out += mNumChannels;
+        }
+        mDelays[ch][0] = x1;
+        mDelays[ch][1] = x2;
+        mDelays[ch][2] = y1;
+        mDelays[ch][3] = y2;
+        in -= frameCount * mNumChannels - 1;
+        out -= frameCount * mNumChannels - 1;
+    }
+}
+
+void AudioBiquadFilter::process_transition_normal_multi(const audio_sample_t * in,
+                                                        audio_sample_t * out,
+                                                        int frameCount) {
+    if (updateCoefs(mTargetCoefs, frameCount)) {
+        setState(STATE_NORMAL);
+    }
+    process_normal_multi(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_transition_bypass_multi(const audio_sample_t * in,
+                                                        audio_sample_t * out,
+                                                        int frameCount)  {
+    if (updateCoefs(IDENTITY_COEFS, frameCount)) {
+        setState(STATE_NORMAL);
+    }
+    process_normal_multi(in, out, frameCount);
+}
+
+}
diff --git a/media/libeffects/testlibs/AudioBiquadFilter.h b/media/libeffects/testlibs/AudioBiquadFilter.h
new file mode 100644
index 0000000..2b0e2d6
--- /dev/null
+++ b/media/libeffects/testlibs/AudioBiquadFilter.h
@@ -0,0 +1,180 @@
+/* //device/include/server/AudioFlinger/AudioBiquadFilter.h
+**
+** Copyright 2007, 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 ANDROID_AUDIO_BIQUAD_FILTER_H
+#define ANDROID_AUDIO_BIQUAD_FILTER_H
+
+#include "AudioCommon.h"
+
+namespace android {
+// A biquad filter.
+// Implements the recursion y[n]=a0*y[n-1]+a1*y[n-2]+b0*x[n]+b1*x[n-1]+b2*x[n-2]
+// (the a0 and a1 coefficients have an opposite sign to the common convention)
+// The filter works on fixed sized blocks of data (frameCount multi-channel
+// samples, as defined during construction). An arbitrary number of interlaced
+// channels is supported.
+// Filter can operate in an enabled (active) or disabled (bypassed) states.
+// A mechanism for suppression of artifacts caused by abrupt coefficient changes
+// is implemented: normally, when the enable(), disable() and setCoefs() methods
+// are called without the immediate flag set, the filter smoothly transitions
+// from its current state to the desired state.
+class AudioBiquadFilter {
+public:
+    // Max number of channels (can be changed here, and everything should work).
+    static const int MAX_CHANNELS = 2;
+    // Number of coefficients.
+    static const int NUM_COEFS = 5;
+
+    // Constructor.
+    // nChannels    Number of input/output channels.
+    // sampleRate   Sample rate, in Hz.
+    AudioBiquadFilter(int nChannels, int sampleRate);
+
+    // Reconfiguration of the filter. Implies clear().
+    // nChannels    Number of input/output channels.
+    // sampleRate   Sample rate, in Hz.
+    void configure(int nChannels, int sampleRate);
+
+    // Resets the internal state of the filter.
+    // Coefficients are reset to identity, state becomes disabled. This change
+    // happens immediately and might cause discontinuities in the output.
+    // Delay lines are not cleared.
+    void reset();
+
+    // Clears the delay lines.
+    // This change happens immediately and might cause discontinuities in the
+    // output.
+    void clear();
+
+    // Sets the coefficients.
+    // If called when filter is disabled, will have no immediate effect, but the
+    // new coefficients will be set and used next time the filter is enabled.
+    // coefs        The new coefficients.
+    // immediate    If true, transitions to new coefficients smoothly, without
+    //              introducing discontinuities in the output. Otherwise,
+    //              transitions immediately.
+    void setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate = false);
+
+    // Process a buffer of data. Always processes frameCount multi-channel
+    // samples. Processing can be done in-place, by passing the same buffer as
+    // both arguments.
+    // in           The input buffer. Should be of size frameCount * nChannels.
+    // out          The output buffer. Should be of size frameCount * nChannels.
+    // frameCount   Number of multi-channel samples to process.
+    void process(const audio_sample_t in[], audio_sample_t out[],
+                 int frameCount);
+
+    // Enables (activates) the filter.
+    // immediate    If true, transitions to new state smoothly, without
+    //              introducing discontinuities in the output. Otherwise,
+    //              transitions immediately.
+    void enable(bool immediate = false);
+
+    // Disables (bypasses) the filter.
+    // immediate    If true, transitions to new state smoothly, without
+    //              introducing discontinuities in the output. Otherwise,
+    //              transitions immediately.
+    void disable(bool immediate = false);
+
+private:
+    // A prototype of the actual processing function. Has the same semantics as
+    // the process() method.
+    typedef void (AudioBiquadFilter::*process_func)(const audio_sample_t[],
+                                                    audio_sample_t[],
+                                                    int frameCount);
+
+    // The maximum rate of coefficient change, measured in coefficient units per
+    // second.
+    static const audio_coef_t MAX_DELTA_PER_SEC = 2000;
+
+    // Coefficients of identity transformation.
+    static const audio_coef_t IDENTITY_COEFS[NUM_COEFS];
+
+    // Filter state.
+    enum state_t {
+        // Bypass.
+        STATE_BYPASS = 0x01,
+        // In the process of smooth transition to bypass state.
+        STATE_TRANSITION_TO_BYPASS = 0x02,
+        // In the process of smooth transition to normal (enabled) state.
+        STATE_TRANSITION_TO_NORMAL = 0x04,
+        // In normal (enabled) state.
+        STATE_NORMAL = 0x05,
+        // A bit-mask for determining whether the filter is enabled or disabled
+        // in the eyes of the client.
+        STATE_ENABLED_MASK = 0x04
+    };
+
+    // Number of channels.
+    int mNumChannels;
+    // Current state.
+    state_t mState;
+    // Maximum coefficient delta per sample.
+    audio_coef_t mMaxDelta;
+
+    // A bit-mask designating for which coefficients the current value is not
+    // necessarily identical to the target value (since we're in transition
+    // state).
+    uint32_t mCoefDirtyBits;
+    // The current coefficients.
+    audio_coef_t mCoefs[NUM_COEFS];
+    // The target coefficients. Will not be identical to mCoefs if we are in a
+    // transition state.
+    audio_coef_t mTargetCoefs[NUM_COEFS];
+
+    // The delay lines.
+    audio_sample_t mDelays[MAX_CHANNELS][4];
+
+    // Current processing function (determines according to current state and
+    // number of channels).
+    process_func mCurProcessFunc;
+
+    // Sets a new state. Updates the processing function accordingly, and sets
+    // the dirty bits if changing to a transition state.
+    void setState(state_t state);
+
+    // In a transition state, modifies the current coefs towards the passed
+    // coefs, while keeping a smooth change rate. Whenever a coef reaches its
+    // target value, the dirty bit is cleared. If all are clear, the function
+    // returns true, and we can then change to our target state.
+    bool updateCoefs(const audio_coef_t coefs[NUM_COEFS], int frameCount);
+
+    // Processing function when in disabled state.
+    void process_bypass(const audio_sample_t * in, audio_sample_t * out,
+                        int frameCount);
+    // Processing function when in normal state, mono.
+    void process_normal_mono(const audio_sample_t * in, audio_sample_t * out,
+                             int frameCount);
+    // Processing function when transitioning to normal state, mono.
+    void process_transition_normal_mono(const audio_sample_t * in,
+                                        audio_sample_t * out, int frameCount);
+    // Processing function when transitioning to bypass state, mono.
+    void process_transition_bypass_mono(const audio_sample_t * in,
+                                        audio_sample_t * out, int frameCount);
+    // Processing function when in normal state, multi-channel.
+    void process_normal_multi(const audio_sample_t * in, audio_sample_t * out,
+                              int frameCount);
+    // Processing function when transitioning to normal state, multi-channel.
+    void process_transition_normal_multi(const audio_sample_t * in,
+                                         audio_sample_t * out, int frameCount);
+    // Processing function when transitioning to bypass state, multi-channel.
+    void process_transition_bypass_multi(const audio_sample_t * in,
+                                         audio_sample_t * out, int frameCount);
+};
+}
+
+#endif // ANDROID_AUDIO_BIQUAD_FILTER_H
diff --git a/media/libeffects/testlibs/AudioCoefInterpolator.cpp b/media/libeffects/testlibs/AudioCoefInterpolator.cpp
new file mode 100644
index 0000000..039ab9f
--- /dev/null
+++ b/media/libeffects/testlibs/AudioCoefInterpolator.cpp
@@ -0,0 +1,84 @@
+/* //device/servers/AudioFlinger/AudioCoefInterpolator.cpp
+ **
+ ** Copyright 2008, 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.
+ */
+
+#include <string.h>
+#include "AudioCoefInterpolator.h"
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+AudioCoefInterpolator::AudioCoefInterpolator(size_t nInDims,
+                                             const size_t inDims[],
+                                             size_t nOutDims,
+                                             const audio_coef_t * table) {
+    mNumInDims = nInDims;
+    memcpy(mInDims, inDims, nInDims * sizeof(size_t));
+    mNumOutDims = nOutDims;
+    mTable = table;
+    // Initialize offsets array
+    size_t dim = nInDims - 1;
+    mInDimOffsets[nInDims - 1] = nOutDims;
+    while (dim-- > 0) {
+        mInDimOffsets[dim] = mInDimOffsets[dim + 1] * mInDims[dim + 1];
+    }
+}
+
+void AudioCoefInterpolator::getCoef(const int intCoord[], uint32_t fracCoord[],
+                                    audio_coef_t out[]) {
+    size_t index = 0;
+    size_t dim = mNumInDims;
+    while (dim-- > 0) {
+        if (UNLIKELY(intCoord[dim] < 0)) {
+            fracCoord[dim] = 0;
+        } else if (UNLIKELY(intCoord[dim] >= (int)mInDims[dim] - 1)) {
+            fracCoord[dim] = 0;
+            index += mInDimOffsets[dim] * (mInDims[dim] - 1);
+        } else {
+            index += mInDimOffsets[dim] * intCoord[dim];
+        }
+    }
+    getCoefRecurse(index, fracCoord, out, 0);
+}
+
+void AudioCoefInterpolator::getCoefRecurse(size_t index,
+                                           const uint32_t fracCoord[],
+                                           audio_coef_t out[], size_t dim) {
+    if (dim == mNumInDims) {
+        memcpy(out, mTable + index, mNumOutDims * sizeof(audio_coef_t));
+    } else {
+        getCoefRecurse(index, fracCoord, out, dim + 1);
+        if (LIKELY(fracCoord != 0)) {
+           audio_coef_t tempCoef[MAX_OUT_DIMS];
+           getCoefRecurse(index + mInDimOffsets[dim], fracCoord, tempCoef,
+                           dim + 1);
+            size_t d = mNumOutDims;
+            while (d-- > 0) {
+                out[d] = interp(out[d], tempCoef[d], fracCoord[dim]);
+            }
+        }
+    }
+}
+
+audio_coef_t AudioCoefInterpolator::interp(audio_coef_t lo, audio_coef_t hi,
+                                           uint32_t frac) {
+    int64_t delta = static_cast<int64_t>(hi-lo) * frac;
+    return lo + static_cast<audio_coef_t> (delta >> 32);
+}
+
+}
diff --git a/media/libeffects/testlibs/AudioCoefInterpolator.h b/media/libeffects/testlibs/AudioCoefInterpolator.h
new file mode 100644
index 0000000..13e5697
--- /dev/null
+++ b/media/libeffects/testlibs/AudioCoefInterpolator.h
@@ -0,0 +1,98 @@
+/* //device/include/server/AudioFlinger/AudioCoefInterpolator.h
+ **
+ ** Copyright 2007, 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 ANDROID_AUDIO_COEF_INTERPOLATOR_H
+#define ANDROID_AUDIO_COEF_INTERPOLATOR_H
+
+#include "AudioCommon.h"
+
+namespace android {
+
+// A helper class for linear interpolation of N-D -> M-D coefficient tables.
+// This class provides support for out-of-range indexes.
+// Details:
+// The purpose is efficient approximation of a N-dimensional vector to
+// M-dimensional function. The approximation is based on a table of output
+// values on a uniform grid of the input values. Values not on the grid are
+// linearly interpolated.
+// Access to values are done by specifying input values in table index units,
+// having an integer and a fractional part, e.g. retrieving a value from index
+// 1.4 will result in linear interpolation between index 1 and index 2.
+class AudioCoefInterpolator {
+public:
+    // Constructor.
+    // nInDims      Number of input dimensions (limited to MAX_IN_DIMS).
+    // inDims       An array of size nInDims with the size of the table on each
+    //              respective dimension.
+    // nOutDims     Number of output dimensions (limited to MAX_OUT_DIMS).
+    // table        The coefficient table. Should be of size:
+    //              inDims[0]*inDims[1]*...*inDims[nInDims-1]*nOutDims, where
+    //              func([i,j,k]) = table(i,j,k,:)
+    AudioCoefInterpolator(size_t nInDims, const size_t inDims[],
+                          size_t nOutDims, const audio_coef_t * table);
+
+    // Get the value of the approximated function at a given point.
+    // intCoord     The integer part of the input value. Should be an array of
+    //              size nInDims.
+    // fracCoord    The fractional part of the input value. Should be an array
+    //              of size nInDims. This value is in 32-bit precision.
+    // out          An array for the output value. Should be of size nOutDims.
+    void getCoef(const int intCoord[], uint32_t fracCoord[], audio_coef_t out[]);
+
+private:
+    // Maximum allowed number of input dimensions.
+    static const size_t MAX_IN_DIMS = 8;
+    // Maximum allowed number of output dimensions.
+    static const size_t MAX_OUT_DIMS = 8;
+
+    // Number of input dimensions.
+    size_t mNumInDims;
+    // Number of input dimensions.
+    size_t mInDims[MAX_IN_DIMS];
+    // The offset between two consecutive indexes of each dimension. This is in
+    // fact a cumulative product of mInDims (done in reverse).
+    size_t mInDimOffsets[MAX_IN_DIMS];
+    // Number of output dimensions.
+    size_t mNumOutDims;
+    // The coefficient table.
+    const audio_coef_t * mTable;
+
+    // A recursive function for getting an interpolated coefficient value.
+    // The recursion depth is the number of input dimensions.
+    // At each step, we fetch two interpolated values of the current dimension,
+    // by two recursive calls to this method for the next dimensions. We then
+    // linearly interpolate these values over the current dimension.
+    // index      The linear integer index of the value we need to interpolate.
+    // fracCoord  A vector of fractional coordinates for each of the input
+    //            dimensions.
+    // out        Where the output should be written. Needs to be of size
+    //            mNumOutDims.
+    // dim        The input dimensions we are currently interpolating. This
+    //            value will be increased on recursive calls.
+    void getCoefRecurse(size_t index, const uint32_t fracCoord[],
+                        audio_coef_t out[], size_t dim);
+
+    // Scalar interpolation of two data points.
+    // lo       The first data point.
+    // hi       The second data point.
+    // frac     A 32-bit fraction designating the weight of the second point.
+    static audio_coef_t interp(audio_coef_t lo, audio_coef_t hi, uint32_t frac);
+};
+
+}
+
+#endif // ANDROID_AUDIO_COEF_INTERPOLATOR_H
diff --git a/media/libeffects/testlibs/AudioCommon.h b/media/libeffects/testlibs/AudioCommon.h
new file mode 100644
index 0000000..444f93a
--- /dev/null
+++ b/media/libeffects/testlibs/AudioCommon.h
@@ -0,0 +1,92 @@
+/*
+**
+** Copyright 2009, 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 ANDROID_AUDIO_COMMON_H
+#define ANDROID_AUDIO_COMMON_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+namespace android {
+
+// Audio coefficient type.
+typedef int32_t audio_coef_t;
+// Audio sample type.
+typedef int32_t audio_sample_t;
+// Accumulator type for coef x sample.
+typedef int64_t audio_coef_sample_acc_t;
+
+// Number of fraction bits for audio coefficient.
+static const int AUDIO_COEF_PRECISION = 24;
+// Audio coefficient with the value of 1.0
+static const audio_coef_t AUDIO_COEF_ONE = 1 << AUDIO_COEF_PRECISION;
+// Audio coefficient with the value of 0.5
+static const audio_coef_t AUDIO_COEF_HALF = 1 << (AUDIO_COEF_PRECISION - 1);
+// Number of fraction bits for audio sample.
+static const int AUDIO_SAMPLE_PRECISION = 24;
+// Audio sample with the value of 1.0
+static const audio_sample_t AUDIO_SAMPLE_ONE = 1 << AUDIO_SAMPLE_PRECISION;
+
+// TODO: These are just temporary naive implementations of the necessary
+// arithmetic operations needed for the filter. They should be moved to a more
+// generic location and implemented more efficiently.
+
+// Multiply a sample by a coefficient to return an accumulator.
+inline audio_coef_sample_acc_t mul_coef_sample(audio_coef_t x, audio_sample_t y) {
+    return ((audio_coef_sample_acc_t) (x)) * y;
+}
+
+// Multiply and accumulate sample by a coefficient to return an accumulator.
+inline audio_coef_sample_acc_t mac_coef_sample(audio_coef_t x, audio_sample_t y, audio_coef_sample_acc_t acc) {
+    return acc + ((audio_coef_sample_acc_t) (x)) * y;
+}
+
+// Convert a sample-coefficient accumulator to a sample.
+inline audio_sample_t coef_sample_acc_to_sample(audio_coef_sample_acc_t acc) {
+    if (acc < 0) {
+        acc += AUDIO_COEF_ONE - 1;
+    }
+    return (audio_sample_t) (acc >> AUDIO_COEF_PRECISION);
+}
+
+// Convert a S15 sample to audio_sample_t
+inline audio_sample_t s15_to_audio_sample_t(int16_t s15) {
+    return audio_sample_t(s15) << 9;
+}
+
+// Convert a audio_sample_t sample to S15 (no clipping)
+inline int16_t audio_sample_t_to_s15(audio_sample_t sample) {
+    return int16_t((sample + (1 << 8)) >> 9);
+}
+
+// Convert a audio_sample_t sample to S15 (with clipping)
+inline int16_t audio_sample_t_to_s15_clip(audio_sample_t sample) {
+    // TODO: optimize for targets supporting this as an atomic operation.
+    if (__builtin_expect(sample >= (0x7FFF << 9), 0)) {
+        return 0x7FFF;
+    } else if (__builtin_expect(sample <= -(0x8000 << 9), 0)) {
+        return 0x8000;
+    } else {
+        return audio_sample_t_to_s15(sample);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+}
+
+#endif // ANDROID_AUDIO_COMMON_H
diff --git a/media/libeffects/testlibs/AudioEqualizer.cpp b/media/libeffects/testlibs/AudioEqualizer.cpp
new file mode 100644
index 0000000..44c9476
--- /dev/null
+++ b/media/libeffects/testlibs/AudioEqualizer.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2009, 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_TAG "AudioEqualizer"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <new>
+#include <utils/Log.h>
+
+#include "AudioEqualizer.h"
+#include "AudioPeakingFilter.h"
+#include "AudioShelvingFilter.h"
+#include "EffectsMath.h"
+
+namespace android {
+
+size_t AudioEqualizer::GetInstanceSize(int nBands) {
+    assert(nBands >= 2);
+    return sizeof(AudioEqualizer) +
+           sizeof(AudioShelvingFilter) * 2 +
+           sizeof(AudioPeakingFilter) * (nBands - 2);
+}
+
+AudioEqualizer * AudioEqualizer::CreateInstance(void * pMem, int nBands,
+                                                int nChannels, int sampleRate,
+                                                const PresetConfig * presets,
+                                                int nPresets) {
+    LOGV("AudioEqualizer::CreateInstance(pMem=%p, nBands=%d, nChannels=%d, "
+         "sampleRate=%d, nPresets=%d)",
+         pMem, nBands, nChannels, sampleRate, nPresets);
+    assert(nBands >= 2);
+    bool ownMem = false;
+    if (pMem == NULL) {
+        pMem = malloc(GetInstanceSize(nBands));
+        if (pMem == NULL) {
+            return NULL;
+        }
+        ownMem = true;
+    }
+    return new (pMem) AudioEqualizer(pMem, nBands, nChannels, sampleRate,
+                                     ownMem, presets, nPresets);
+}
+
+void AudioEqualizer::configure(int nChannels, int sampleRate) {
+    LOGV("AudioEqualizer::configure(nChannels=%d, sampleRate=%d)", nChannels,
+         sampleRate);
+    mpLowShelf->configure(nChannels, sampleRate);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].configure(nChannels, sampleRate);
+    }
+    mpHighShelf->configure(nChannels, sampleRate);
+}
+
+void AudioEqualizer::clear() {
+    LOGV("AudioEqualizer::clear()");
+    mpLowShelf->clear();
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].clear();
+    }
+    mpHighShelf->clear();
+}
+
+void AudioEqualizer::free() {
+    LOGV("AudioEqualizer::free()");
+    if (mpMem != NULL) {
+        ::free(mpMem);
+    }
+}
+
+void AudioEqualizer::reset() {
+    LOGV("AudioEqualizer::reset()");
+    const int32_t bottom = Effects_log2(kMinFreq);
+    const int32_t top = Effects_log2(mSampleRate * 500);
+    const int32_t jump = (top - bottom) / (mNumPeaking + 2);
+    int32_t centerFreq = bottom + jump/2;
+
+    mpLowShelf->reset();
+    mpLowShelf->setFrequency(Effects_exp2(centerFreq));
+    centerFreq += jump;
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].reset();
+        mpPeakingFilters[i].setFrequency(Effects_exp2(centerFreq));
+        centerFreq += jump;
+    }
+    mpHighShelf->reset();
+    mpHighShelf->setFrequency(Effects_exp2(centerFreq));
+    commit(true);
+    mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setGain(int band, int32_t millibel) {
+    LOGV("AudioEqualizer::setGain(band=%d, millibel=%d)", band, millibel);
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        mpLowShelf->setGain(millibel);
+    } else if (band == mNumPeaking + 1) {
+        mpHighShelf->setGain(millibel);
+    } else {
+        mpPeakingFilters[band - 1].setGain(millibel);
+    }
+    mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setFrequency(int band, uint32_t millihertz) {
+    LOGV("AudioEqualizer::setFrequency(band=%d, millihertz=%d)", band,
+         millihertz);
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        mpLowShelf->setFrequency(millihertz);
+    } else if (band == mNumPeaking + 1) {
+        mpHighShelf->setFrequency(millihertz);
+    } else {
+        mpPeakingFilters[band - 1].setFrequency(millihertz);
+    }
+    mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setBandwidth(int band, uint32_t cents) {
+    LOGV("AudioEqualizer::setBandwidth(band=%d, cents=%d)", band, cents);
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band > 0 && band < mNumPeaking + 1) {
+        mpPeakingFilters[band - 1].setBandwidth(cents);
+        mCurPreset = PRESET_CUSTOM;
+    }
+}
+
+int32_t AudioEqualizer::getGain(int band) const {
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        return mpLowShelf->getGain();
+    } else if (band == mNumPeaking + 1) {
+        return mpHighShelf->getGain();
+    } else {
+        return mpPeakingFilters[band - 1].getGain();
+    }
+}
+
+uint32_t AudioEqualizer::getFrequency(int band) const {
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        return mpLowShelf->getFrequency();
+    } else if (band == mNumPeaking + 1) {
+        return mpHighShelf->getFrequency();
+    } else {
+        return mpPeakingFilters[band - 1].getFrequency();
+    }
+}
+
+uint32_t AudioEqualizer::getBandwidth(int band) const {
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0 || band == mNumPeaking + 1) {
+        return 0;
+    } else {
+        return mpPeakingFilters[band - 1].getBandwidth();
+    }
+}
+
+void AudioEqualizer::getBandRange(int band, uint32_t & low,
+                                  uint32_t & high) const {
+    assert(band >= 0 && band < mNumPeaking + 2);
+    if (band == 0) {
+        low = 0;
+        high = mpLowShelf->getFrequency();
+    } else if (band == mNumPeaking + 1) {
+        low = mpHighShelf->getFrequency();
+        high = mSampleRate * 500;
+    } else {
+        mpPeakingFilters[band - 1].getBandRange(low, high);
+    }
+}
+
+const char * AudioEqualizer::getPresetName(int preset) const {
+    assert(preset < mNumPresets && preset >= PRESET_CUSTOM);
+    if (preset == PRESET_CUSTOM) {
+        return "Custom";
+    } else {
+        return mpPresets[preset].name;
+    }
+}
+
+int AudioEqualizer::getNumPresets() const {
+    return mNumPresets;
+}
+
+int AudioEqualizer::getPreset() const {
+    return mCurPreset;
+}
+
+void AudioEqualizer::setPreset(int preset) {
+    LOGV("AudioEqualizer::setPreset(preset=%d)", preset);
+    assert(preset < mNumPresets && preset >= 0);
+    const PresetConfig &presetCfg = mpPresets[preset];
+    for (int band = 0; band < (mNumPeaking + 2); ++band) {
+        const BandConfig & bandCfg = presetCfg.bandConfigs[band];
+        setGain(band, bandCfg.gain);
+        setFrequency(band, bandCfg.freq);
+        setBandwidth(band, bandCfg.bandwidth);
+    }
+    mCurPreset = preset;
+}
+
+void AudioEqualizer::commit(bool immediate) {
+    LOGV("AudioEqualizer::commit(immediate=%d)", immediate);
+    mpLowShelf->commit(immediate);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].commit(immediate);
+    }
+    mpHighShelf->commit(immediate);
+}
+
+void AudioEqualizer::process(const audio_sample_t * pIn,
+                             audio_sample_t * pOut,
+                             int frameCount) {
+//    LOGV("AudioEqualizer::process(frameCount=%d)", frameCount);
+    mpLowShelf->process(pIn, pOut, frameCount);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].process(pIn, pOut, frameCount);
+    }
+    mpHighShelf->process(pIn, pOut, frameCount);
+}
+
+void AudioEqualizer::enable(bool immediate) {
+    LOGV("AudioEqualizer::enable(immediate=%d)", immediate);
+    mpLowShelf->enable(immediate);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].enable(immediate);
+    }
+    mpHighShelf->enable(immediate);
+}
+
+void AudioEqualizer::disable(bool immediate) {
+    LOGV("AudioEqualizer::disable(immediate=%d)", immediate);
+    mpLowShelf->disable(immediate);
+    for (int i = 0; i < mNumPeaking; ++i) {
+        mpPeakingFilters[i].disable(immediate);
+    }
+    mpHighShelf->disable(immediate);
+}
+
+int AudioEqualizer::getMostRelevantBand(uint32_t targetFreq) const {
+    // First, find the two bands that the target frequency is between.
+    uint32_t low = mpLowShelf->getFrequency();
+    if (targetFreq <= low) {
+        return 0;
+    }
+    uint32_t high = mpHighShelf->getFrequency();
+    if (targetFreq >= high) {
+        return mNumPeaking + 1;
+    }
+    int band = mNumPeaking;
+    for (int i = 0; i < mNumPeaking; ++i) {
+        uint32_t freq = mpPeakingFilters[i].getFrequency();
+        if (freq >= targetFreq) {
+            high = freq;
+            band = i;
+            break;
+        }
+        low = freq;
+    }
+    // Now, low is right below the target and high is right above. See which one
+    // is closer on a log scale.
+    low = Effects_log2(low);
+    high = Effects_log2(high);
+    targetFreq = Effects_log2(targetFreq);
+    if (high - targetFreq < targetFreq - low) {
+        return band + 1;
+    } else {
+        return band;
+    }
+}
+
+
+AudioEqualizer::AudioEqualizer(void * pMem, int nBands, int nChannels,
+                               int sampleRate, bool ownMem,
+                               const PresetConfig * presets, int nPresets)
+                               : mSampleRate(sampleRate)
+                               , mpPresets(presets)
+                               , mNumPresets(nPresets) {
+    assert(pMem != NULL);
+    assert(nPresets == 0 || nPresets > 0 && presets != NULL);
+    mpMem = ownMem ? pMem : NULL;
+
+    pMem = (char *) pMem + sizeof(AudioEqualizer);
+    mpLowShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kLowShelf,
+                                                nChannels, sampleRate);
+    pMem = (char *) pMem + sizeof(AudioShelvingFilter);
+    mpHighShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kHighShelf,
+                                                 nChannels, sampleRate);
+    pMem = (char *) pMem + sizeof(AudioShelvingFilter);
+    mNumPeaking = nBands - 2;
+    if (mNumPeaking > 0) {
+        mpPeakingFilters = reinterpret_cast<AudioPeakingFilter *>(pMem);
+        for (int i = 0; i < mNumPeaking; ++i) {
+            new (&mpPeakingFilters[i]) AudioPeakingFilter(nChannels,
+                                                          sampleRate);
+        }
+    }
+    reset();
+}
+
+}
diff --git a/media/libeffects/testlibs/AudioEqualizer.h b/media/libeffects/testlibs/AudioEqualizer.h
new file mode 100644
index 0000000..4028462
--- /dev/null
+++ b/media/libeffects/testlibs/AudioEqualizer.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2009, 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 AUDIOEQUALIZER_H_
+#define AUDIOEQUALIZER_H_
+
+#include "AudioCommon.h"
+
+namespace android {
+
+class AudioShelvingFilter;
+class AudioPeakingFilter;
+
+// A parametric audio equalizer. Supports an arbitrary number of bands and
+// presets.
+// The EQ is composed of a low-shelf, zero or more peaking filters and a high
+// shelf, where each band has frequency and gain controls, and the peaking
+// filters have an additional bandwidth control.
+class AudioEqualizer {
+public:
+    // Configuration of a single band.
+    struct BandConfig {
+        // Gain in millibel.
+        int32_t gain;
+        // Frequency in millihertz.
+        uint32_t freq;
+        // Bandwidth in cents (ignored on shelving filters).
+        uint32_t bandwidth;
+    };
+
+    // Preset configuration.
+    struct PresetConfig {
+        // Human-readable name.
+        const char * name;
+        // An array of size nBands where each element is a configuration for the
+        // corresponding band.
+        const BandConfig * bandConfigs;
+    };
+
+    // This value is used when requesting current preset, and EQ is not using a
+    // preset.
+    static const int PRESET_CUSTOM = -1;
+
+    // Get the required memory size for an instance of this class.
+    // nBands   Number of bands required in the instance.
+    static size_t GetInstanceSize(int nBands);
+
+    // Create an instance of this class.
+    // If succeeds, a respective call is expected to freeInstance(), regardless
+    // of who owns the context memory.
+    // pMem         A memory buffer of at least the size returned by
+    //              GetInstanceSize(), where the instance context is to be
+    //              stored. If NULL, it will be automatically allocated (using
+    //              malloc).
+    // nBands       Number of bands. Must be >= 2.
+    // nChannels    Number of input/output channels (interlaced).
+    // sampleRate   The input/output sample rate, in Hz.
+    // presets      The presets configuration. May be NULL, but in that case the
+    //              client is required not to call preset-related functions.
+    //              This array is owned by the client and is not copied. It
+    //              must be kept valid by the client as long as the instance is
+    //              alive.
+    // nPresets     Number of elements in the presets array.
+    // returns      The instance if success. NULL if pMem is NULL and allocation
+    //              failed.
+    static AudioEqualizer * CreateInstance(void * pMem, int nBands,
+                                           int nChannels,
+                                           int sampleRate,
+                                           const PresetConfig * presets,
+                                           int nPresets);
+
+    // Reconfiguration of the filter. Changes input/output format, but does not
+    // alter current parameter values. Causes reset of the delay lines.
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    void configure(int nChannels, int sampleRate);
+
+    // Resets the filter parameters to the following values:
+    // frequency: 0
+    // gain: 0
+    // bandwidth: 1200 cents.
+    // It also disables the filter. Does not clear the delay lines.
+    void reset();
+
+    // Clears delay lines. Does not alter parameter values.
+    void clear();
+
+    // Frees the object. Will free the memory if the object owned it, i.e. if
+    // a NULL pointer was passed to CreateInstance as pMem.
+    void free();
+
+    // Sets gain value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // band     The band to set the gain for.
+    // millibel Gain value in millibel (1/100 of decibel).
+    void setGain(int band, int32_t millibel);
+
+    // Gets gain of a certain band. This is always the last value set (or
+    // default value after reset).
+    // band     The band to get the gain for.
+    // returns  Gain value in millibel (1/100 of decibel).
+    int32_t getGain(int band) const;
+
+    // Sets cutoff frequency value. Actual change will only take place upon
+    // commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // band       The band to set the frequency for.
+    // millihertz Frequency value in mHz.
+    void setFrequency(int band, uint32_t millihertz);
+
+    // Gets frequency of a certain band. This is always the last value set (or
+    // default value after reset).
+    // band     The band to get the frequency for.
+    // returns  Frequency value in mHz.
+    uint32_t getFrequency(int band) const;
+
+    // Sets bandwidth value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // If called on the first or last band, this call is ignored.
+    // band  The band to set the frequency for.
+    // cents Bandwidth value in cents (1/1200 octave).
+    void setBandwidth(int band, uint32_t cents);
+
+    // Gets bandwidth of a certain band. This is always the last value set (or
+    // default value after reset). For the first and last bands, 0 is always
+    // returned.
+    // band     The band to get the bandwidth for.
+    // returns  Bandwidth value in cents (1/1200 octave).
+    uint32_t getBandwidth(int band) const;
+
+    // Gets lower and upper boundaries of a band.
+    // For the low shelf, the low bound is 0 and the high bound is the band
+    // frequency.
+    // For the high shelf, the low bound is the band frequency and the high
+    // bound is Nyquist.
+    // For the peaking filters, they are the gain[dB]/2 points.
+    void getBandRange(int band, uint32_t & low, uint32_t & high) const;
+
+    // Gets a human-readable name for a preset ID. Will return "Custom" if
+    // PRESET_CUSTOM is passed.
+    // preset       The preset ID. Must be less than number of presets.
+    const char * getPresetName(int preset) const;
+
+    // Gets the number of presets.
+    int getNumPresets() const;
+
+    // Gets the currently set preset ID.
+    // Will return PRESET_CUSTOM in case the EQ parameters have been modified
+    // manually since a preset was set.
+    int getPreset() const;
+
+    // Sets the current preset by ID.
+    // All the band parameters will be overridden.
+    // Change will not be applied until commit() is called.
+    // preset       The preset ID. Must be less than number of presets.
+    //              PRESET_CUSTOM is NOT a valid value here.
+    void setPreset(int preset);
+
+    // Applies all parameter changes done to this point in time.
+    // If the filter is disabled, the new parameters will take place when it is
+    // enabled again. Does not introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly (ignored if filter is
+    // disabled).
+   void commit(bool immediate = false);
+
+    // Process a buffer of input data. The input and output should contain
+    // frameCount * nChannels interlaced samples. Processing can be done
+    // in-place, by passing the same buffer as both arguments.
+    // pIn          Input buffer.
+    // pOut         Output buffer.
+    // frameCount   Number of frames to produce on each call to process().
+    void process(const audio_sample_t * pIn, audio_sample_t * pOut,
+                 int frameCount);
+
+    // Enables the filter, so it would start processing input. Does not
+    // introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void enable(bool immediate = false);
+
+    // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+    // immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void disable(bool immediate = false);
+
+    // Returns the band with the maximum influence on a given frequency.
+    // Result is unaffected by whether EQ is enabled or not, or by whether
+    // changes have been committed or not.
+    // targetFreq   The target frequency, in millihertz.
+    int getMostRelevantBand(uint32_t targetFreq) const;
+
+private:
+    // Bottom frequency, in mHz.
+    static const int kMinFreq = 20000;
+    // Sample rate, in Hz.
+    int mSampleRate;
+    // Number of peaking filters. Total number of bands is +2.
+    int mNumPeaking;
+    // Preset configurations.
+    const PresetConfig * mpPresets;
+    // Number of elements in mpPresets;
+    int mNumPresets;
+    // Current preset.
+    int mCurPreset;
+
+    // Memory space to free when instance is deleted, or NULL if no memory is
+    // owned.
+    void * mpMem;
+    // The low-shelving filter.
+    AudioShelvingFilter * mpLowShelf;
+    // The high-shelving filter.
+    AudioShelvingFilter * mpHighShelf;
+    // An array of size mNumPeaking of peaking filters.
+    AudioPeakingFilter * mpPeakingFilters;
+
+    // Constructor. Resets the filter (see reset()). Must call init() doing
+    // anything else.
+    // pMem       Memory buffer for bands.
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    // ownMem     Whether pMem is owned by me.
+    // presets      The presets configuration. May be NULL, but in that case the
+    //              client is required not to call preset-related functions.
+    //              This array is owned by the client and is not copied. It
+    //              must be kept valid by the client as long as the instance is
+    //              alive.
+    // nPresets     Number of elements in the presets array.
+    AudioEqualizer(void * pMem, int nBands, int nChannels, int sampleRate,
+                   bool ownMem, const PresetConfig * presets, int nPresets);
+};
+
+}
+
+#endif // AUDIOEQUALIZER_H_
diff --git a/media/libeffects/testlibs/AudioFormatAdapter.h b/media/libeffects/testlibs/AudioFormatAdapter.h
new file mode 100644
index 0000000..d93ebe9
--- /dev/null
+++ b/media/libeffects/testlibs/AudioFormatAdapter.h
@@ -0,0 +1,184 @@
+/* /android/src/frameworks/base/media/libeffects/AudioFormatAdapter.h
+**
+** Copyright 2009, 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 AUDIOFORMATADAPTER_H_
+#define AUDIOFORMATADAPTER_H_
+
+#include <media/EffectApi.h>
+
+
+#define min(x,y) (((x) < (y)) ? (x) : (y))
+
+namespace android {
+
+// An adapter for an audio processor working on audio_sample_t samples with a
+// buffer override behavior to arbitrary sample formats and buffer behaviors.
+// The adapter may work on any processing class which has a processing function
+// with the following signature:
+// void process(const audio_sample_t * pIn,
+//              audio_sample_t * pOut,
+//              int frameCount);
+// It is assumed that the underlying processor works in S7.24 format and an
+// overwrite behavior.
+//
+// Usage is simple: just work with the processor normally, but instead of
+// calling its process() function directly, work with the process() function of
+// the adapter.
+// The adapter supports re-configuration to a different format on the fly.
+//
+// T        The processor class.
+// bufSize  The maximum number of samples (single channel) to process on a
+//          single call to the underlying processor. Setting this to a small
+//          number will save a little memory, but will cost function call
+//          overhead, resulting from multiple calls to the underlying process()
+//          per a single call to this class's process().
+template<class T, size_t bufSize>
+class AudioFormatAdapter {
+public:
+    // Configure the adapter.
+    // processor    The underlying audio processor.
+    // nChannels    Number of input and output channels. The adapter does not do
+    //              channel conversion - this parameter must be in sync with the
+    //              actual processor.
+    // pcmFormat    The desired input/output sample format.
+    // behavior     The desired behavior (overwrite or accumulate).
+    void configure(T & processor, int nChannels, uint8_t pcmFormat,
+                   uint32_t behavior) {
+        mpProcessor = &processor;
+        mNumChannels = nChannels;
+        mPcmFormat = pcmFormat;
+        mBehavior = behavior;
+        mMaxSamplesPerCall = bufSize / nChannels;
+    }
+
+    // Process a block of samples.
+    // pIn          A buffer of samples with the format specified on
+    //              configure().
+    // pOut         A buffer of samples with the format specified on
+    //              configure(). May be the same as pIn.
+    // numSamples   The number of multi-channel samples to process.
+    void process(const void * pIn, void * pOut, uint32_t numSamples) {
+        while (numSamples > 0) {
+            uint32_t numSamplesIter = min(numSamples, mMaxSamplesPerCall);
+            uint32_t nSamplesChannels = numSamplesIter * mNumChannels;
+            if (mPcmFormat == SAMPLE_FORMAT_PCM_S7_24) {
+                if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) {
+                    mpProcessor->process(
+                        reinterpret_cast<const audio_sample_t *> (pIn),
+                        reinterpret_cast<audio_sample_t *> (pOut),
+                        numSamplesIter);
+                } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+                    mpProcessor->process(
+                        reinterpret_cast<const audio_sample_t *> (pIn),
+                        mBuffer, numSamplesIter);
+                    MixOutput(pOut, numSamplesIter);
+                } else {
+                    assert(false);
+                }
+                pIn = reinterpret_cast<const audio_sample_t *> (pIn)
+                        + nSamplesChannels;
+                pOut = reinterpret_cast<audio_sample_t *> (pOut)
+                        + nSamplesChannels;
+            } else {
+                ConvertInput(pIn, nSamplesChannels);
+                mpProcessor->process(mBuffer, mBuffer, numSamplesIter);
+                ConvertOutput(pOut, nSamplesChannels);
+            }
+            numSamples -= numSamplesIter;
+        }
+    }
+
+private:
+    // The underlying processor.
+    T * mpProcessor;
+    // The number of input/output channels.
+    int mNumChannels;
+    // The desired PCM format.
+    uint8_t mPcmFormat;
+    // The desired buffer behavior.
+    uint32_t mBehavior;
+    // An intermediate buffer for processing.
+    audio_sample_t mBuffer[bufSize];
+    // The buffer size, divided by the number of channels - represents the
+    // maximum number of multi-channel samples that can be stored in the
+    // intermediate buffer.
+    size_t mMaxSamplesPerCall;
+
+    // Converts a buffer of input samples to audio_sample_t format.
+    // Output is written to the intermediate buffer.
+    // pIn          The input buffer with the format designated in configure().
+    //              When function exist will point to the next unread input
+    //              sample.
+    // numSamples   The number of single-channel samples to process.
+    void ConvertInput(const void *& pIn, uint32_t numSamples) {
+        if (mPcmFormat == SAMPLE_FORMAT_PCM_S15) {
+            const int16_t * pIn16 = reinterpret_cast<const int16_t *>(pIn);
+            audio_sample_t * pOut = mBuffer;
+            while (numSamples-- > 0) {
+                *(pOut++) = s15_to_audio_sample_t(*(pIn16++));
+            }
+            pIn = pIn16;
+        } else {
+            assert(false);
+        }
+    }
+
+    // Converts audio_sample_t samples from the intermediate buffer to the
+    // output buffer, converting to the desired format and buffer behavior.
+    // pOut         The buffer to write the output to.
+    //              When function exist will point to the next output sample.
+    // numSamples   The number of single-channel samples to process.
+    void ConvertOutput(void *& pOut, uint32_t numSamples) {
+        if (mPcmFormat == SAMPLE_FORMAT_PCM_S15) {
+            const audio_sample_t * pIn = mBuffer;
+            int16_t * pOut16 = reinterpret_cast<int16_t *>(pOut);
+            if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) {
+                while (numSamples-- > 0) {
+                    *(pOut16++) = audio_sample_t_to_s15_clip(*(pIn++));
+                }
+            } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+                while (numSamples-- > 0) {
+                    *(pOut16++) += audio_sample_t_to_s15_clip(*(pIn++));
+                }
+            } else {
+                assert(false);
+            }
+            pOut = pOut16;
+        } else {
+            assert(false);
+        }
+    }
+
+    // Accumulate data from the intermediate buffer to the output. Output is
+    // assumed to be of audio_sample_t type.
+    // pOut         The buffer to mix the output to.
+    //              When function exist will point to the next output sample.
+    // numSamples   The number of single-channel samples to process.
+    void MixOutput(void *& pOut, uint32_t numSamples) {
+        const audio_sample_t * pIn = mBuffer;
+        audio_sample_t * pOut24 = reinterpret_cast<audio_sample_t *>(pOut);
+        numSamples *= mNumChannels;
+        while (numSamples-- > 0) {
+            *(pOut24++) += *(pIn++);
+        }
+        pOut = pOut24;
+    }
+};
+
+}
+
+#endif // AUDIOFORMATADAPTER_H_
diff --git a/media/libeffects/testlibs/AudioHighShelfFilterCoef.inl b/media/libeffects/testlibs/AudioHighShelfFilterCoef.inl
new file mode 100644
index 0000000..ebba139
--- /dev/null
+++ b/media/libeffects/testlibs/AudioHighShelfFilterCoef.inl
@@ -0,0 +1,225 @@
+13679,
+21575,
+8921,
+32315056,
+-15582015,
+26172,
+37678,
+14797,
+31891096,
+-15192527,
+51020,
+64449,
+23945,
+31322988,
+-14685186,
+101817,
+106144,
+37744,
+30562882,
+-14031372,
+208996,
+162163,
+58536,
+29548538,
+-13201017,
+442996,
+207459,
+93300,
+28200792,
+-12167331,
+971423,
+128786,
+169690,
+26422744,
+-10915428,
+2200461,
+-465686,
+394986,
+24103317,
+-9455862,
+5119991,
+-2777199,
+1147245,
+21129473,
+-7842294,
+12120379,
+-10198160,
+3631544,
+17411837,
+-6188384,
+28834234,
+-31647135,
+11337795,
+12924960,
+-4672638,
+68037766,
+-88974388,
+33477255,
+7752680,
+-3516098,
+157369944,
+-232063160,
+92282129,
+2113926,
+-2925624,
+353720112,
+-567427144,
+237164112,
+-3659993,
+-3019871,
+769091151,
+-1309871949,
+570539430,
+-9202114,
+-3779302,
+66791,
+121706,
+55888,
+30571245,
+-14038415,
+120426,
+212178,
+94820,
+29559679,
+-13209886,
+217130,
+365165,
+157610,
+28215554,
+-12178243,
+391489,
+617016,
+255010,
+26442131,
+-10928431,
+705862,
+1015147,
+398457,
+24128430,
+-9470680,
+1272682,
+1605251,
+596102,
+21161334,
+-7858153,
+2294668,
+2386833,
+848523,
+17451072,
+-6203880,
+4137327,
+3198789,
+1155536,
+12971362,
+-4685798,
+7459675,
+3470266,
+1567219,
+7804818,
+-3524761,
+13449926,
+1738911,
+2347406,
+2169089,
+-2928116,
+24250455,
+-5211241,
+4358971,
+-3605298,
+-3015671,
+43724001,
+-23849570,
+9823315,
+-9151253,
+-3769277,
+78835150,
+-66542375,
+23686373,
+-14161143,
+-5040790,
+142141173,
+-156324261,
+56024234,
+-18451275,
+-6612656,
+256283057,
+-335606326,
+126341244,
+-21970004,
+-8270755,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
diff --git a/media/libeffects/testlibs/AudioLowShelfFilterCoef.inl b/media/libeffects/testlibs/AudioLowShelfFilterCoef.inl
new file mode 100644
index 0000000..b57deb4
--- /dev/null
+++ b/media/libeffects/testlibs/AudioLowShelfFilterCoef.inl
@@ -0,0 +1,375 @@
+16212506,
+-32420574,
+16208068,
+32401411,
+-15662521,
+16356129,
+-32706246,
+16350118,
+32695525,
+-15939752,
+16464399,
+-32920670,
+16456274,
+32914686,
+-16149441,
+16546128,
+-33081289,
+16535165,
+33077955,
+-16307411,
+16608101,
+-33201422,
+16593328,
+33199569,
+-16426067,
+16655539,
+-33291174,
+16635647,
+33290147,
+-16514997,
+16692478,
+-33358171,
+16665715,
+33357608,
+-16581540,
+16722089,
+-33408149,
+16686099,
+33407850,
+-16631271,
+16746930,
+-33445409,
+16698549,
+33445267,
+-16668405,
+16769156,
+-33473168,
+16704138,
+33473133,
+-16696114,
+16790706,
+-33493827,
+16703348,
+33493886,
+-16716779,
+16813466,
+-33509166,
+16696111,
+33509342,
+-16732186,
+16839437,
+-33520498,
+16681802,
+33520852,
+-16743669,
+16870911,
+-33528765,
+16659191,
+33529424,
+-16752226,
+16910681,
+-33534607,
+16626337,
+33535807,
+-16758602,
+15667401,
+-31326224,
+15658825,
+31252161,
+-14623074,
+15945865,
+-31880007,
+15934146,
+31838205,
+-15144597,
+16157521,
+-32299091,
+16141578,
+32275604,
+-15545369,
+16318267,
+-32614903,
+16296651,
+32601755,
+-15850850,
+16440710,
+-32852157,
+16411473,
+32844820,
+-16082303,
+16534751,
+-33029985,
+16495281,
+33025910,
+-16256891,
+16608171,
+-33163043,
+16554957,
+33160803,
+-16388152,
+16667145,
+-33262468,
+16595477,
+33261275,
+-16486599,
+16716699,
+-33336671,
+16620252,
+33336105,
+-16560301,
+16761100,
+-33391976,
+16631379,
+33391836,
+-16615404,
+16804207,
+-33433103,
+16629806,
+33433341,
+-16656560,
+16849794,
+-33463551,
+16615399,
+33464251,
+-16687277,
+16901887,
+-33485857,
+16586933,
+33487271,
+-16710189,
+16965125,
+-33501781,
+16542000,
+33504415,
+-16727274,
+17045198,
+-33512384,
+16476824,
+33517183,
+-16740008,
+14635201,
+-29254376,
+14619184,
+28977711,
+-12753834,
+15157556,
+-30292825,
+15135285,
+30133938,
+-13674513,
+15561511,
+-31092298,
+15530817,
+31001860,
+-14405551,
+15872211,
+-31702342,
+15830187,
+31651218,
+-14976306,
+16111094,
+-32164834,
+16053843,
+32136101,
+-15416453,
+16295848,
+-32513802,
+16218140,
+32497757,
+-15752817,
+16440852,
+-32776179,
+16335665,
+32767326,
+-16008155,
+16557804,
+-32972907,
+16415715,
+32968179,
+-16201031,
+16656403,
+-33120052,
+16464758,
+33117802,
+-16346195,
+16745001,
+-33229805,
+16486810,
+33229247,
+-16455153,
+16831240,
+-33311306,
+16483692,
+33312252,
+-16536771,
+16922682,
+-33371278,
+16455145,
+33374070,
+-16597819,
+17027472,
+-33414465,
+16398818,
+33420110,
+-16643430,
+17155108,
+-33443875,
+16310110,
+33454398,
+-16677479,
+17317384,
+-33460760,
+16181887,
+33479933,
+-16702882,
+12792703,
+-25557388,
+12764716,
+24590507,
+-9747085,
+13706465,
+-27372621,
+13666215,
+26798296,
+-11169790,
+14439425,
+-28821830,
+14382518,
+28486469,
+-12380088,
+15018453,
+-29957273,
+14939030,
+29764018,
+-13373522,
+15472460,
+-30834757,
+15362688,
+30724568,
+-14168120,
+15828725,
+-31506123,
+15678118,
+31443928,
+-14791822,
+16111406,
+-32015988,
+15905901,
+31981391,
+-15274688,
+16341329,
+-32400984,
+16062061,
+32382398,
+-15644761,
+16536484,
+-32690238,
+16158133,
+32681354,
+-15926286,
+16712853,
+-32906337,
+16201432,
+32904128,
+-16139278,
+16885430,
+-33066336,
+16195306,
+33070090,
+-16299767,
+17069377,
+-33182599,
+16139282,
+33193711,
+-16420332,
+17281371,
+-33263294,
+16029039,
+33285785,
+-16510702,
+17541271,
+-33312390,
+15856243,
+33354359,
+-16578329,
+17874330,
+-33328902,
+15608287,
+33405430,
+-16628873,
+9881279,
+-19719268,
+9838084,
+16734303,
+-5927111,
+11264857,
+-22463447,
+11198784,
+20577584,
+-7572288,
+12460736,
+-24823046,
+12362697,
+23667359,
+-9201903,
+13459805,
+-26776851,
+13317799,
+26085683,
+-10691555,
+14276287,
+-28349256,
+14074406,
+27943899,
+-11978834,
+14936943,
+-29588248,
+14654011,
+29354533,
+-13047453,
+15473300,
+-30549299,
+15081036,
+30417203,
+-13909216,
+15917271,
+-31285788,
+15377817,
+31213972,
+-14589687,
+16299384,
+-31844320,
+15562006,
+31809683,
+-15118811,
+16648774,
+-32262999,
+15645414,
+32254329,
+-15525641,
+16994277,
+-32571090,
+15633607,
+32585895,
+-15835862,
+17366374,
+-32789019,
+15525801,
+32833003,
+-16070975,
+17799955,
+-32927834,
+15314895,
+33017107,
+-16248361,
+18338206,
+-32987318,
+14987686,
+33154246,
+-16381747,
+19038270,
+-32951545,
+14525592,
+33256392,
+-16481800,
diff --git a/media/libeffects/testlibs/AudioPeakingFilter.cpp b/media/libeffects/testlibs/AudioPeakingFilter.cpp
new file mode 100644
index 0000000..60fefe6
--- /dev/null
+++ b/media/libeffects/testlibs/AudioPeakingFilter.cpp
@@ -0,0 +1,121 @@
+/* //device/include/server/AudioFlinger/AudioPeakingFilter.cpp
+ **
+ ** Copyright 2007, 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.
+ */
+
+#include "AudioPeakingFilter.h"
+#include "AudioCommon.h"
+#include "EffectsMath.h"
+
+#include <new>
+#include <assert.h>
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+// Format of the coefficient table:
+// kCoefTable[freq][gain][bw][coef]
+// freq - peak frequency, in octaves below Nyquist,from -9 to -1.
+// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel.
+// bw   - bandwidth, starting at 1 cent, jumps of 1024, to 3073 cents.
+// coef - 0: b0
+//        1: b1
+//        2: b2
+//        3: -a1
+//        4: -a2
+static const size_t kInDims[3] = {9, 15, 4};
+static const audio_coef_t kCoefTable[9*15*4*5] = {
+#include "AudioPeakingFilterCoef.inl"
+};
+
+AudioCoefInterpolator AudioPeakingFilter::mCoefInterp(3, kInDims, 5, (const audio_coef_t*) kCoefTable);
+
+AudioPeakingFilter::AudioPeakingFilter(int nChannels, int sampleRate)
+        : mBiquad(nChannels, sampleRate) {
+    configure(nChannels, sampleRate);
+    reset();
+}
+
+void AudioPeakingFilter::configure(int nChannels, int sampleRate) {
+    mNiquistFreq = sampleRate * 500;
+    mFrequencyFactor = ((1ull) << 42) / mNiquistFreq;
+    mBiquad.configure(nChannels, sampleRate);
+    setFrequency(mNominalFrequency);
+    commit(true);
+}
+
+void AudioPeakingFilter::reset() {
+    setGain(0);
+    setFrequency(0);
+    setBandwidth(2400);
+    commit(true);
+}
+
+void AudioPeakingFilter::setFrequency(uint32_t millihertz) {
+    mNominalFrequency = millihertz;
+    if (UNLIKELY(millihertz > mNiquistFreq / 2)) {
+        millihertz = mNiquistFreq / 2;
+    }
+    uint32_t normFreq = static_cast<uint32_t>(
+            (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10);
+    if (LIKELY(normFreq > (1 << 23))) {
+        mFrequency = (Effects_log2(normFreq) - ((32-9) << 15)) << (FREQ_PRECISION_BITS - 15);
+    } else {
+        mFrequency = 0;
+    }
+}
+
+void AudioPeakingFilter::setGain(int32_t millibel) {
+    mGain = millibel + 9600;
+}
+
+void AudioPeakingFilter::setBandwidth(uint32_t cents) {
+    mBandwidth = cents - 1;
+}
+
+void AudioPeakingFilter::commit(bool immediate) {
+    audio_coef_t coefs[5];
+    int intCoord[3] = {
+        mFrequency >> FREQ_PRECISION_BITS,
+        mGain >> GAIN_PRECISION_BITS,
+        mBandwidth >> BANDWIDTH_PRECISION_BITS
+    };
+    uint32_t fracCoord[3] = {
+        mFrequency << (32 - FREQ_PRECISION_BITS),
+        static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS),
+        mBandwidth << (32 - BANDWIDTH_PRECISION_BITS)
+    };
+    mCoefInterp.getCoef(intCoord, fracCoord, coefs);
+    mBiquad.setCoefs(coefs, immediate);
+}
+
+void AudioPeakingFilter::getBandRange(uint32_t & low, uint32_t & high) const {
+    // Half bandwidth, in octaves, 15-bit precision
+    int32_t halfBW = (((mBandwidth + 1) / 2) << 15) / 1200;
+
+    low = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(-halfBW + (16 << 15))) >> 16);
+    if (UNLIKELY(halfBW >= (16 << 15))) {
+        high = mNiquistFreq;
+    } else {
+        high = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(halfBW + (16 << 15))) >> 16);
+        if (UNLIKELY(high > mNiquistFreq)) {
+            high = mNiquistFreq;
+        }
+    }
+}
+
+}
+
diff --git a/media/libeffects/testlibs/AudioPeakingFilter.h b/media/libeffects/testlibs/AudioPeakingFilter.h
new file mode 100644
index 0000000..d0f49c9
--- /dev/null
+++ b/media/libeffects/testlibs/AudioPeakingFilter.h
@@ -0,0 +1,151 @@
+/* //device/include/server/AudioFlinger/AudioPeakingFilter.h
+**
+** Copyright 2009, 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 ANDROID_AUDIO_PEAKING_FILTER_H
+#define ANDROID_AUDIO_PEAKING_FILTER_H
+
+#include "AudioBiquadFilter.h"
+#include "AudioCoefInterpolator.h"
+
+namespace android {
+
+// A peaking audio filter, with unity skirt gain, and controllable peak
+// frequency, gain and bandwidth.
+// This filter is able to suppress introduce discontinuities and other artifacts
+// in the output, even when changing parameters abruptly.
+// Parameters can be set to any value - this class will make sure to clip them
+// when they are out of supported range.
+//
+// Implementation notes:
+// This class uses an underlying biquad filter whose parameters are determined
+// using a linear interpolation from a coefficient table, using a
+// AudioCoefInterpolator.
+// All is left for this class to do is mapping between high-level parameters to
+// fractional indices into the coefficient table.
+class AudioPeakingFilter {
+public:
+    // Constructor. Resets the filter (see reset()).
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    AudioPeakingFilter(int nChannels, int sampleRate);
+
+    // Reconfiguration of the filter. Changes input/output format, but does not
+    // alter current parameter values. Clears delay lines.
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    void configure(int nChannels, int sampleRate);
+
+    // Resets the filter parameters to the following values:
+    // frequency: 0
+    // gain: 0
+    // bandwidth: 1200 cents.
+    // It also disables the filter. Does not clear the delay lines.
+    void reset();
+
+    // Clears delay lines. Does not alter parameter values.
+    void clear() { mBiquad.clear(); }
+
+    // Sets gain value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // millibel Gain value in millibel (1/100 of decibel).
+    void setGain(int32_t millibel);
+
+    // Gets the gain, in millibel, as set.
+    int32_t getGain() const { return mGain - 9600; }
+
+    // Sets bandwidth value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // cents Bandwidth value in cents (1/1200 octave).
+    void setBandwidth(uint32_t cents);
+
+    // Gets the gain, in cents, as set.
+    uint32_t getBandwidth() const { return mBandwidth + 1; }
+
+    // Sets frequency value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // millihertz Frequency value in mHz.
+    void setFrequency(uint32_t millihertz);
+
+    // Gets the frequency, in mHz, as set.
+    uint32_t getFrequency() const { return mNominalFrequency; }
+
+    // Gets gain[dB]/2 points.
+    // Results in mHz, and are computed based on the nominal values set, not on
+    // possibly rounded or truncated actual values.
+    void getBandRange(uint32_t & low, uint32_t & high) const;
+
+    // Applies all parameter changes done to this point in time.
+    // If the filter is disabled, the new parameters will take place when it is
+    // enabled again. Does not introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly (ignored if filter is
+    // disabled).
+   void commit(bool immediate = false);
+
+    // Process a buffer of input data. The input and output should contain
+    // frameCount * nChannels interlaced samples. Processing can be done
+    // in-place, by passing the same buffer as both arguments.
+    // in           Input buffer.
+    // out          Output buffer.
+    // frameCount   Number of frames to produce.
+    void process(const audio_sample_t in[], audio_sample_t out[],
+                 int frameCount) { mBiquad.process(in, out, frameCount); }
+
+    // Enables the filter, so it would start processing input. Does not
+    // introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void enable(bool immediate = false) { mBiquad.enable(immediate); }
+
+    // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+    // immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void disable(bool immediate = false) { mBiquad.disable(immediate); }
+
+private:
+    // Precision for the mFrequency member.
+    static const int FREQ_PRECISION_BITS = 26;
+    // Precision for the mGain member.
+    static const int GAIN_PRECISION_BITS = 10;
+    // Precision for the mBandwidth member.
+    static const int BANDWIDTH_PRECISION_BITS = 10;
+
+    // Nyquist, in mHz.
+    uint32_t mNiquistFreq;
+    // Fractional index into the gain dimension of the coef table in
+    // GAIN_PRECISION_BITS precision.
+    int32_t mGain;
+    // Fractional index into the bandwidth dimension of the coef table in
+    // BANDWIDTH_PRECISION_BITS precision.
+    uint32_t mBandwidth;
+    // Fractional index into the frequency dimension of the coef table in
+    // FREQ_PRECISION_BITS precision.
+    uint32_t mFrequency;
+    // Nominal value of frequency, as set.
+    uint32_t mNominalFrequency;
+    // 1/Nyquist[mHz], in 42-bit precision (very small).
+    // Used for scaling the frequency.
+    uint32_t mFrequencyFactor;
+
+    // A biquad filter, used for the actual processing.
+    AudioBiquadFilter mBiquad;
+    // A coefficient interpolator, used for mapping the high level parameters to
+    // the low-level biquad coefficients.
+    static AudioCoefInterpolator mCoefInterp;
+};
+
+}
+
+#endif // ANDROID_AUDIO_PEAKING_FILTER_H
diff --git a/media/libeffects/testlibs/AudioPeakingFilterCoef.inl b/media/libeffects/testlibs/AudioPeakingFilterCoef.inl
new file mode 100644
index 0000000..374c6e1
--- /dev/null
+++ b/media/libeffects/testlibs/AudioPeakingFilterCoef.inl
@@ -0,0 +1,2700 @@
+16769751,
+-33538871,
+16769751,
+33538871,
+-16762286,
+11468083,
+-22935566,
+11467915,
+22935566,
+-6158781,
+8532673,
+-17064763,
+8532412,
+17064763,
+-287869,
+6567366,
+-13134160,
+6567042,
+13134160,
+3642808,
+16773075,
+-33545518,
+16773075,
+33545518,
+-16768934,
+13349658,
+-26698459,
+13349304,
+26698459,
+-9921746,
+10923581,
+-21846147,
+10922977,
+21846147,
+-5069342,
+9009390,
+-18017641,
+9008590,
+18017641,
+-1240764,
+16774919,
+-33549207,
+16774919,
+33549207,
+-16772622,
+14686150,
+-29371047,
+14685450,
+29371047,
+-12594384,
+12933736,
+-25865697,
+12932448,
+25865697,
+-9088968,
+11350364,
+-22698482,
+11348545,
+22698482,
+-5921693,
+16775943,
+-33551252,
+16775941,
+33551252,
+-16774668,
+15549746,
+-31097569,
+15548408,
+31097569,
+-14320938,
+14404163,
+-28805197,
+14401577,
+28805197,
+-12028524,
+13261978,
+-26519626,
+13258147,
+26519626,
+-9742909,
+16776511,
+-33552387,
+16776508,
+33552387,
+-16775803,
+16074349,
+-32145600,
+16071856,
+32145600,
+-15368989,
+15374244,
+-30742933,
+15369268,
+30742933,
+-13966296,
+14629431,
+-29250695,
+14621814,
+29250695,
+-12474030,
+16776826,
+-33553017,
+16776822,
+33553017,
+-16776432,
+16381548,
+-32757900,
+16376968,
+32757900,
+-15981300,
+15972161,
+-31934402,
+15962842,
+31934402,
+-15157787,
+15518882,
+-31022614,
+15504316,
+31022614,
+-14245982,
+16777003,
+-33553366,
+16776995,
+33553366,
+-16776781,
+16558315,
+-33107660,
+16549969,
+33107660,
+-16331067,
+16326848,
+-32635910,
+16309677,
+32635910,
+-15859308,
+16064456,
+-32101133,
+16037281,
+32101133,
+-15324521,
+16777103,
+-33553559,
+16777088,
+33553559,
+-16776975,
+16660325,
+-33304885,
+16645187,
+33304885,
+-16528296,
+16535200,
+-33038436,
+16503858,
+33038436,
+-16261842,
+16391425,
+-32732273,
+16341464,
+32732273,
+-15955673,
+16777162,
+-33553667,
+16777136,
+33553667,
+-16777082,
+16721651,
+-33415288,
+16694267,
+33415288,
+-16638701,
+16661761,
+-33265997,
+16604862,
+33265997,
+-16489407,
+16592417,
+-33093137,
+16501343,
+33093137,
+-16316544,
+16777203,
+-33553726,
+16777155,
+33553726,
+-16777142,
+16763466,
+-33476836,
+16714001,
+33476836,
+-16700251,
+16748588,
+-33393565,
+16645605,
+33393565,
+-16616978,
+16731288,
+-33296733,
+16566071,
+33296733,
+-16520144,
+16777238,
+-33553759,
+16777152,
+33553759,
+-16777175,
+16800489,
+-33511071,
+16711212,
+33511071,
+-16734485,
+16825723,
+-33464740,
+16639647,
+33464740,
+-16688154,
+16855137,
+-33410736,
+16556228,
+33410736,
+-16634149,
+16777282,
+-33553778,
+16777127,
+33553778,
+-16777193,
+16845889,
+-33530088,
+16684830,
+33530088,
+-16753503,
+16920437,
+-33504347,
+16584541,
+33504347,
+-16727762,
+17007449,
+-33474302,
+16467484,
+33474302,
+-16697716,
+16777349,
+-33553788,
+16777070,
+33553788,
+-16777203,
+16915880,
+-33540645,
+16625396,
+33540645,
+-16764060,
+17066504,
+-33526354,
+16460481,
+33526354,
+-16749769,
+17242444,
+-33509662,
+16267849,
+33509662,
+-16733077,
+16777464,
+-33553793,
+16776961,
+33553793,
+-16777209,
+17035487,
+-33546503,
+16511647,
+33546503,
+-16769918,
+17316137,
+-33538572,
+16223067,
+33538572,
+-16761988,
+17644089,
+-33529306,
+15885848,
+33529306,
+-16752721,
+16777668,
+-33553796,
+16776760,
+33553796,
+-16777212,
+17247484,
+-33549752,
+16302900,
+33549752,
+-16773168,
+17758603,
+-33545353,
+15787381,
+33545353,
+-16768768,
+18356007,
+-33540211,
+15184835,
+33540211,
+-16763626,
+16762293,
+-33522062,
+16762293,
+33522062,
+-16747370,
+8711405,
+-17421242,
+8711149,
+17421242,
+-645338,
+5721250,
+-11441288,
+5720900,
+11441288,
+5335066,
+4082836,
+-8164655,
+4082434,
+8164655,
+8611946,
+16768936,
+-33535347,
+16768936,
+33535347,
+-16760656,
+11085056,
+-22167856,
+11084469,
+22167856,
+-5392309,
+8098223,
+-16194333,
+8097329,
+16194333,
+581664,
+6158323,
+-12314623,
+6157228,
+12314623,
+4461665,
+16772623,
+-33542719,
+16772622,
+33542719,
+-16768029,
+13058634,
+-26114055,
+13057388,
+26114055,
+-9338806,
+10523211,
+-21042742,
+10521116,
+21042742,
+-4267110,
+8576560,
+-17149081,
+8573812,
+17149081,
+-373156,
+16774670,
+-33546810,
+16774667,
+33546810,
+-16772120,
+14489725,
+-28974776,
+14487233,
+28974776,
+-12199742,
+12619509,
+-25232587,
+12614979,
+25232587,
+-8457271,
+10965151,
+-21922319,
+10958818,
+21922319,
+-5146753,
+16775805,
+-33549079,
+16775800,
+33549079,
+-16774390,
+15428102,
+-30849095,
+15423317,
+30849095,
+-14074202,
+14188157,
+-28364996,
+14178975,
+28364996,
+-11589916,
+12969900,
+-25924346,
+12956398,
+25924346,
+-9149082,
+16776437,
+-33550338,
+16776428,
+33550338,
+-16775648,
+16004216,
+-31997074,
+15995268,
+31997074,
+-15222267,
+15241233,
+-30462393,
+15223454,
+30462393,
+-13687471,
+14437070,
+-28844880,
+14409982,
+28844880,
+-12069836,
+16776789,
+-33551036,
+16776773,
+33551036,
+-16776347,
+16345158,
+-32671383,
+16328685,
+32671383,
+-15896627,
+15900462,
+-31765104,
+15867034,
+31765104,
+-14990280,
+15410846,
+-30767279,
+15358750,
+30767279,
+-13992380,
+16776990,
+-33551423,
+16776960,
+33551423,
+-16776734,
+16545156,
+-33057769,
+16515103,
+33057769,
+-16283043,
+16300504,
+-32536823,
+16238769,
+32536823,
+-15762058,
+16024071,
+-31948201,
+15926537,
+31948201,
+-15173391,
+16777109,
+-33551638,
+16777056,
+33551638,
+-16776949,
+16666542,
+-33276035,
+16611999,
+33276035,
+-16501325,
+16548270,
+-32981225,
+16435439,
+32981225,
+-16206493,
+16412621,
+-32643103,
+16232940,
+32643103,
+-15868346,
+16777189,
+-33551757,
+16777094,
+33551757,
+-16777068,
+16749778,
+-33398338,
+16651075,
+33398338,
+-16623637,
+16720233,
+-33232976,
+16515245,
+33232976,
+-16458262,
+16686059,
+-33041706,
+16358135,
+33041706,
+-16266978,
+16777261,
+-33551823,
+16777089,
+33551823,
+-16777134,
+16823703,
+-33466559,
+16645376,
+33466559,
+-16691863,
+16873974,
+-33374267,
+16502806,
+33374267,
+-16599564,
+16932398,
+-33267006,
+16337114,
+33267006,
+-16492295,
+16777348,
+-33551860,
+16777038,
+33551860,
+-16777170,
+16914465,
+-33504517,
+16592574,
+33504517,
+-16729824,
+17063236,
+-33453150,
+16392432,
+33453150,
+-16678453,
+17236595,
+-33393293,
+16159213,
+33393293,
+-16618592,
+16777483,
+-33551880,
+16776924,
+33551880,
+-16777191,
+17054436,
+-33525606,
+16473695,
+33525606,
+-16750914,
+17355321,
+-33497061,
+16144262,
+33497061,
+-16722367,
+17706453,
+-33463749,
+15759816,
+33463749,
+-16689053,
+16777713,
+-33551891,
+16776705,
+33551891,
+-16777202,
+17293646,
+-33537314,
+16246194,
+33537314,
+-16762623,
+17854571,
+-33521465,
+15669419,
+33521465,
+-16746773,
+18509706,
+-33502954,
+14995772,
+33502954,
+-16728261,
+16778120,
+-33551898,
+16776304,
+33551898,
+-16777208,
+17717639,
+-33543811,
+15828698,
+33543811,
+-16769121,
+18739501,
+-33535016,
+14798040,
+33535016,
+-16760325,
+19933534,
+-33524738,
+13593729,
+33524738,
+-16750047,
+16747397,
+-33484705,
+16747396,
+33484705,
+-16717577,
+5883112,
+-11762335,
+5882767,
+11762335,
+5011337,
+3448701,
+-6894903,
+3448279,
+6894903,
+9880236,
+2324286,
+-4646714,
+2323828,
+4646714,
+12129102,
+16760665,
+-33511232,
+16760663,
+33511232,
+-16744112,
+8276984,
+-16548106,
+8276108,
+16548106,
+224124,
+5337400,
+-10670406,
+5336221,
+10670406,
+6103596,
+3771525,
+-7539439,
+3770185,
+7539439,
+9235506,
+16768033,
+-33525963,
+16768030,
+33525963,
+-16758848,
+10689564,
+-21370649,
+10687524,
+21370649,
+-4599872,
+7666068,
+-15324466,
+7663015,
+15324466,
+1448133,
+5761266,
+-11515371,
+5757575,
+11515371,
+5258376,
+16772124,
+-33534139,
+16772118,
+33534139,
+-16767026,
+12751423,
+-25490780,
+12747036,
+25490780,
+-8721243,
+10113942,
+-20214533,
+10106682,
+20214533,
+-3443407,
+8145025,
+-16275741,
+8135620,
+16275741,
+496571,
+16774395,
+-33538675,
+16774385,
+33538675,
+-16771564,
+14280137,
+-28542819,
+14271281,
+28542819,
+-11774202,
+12292391,
+-24561476,
+12276485,
+24561476,
+-7791660,
+10572949,
+-21117532,
+10550945,
+21117532,
+-4346678,
+16775657,
+-33541192,
+16775639,
+33541192,
+-16774081,
+15299683,
+-30573051,
+15282579,
+30573051,
+-13805046,
+13964251,
+-27887539,
+13931690,
+27887539,
+-11118724,
+12672686,
+-25290241,
+12625174,
+25290241,
+-8520644,
+16776363,
+-33542588,
+16776330,
+33542588,
+-16775477,
+15935196,
+-31828699,
+15903092,
+31828699,
+-15061072,
+15112356,
+-30152153,
+15048881,
+30152153,
+-13384021,
+14253857,
+-28402950,
+14157649,
+28402950,
+-11634291,
+16776763,
+-33543362,
+16776704,
+33543362,
+-16776252,
+16319830,
+-32570615,
+16260598,
+32570615,
+-15803212,
+15851783,
+-31574208,
+15731938,
+31574208,
+-14806505,
+15339614,
+-30483871,
+15153441,
+30483871,
+-13715838,
+16777001,
+-33543791,
+16776896,
+33543791,
+-16776681,
+16557673,
+-32997208,
+16449476,
+32997208,
+-16229933,
+16326977,
+-32422299,
+16105089,
+32422299,
+-15654851,
+16067244,
+-31775024,
+15717353,
+31775024,
+-15007381,
+16777163,
+-33544029,
+16776972,
+33544029,
+-16776919,
+16722590,
+-33238660,
+16526083,
+33238660,
+-16471458,
+16664322,
+-32912610,
+16258203,
+32912610,
+-16145310,
+16597629,
+-32539419,
+15951593,
+32539419,
+-15772007,
+16777306,
+-33544162,
+16776962,
+33544162,
+-16777051,
+16869955,
+-33374105,
+16514205,
+33374105,
+-16606944,
+16969714,
+-33190996,
+16231282,
+33190996,
+-16423780,
+17084972,
+-32979442,
+15904406,
+32979442,
+-16212162,
+16777480,
+-33544235,
+16776860,
+33544235,
+-16777125,
+17051328,
+-33449703,
+16408452,
+33449703,
+-16682565,
+17347583,
+-33347437,
+16009901,
+33347437,
+-16580267,
+17691668,
+-33228659,
+15547002,
+33228659,
+-16461454,
+16777750,
+-33544275,
+16776632,
+33544275,
+-16777165,
+17331222,
+-33491780,
+16170648,
+33491780,
+-16724654,
+17931550,
+-33434840,
+15513363,
+33434840,
+-16667697,
+18630855,
+-33368512,
+14747710,
+33368512,
+-16601349,
+16778210,
+-33544298,
+16776194,
+33544298,
+-16777188,
+17809628,
+-33515162,
+15715631,
+33515162,
+-16748043,
+18929991,
+-33483514,
+14563611,
+33483514,
+-16716385,
+20237212,
+-33446587,
+13219451,
+33446587,
+-16679448,
+16779025,
+-33544310,
+16775392,
+33544310,
+-16777200,
+18657612,
+-33528145,
+14880634,
+33528145,
+-16761030,
+20699844,
+-33510571,
+12820822,
+33510571,
+-16743451,
+23084863,
+-33490047,
+10415274,
+33490047,
+-16722921,
+16717684,
+-33395091,
+16717682,
+33395091,
+-16658149,
+3567009,
+-7125006,
+3566590,
+7125006,
+9643617,
+1921926,
+-3838751,
+1921455,
+3838751,
+12933835,
+1248662,
+-2493824,
+1248170,
+2493824,
+14280384,
+16744147,
+-33447952,
+16744143,
+33447952,
+-16711074,
+5493785,
+-10973174,
+5492622,
+10973174,
+5790808,
+3173694,
+-6338342,
+3172292,
+6338342,
+10431230,
+2124754,
+-4242881,
+2123244,
+4242881,
+12529218,
+16758861,
+-33477342,
+16758855,
+33477342,
+-16740500,
+7843885,
+-15665884,
+7840892,
+15665884,
+1092439,
+4968649,
+-9921376,
+4964692,
+9921376,
+6843875,
+3478437,
+-6944043,
+3473981,
+6944043,
+9824798,
+16767035,
+-33493665,
+16767024,
+33493665,
+-16756842,
+10284421,
+-20536999,
+10277346,
+20536999,
+-3784550,
+7240254,
+-14452686,
+7229862,
+14452686,
+2307100,
+5379798,
+-10734231,
+5367379,
+10734231,
+6030039,
+16771575,
+-33502725,
+16771555,
+33502725,
+-16765913,
+12431046,
+-24816749,
+12415632,
+24816749,
+-8069462,
+9702049,
+-19355664,
+9676957,
+19355664,
+-2601790,
+7722611,
+-15394544,
+7690499,
+15394544,
+1364106,
+16774099,
+-33507752,
+16774063,
+33507752,
+-16770946,
+14062583,
+-28059903,
+14031160,
+28059903,
+-11316527,
+11962999,
+-23841519,
+11907273,
+23841519,
+-7093056,
+10188929,
+-20277142,
+10112667,
+20277142,
+-3524380,
+16775510,
+-33510541,
+16775445,
+33510541,
+-16773738,
+15175102,
+-30252637,
+15114019,
+30252637,
+-13511905,
+13753207,
+-27358123,
+13637911,
+27358123,
+-10613901,
+12400971,
+-24605416,
+12234119,
+24605416,
+-7857874,
+16776310,
+-33512088,
+16776193,
+33512088,
+-16775287,
+15888242,
+-31623221,
+15773117,
+31623221,
+-14884143,
+15028972,
+-29795608,
+14802570,
+29795608,
+-13054325,
+14142237,
+-27909578,
+13801000,
+27909578,
+-11166021,
+16776787,
+-33512946,
+16776575,
+33512946,
+-16776146,
+16345172,
+-32438302,
+16132251,
+32438302,
+-15700207,
+15905856,
+-31344484,
+15476429,
+31344484,
+-14605069,
+15428324,
+-30155514,
+14763558,
+30155514,
+-13414665,
+16777110,
+-33513422,
+16776729,
+33513422,
+-16776623,
+16668950,
+-32908744,
+16279482,
+32908744,
+-16171216,
+16555594,
+-32275015,
+15758344,
+32275015,
+-15536722,
+16428465,
+-31564284,
+15173886,
+31564284,
+-14825134,
+16777395,
+-33513686,
+16776708,
+33513686,
+-16776887,
+16961758,
+-33175594,
+16253845,
+33175594,
+-16438387,
+17158212,
+-32815329,
+15696692,
+32815329,
+-16077688,
+17382578,
+-32403880,
+15060381,
+32403880,
+-15665743,
+16777745,
+-33513832,
+16776505,
+33513832,
+-16777033,
+17323903,
+-33325470,
+16041757,
+33325470,
+-16588444,
+17911332,
+-33122874,
+15251488,
+33122874,
+-16385604,
+18589203,
+-32889086,
+14339546,
+32889086,
+-16151534,
+16778283,
+-33513913,
+16776048,
+33513913,
+-16777115,
+17883505,
+-33409180,
+15565966,
+33409180,
+-16672255,
+19078451,
+-33295944,
+14257648,
+33295944,
+-16558883,
+20465440,
+-33164510,
+12739067,
+33164510,
+-16427290,
+16779203,
+-33513958,
+16775173,
+33513958,
+-16777160,
+18840265,
+-33455789,
+14655871,
+33455789,
+-16718921,
+21075121,
+-33392715,
+12357866,
+33392715,
+-16655771,
+23677621,
+-33319266,
+9681828,
+33319266,
+-16582233,
+16780834,
+-33513983,
+16773567,
+33513983,
+-16777185,
+20536227,
+-33481696,
+12985848,
+33481696,
+-16744859,
+24614855,
+-33446630,
+8872112,
+33446630,
+-16709751,
+29373075,
+-33405721,
+4072934,
+33405721,
+-16668793,
+16658572,
+-33156710,
+16658568,
+33156710,
+-16539925,
+1995694,
+-3971702,
+1995225,
+3971702,
+12786296,
+1019334,
+-2028355,
+1018835,
+2028355,
+14739047,
+648397,
+-1290041,
+647886,
+1290041,
+15480933,
+16711208,
+-33261470,
+16711201,
+33261470,
+-16645192,
+3284873,
+-6536727,
+3283483,
+6536727,
+10208860,
+1752746,
+-3487071,
+1751198,
+3487071,
+13273272,
+1134254,
+-2255981,
+1132642,
+2255981,
+14510319,
+16740546,
+-33319859,
+16740534,
+33319859,
+-16703864,
+5119019,
+-10184853,
+5115113,
+10184853,
+6543083,
+2916766,
+-5800820,
+2912122,
+5800820,
+10948329,
+1940950,
+-3858260,
+1935979,
+3858260,
+12900288,
+16756866,
+-33352332,
+16756844,
+33352332,
+-16736493,
+7416141,
+-14750709,
+7405941,
+14750709,
+1955134,
+4618132,
+-9178604,
+4604884,
+9178604,
+7554200,
+3205731,
+-6365873,
+3190944,
+6365873,
+10380541,
+16765937,
+-33370369,
+16765897,
+33370369,
+-16754618,
+9875714,
+-19631961,
+9851238,
+19631961,
+-2949736,
+6828874,
+-13556870,
+6793592,
+13556870,
+3154751,
+5021920,
+-9953987,
+4980230,
+9953987,
+6775066,
+16770983,
+-33380381,
+16770911,
+33380381,
+-16764679,
+12107731,
+-24045066,
+12053679,
+24045066,
+-7384194,
+9304697,
+-18433704,
+9218200,
+18433704,
+-1745681,
+7330173,
+-14480925,
+7220819,
+14480925,
+2226224,
+16773804,
+-33385937,
+16773674,
+33385937,
+-16770261,
+13857067,
+-27469883,
+13745731,
+27469883,
+-10825583,
+11667230,
+-23028209,
+11472403,
+23028209,
+-6362417,
+9861509,
+-19365642,
+9597835,
+19365642,
+-2682128,
+16775405,
+-33389019,
+16775170,
+33389019,
+-16773358,
+15094166,
+-29826057,
+14876207,
+29826057,
+-13193157,
+13629575,
+-26722225,
+13221948,
+26722225,
+-10074307,
+12261304,
+-23822520,
+11676482,
+23822520,
+-7160571,
+16776358,
+-33390729,
+16775935,
+33390729,
+-16775076,
+15939973,
+-31315809,
+15527360,
+31315809,
+-14690117,
+15140254,
+-29331850,
+14333520,
+29331850,
+-12696558,
+14324552,
+-27308240,
+13115821,
+27308240,
+-10663157,
+16777004,
+-33391677,
+16776241,
+33391677,
+-16776029,
+16564519,
+-32208051,
+15799374,
+32208051,
+-15586676,
+16349720,
+-31011538,
+14811870,
+31011538,
+-14384374,
+16117884,
+-29720119,
+13746038,
+29720119,
+-13086705,
+16777574,
+-33392203,
+16776199,
+33392203,
+-16776558,
+17142623,
+-32725183,
+15740903,
+32725183,
+-16106310,
+17523746,
+-32028793,
+14660021,
+32028793,
+-15406551,
+17949452,
+-31250941,
+13452699,
+31250941,
+-14624935,
+16778273,
+-33392495,
+16775794,
+33392495,
+-16776851,
+17864511,
+-33019221,
+15314476,
+33019221,
+-16401771,
+19019582,
+-32622294,
+13760557,
+32622294,
+-16002923,
+20335886,
+-32169961,
+11989731,
+32169961,
+-15548401,
+16779350,
+-33392657,
+16774879,
+33392657,
+-16777014,
+18982972,
+-33184592,
+14362186,
+33184592,
+-16567942,
+21350554,
+-32961046,
+11769976,
+32961046,
+-16343314,
+24079688,
+-32703362,
+8781912,
+32703362,
+-16084383,
+16781190,
+-33392746,
+16773130,
+33392746,
+-16777104,
+20896303,
+-33277026,
+12541737,
+33277026,
+-16660824,
+25343199,
+-33151977,
+7969185,
+33151977,
+-16535169,
+30502384,
+-33006896,
+2664219,
+33006896,
+-16389387,
+16784451,
+-33392796,
+16769918,
+33392796,
+-16777154,
+24288258,
+-33328516,
+9201520,
+33328516,
+-16712562,
+32423187,
+-33258828,
+996567,
+33258828,
+-16642538,
+41895320,
+-33177686,
+-8557101,
+33177686,
+-16561003,
+16541595,
+-32447498,
+16541587,
+32447498,
+-16305966,
+1060925,
+-2080590,
+1060426,
+2080590,
+14655865,
+525478,
+-1030256,
+524962,
+1030256,
+15726776,
+330321,
+-647437,
+329800,
+647437,
+16117095,
+16645717,
+-32651734,
+16645703,
+32651734,
+-16514203,
+1820789,
+-3570095,
+1819248,
+3570095,
+13137179,
+924575,
+-1812018,
+922942,
+1812018,
+14929699,
+586684,
+-1149186,
+585016,
+1149186,
+15605516,
+16704036,
+-32766121,
+16704011,
+32766121,
+-16630831,
+3020875,
+-5921138,
+3016266,
+5921138,
+10740076,
+1597573,
+-3128764,
+1592487,
+3128764,
+13587156,
+1030124,
+-2015487,
+1024848,
+2015487,
+14722244,
+16736565,
+-32829909,
+16736521,
+32829909,
+-16695869,
+4762013,
+-9328185,
+4748922,
+9328185,
+7266281,
+2679566,
+-5241091,
+2664205,
+5241091,
+11433446,
+1773912,
+-3463620,
+1757564,
+3463620,
+13245740,
+16754673,
+-32865395,
+16754593,
+32865395,
+-16732050,
+7001772,
+-13700468,
+6967104,
+13700468,
+2808340,
+4293363,
+-8378312,
+4249089,
+8378312,
+8234764,
+2960061,
+-5758307,
+2911058,
+5758307,
+10906097,
+16764756,
+-32885110,
+16764611,
+32885110,
+-16752151,
+9480188,
+-18513215,
+9395722,
+18513215,
+-2098694,
+6453693,
+-12542171,
+6334194,
+12542171,
+3989330,
+4710641,
+-9103264,
+4570966,
+9103264,
+7495609,
+16770393,
+-32896054,
+16770133,
+32896054,
+-16763310,
+11816276,
+-22992949,
+11627131,
+22992949,
+-6666191,
+8975726,
+-17314789,
+8678280,
+17314789,
+-876790,
+7032408,
+-13430164,
+6660869,
+13430164,
+3083940,
+16773593,
+-32902127,
+16773124,
+32902127,
+-16769502,
+13735615,
+-26557052,
+13341720,
+26557052,
+-10300120,
+11528165,
+-21946606,
+10848400,
+21946606,
+-5599349,
+9752563,
+-18238110,
+8842853,
+18238110,
+-1818200,
+16775499,
+-32905496,
+16774654,
+32905496,
+-16772937,
+15200588,
+-29054957,
+14423589,
+29054957,
+-12846961,
+13857004,
+-25769995,
+12417855,
+25769995,
+-9497643,
+12624453,
+-22756500,
+10577873,
+22756500,
+-6425111,
+16776792,
+-32907365,
+16775267,
+32907365,
+-16774843,
+16366344,
+-30654089,
+14888294,
+30654089,
+-14477422,
+15978753,
+-28526295,
+13106406,
+28526295,
+-12307942,
+15588057,
+-26381456,
+11310242,
+26381456,
+-10121083,
+16777933,
+-32908402,
+16775183,
+32908402,
+-16775900,
+17493802,
+-31619287,
+14744943,
+31619287,
+-15461529,
+18212414,
+-30325234,
+12706927,
+30325234,
+-14142124,
+18982725,
+-28938081,
+10522286,
+28938081,
+-12727795,
+16779330,
+-32908977,
+16774372,
+32908977,
+-16776486,
+18928041,
+-32181280,
+13883707,
+32181280,
+-16034532,
+21163118,
+-31424334,
+10876855,
+31424334,
+-15262757,
+23650871,
+-30581814,
+7530076,
+30581814,
+-14403731,
+16781484,
+-32909296,
+16772543,
+32909296,
+-16776811,
+21161996,
+-32501674,
+11976424,
+32501674,
+-16361204,
+25812009,
+-32068975,
+6885234,
+32068975,
+-15920027,
+31103385,
+-31576594,
+1091831,
+31576594,
+-15418000,
+16785164,
+-32909473,
+16769043,
+32909473,
+-16776991,
+24988064,
+-32682139,
+8334356,
+32682139,
+-16545204,
+33795794,
+-32438043,
+-722252,
+32438043,
+-16296325,
+43946128,
+-32156738,
+-11159403,
+32156738,
+-16009510,
+16791687,
+-32909571,
+16762620,
+32909571,
+-16777091,
+31772521,
+-32783096,
+1652834,
+32783096,
+-16648139,
+47961229,
+-32646423,
+-14675225,
+32646423,
+-16508788,
+66751682,
+-32487785,
+-33627423,
+32487785,
+-16347043,
+16312500,
+-30141556,
+16312485,
+30141556,
+-15847769,
+547598,
+-1011354,
+547084,
+1011354,
+15682534,
+266448,
+-491849,
+265925,
+491849,
+16244843,
+166111,
+-306446,
+165584,
+306446,
+16445521,
+16516262,
+-30518049,
+16516236,
+30518049,
+-16255282,
+962487,
+-1776938,
+960857,
+1776938,
+14853872,
+474742,
+-875656,
+473062,
+875656,
+15829413,
+297520,
+-548176,
+295821,
+548176,
+16183875,
+16631492,
+-30730944,
+16631443,
+30730944,
+-16485719,
+1660146,
+-3062870,
+1655081,
+3062870,
+13461989,
+838172,
+-1543806,
+832831,
+1543806,
+15106213,
+530135,
+-974532,
+524691,
+974532,
+15722390,
+16696110,
+-30850307,
+16696022,
+30850307,
+-16614916,
+2776642,
+-5116472,
+2761387,
+5116472,
+11239187,
+1456845,
+-2676477,
+1440152,
+2676477,
+13880219,
+936151,
+-1713835,
+918891,
+1713835,
+14922174,
+16732191,
+-30916910,
+16732031,
+30916910,
+-16687006,
+4430219,
+-8145523,
+4386431,
+8145523,
+7960566,
+2467715,
+-4512857,
+2416966,
+4512857,
+11892535,
+1628113,
+-2958725,
+1574387,
+2958725,
+13574716,
+16752314,
+-30953973,
+16752025,
+30953973,
+-16727123,
+6622193,
+-12127616,
+6504644,
+12127616,
+3650379,
+4016541,
+-7285135,
+3868831,
+7285135,
+8891843,
+2762675,
+-4954883,
+2600451,
+4954883,
+11414089,
+16763575,
+-30974568,
+16763055,
+30974568,
+-16749415,
+9150431,
+-16639142,
+8859646,
+16639142,
+-1232861,
+6182181,
+-11049974,
+5778225,
+11049974,
+4816810,
+4518629,
+-7917532,
+4051247,
+7917532,
+8207341,
+16769973,
+-30986002,
+16769034,
+30986002,
+-16761791,
+11676269,
+-20964630,
+11015683,
+20964630,
+-5914736,
+8893418,
+-15489638,
+7872446,
+15489638,
+11352,
+7041383,
+-11845939,
+5780568,
+11845939,
+3955265,
+16773783,
+-30992347,
+16772092,
+30992347,
+-16768659,
+13953280,
+-24496534,
+12561577,
+24496534,
+-9737641,
+11970921,
+-19931025,
+9602265,
+19931025,
+-4795970,
+10413172,
+-16343421,
+7276820,
+16343421,
+-912775,
+16776368,
+-30995868,
+16773318,
+30995868,
+-16772470,
+16007790,
+-27021343,
+13239901,
+27021343,
+-12470475,
+15365527,
+-23700024,
+10287194,
+23700024,
+-8875505,
+14785947,
+-20702857,
+7622664,
+20702857,
+-5631395,
+16778650,
+-30997821,
+16773150,
+30997821,
+-16774583,
+18157056,
+-28659649,
+12863925,
+28659649,
+-14243764,
+19443806,
+-26476950,
+9214638,
+26476950,
+-11881228,
+20728681,
+-24297433,
+5570671,
+24297433,
+-9522136,
+16781445,
+-30998904,
+16771527,
+30998904,
+-16775756,
+20988060,
+-29656921,
+11112361,
+29656921,
+-15323204,
+25187743,
+-28317150,
+5462520,
+28317150,
+-13873047,
+29672124,
+-26886556,
+-570326,
+26886556,
+-12324582,
+16785752,
+-30999505,
+16767870,
+30999505,
+-16776406,
+25444300,
+-30240545,
+7287830,
+30240545,
+-15954914,
+34434980,
+-29452472,
+-2555854,
+29452472,
+-15101910,
+44441242,
+-28575379,
+-13511474,
+28575379,
+-14152552,
+16793112,
+-30999838,
+16760871,
+30999838,
+-16776767,
+33095506,
+-30574250,
+-2177,
+30574250,
+-16316113,
+50408034,
+-30122291,
+-17803902,
+30122291,
+-15826917,
+70153765,
+-29606811,
+-38107583,
+29606811,
+-15268966,
+16806158,
+-31000023,
+16748025,
+31000023,
+-16776967,
+46670155,
+-30762526,
+-13373037,
+30762526,
+-16519902,
+78789544,
+-30507092,
+-45768905,
+30507092,
+-16243423,
+115942747,
+-30211627,
+-83241918,
+30211627,
+-15923613,
+15872835,
+-22447559,
+15872807,
+22447559,
+-14968426,
+277754,
+-392434,
+277231,
+392434,
+16222231,
+133061,
+-187804,
+132533,
+187804,
+16511622,
+81763,
+-115256,
+81233,
+115256,
+16614220,
+16263303,
+-22999746,
+16263250,
+22999746,
+-15749337,
+494605,
+-698290,
+492927,
+698290,
+15789685,
+238776,
+-336475,
+237071,
+336475,
+16301369,
+147228,
+-207000,
+145514,
+207000,
+16484473,
+16488278,
+-23317877,
+16488181,
+23317877,
+-16199242,
+872378,
+-1229961,
+867049,
+1229961,
+15037788,
+426889,
+-599839,
+421411,
+599839,
+15928916,
+264840,
+-370629,
+259308,
+370629,
+16253068,
+16615785,
+-23498145,
+16615609,
+23498145,
+-16454179,
+1513757,
+-2129016,
+1497126,
+2129016,
+13766333,
+758261,
+-1060001,
+740806,
+1060001,
+15278149,
+475551,
+-659971,
+457789,
+659971,
+15843875,
+16687407,
+-23599332,
+16687089,
+23599332,
+-16597280,
+2557116,
+-3580647,
+2506684,
+3580647,
+11713416,
+1332007,
+-1845009,
+1277230,
+1845009,
+14167979,
+851272,
+-1163942,
+794791,
+1163942,
+15131154,
+16727486,
+-23655830,
+16726910,
+23655830,
+-16677180,
+4144749,
+-5758163,
+3998523,
+5758163,
+8633944,
+2297803,
+-3131069,
+2130198,
+3131069,
+12349216,
+1516025,
+-2019070,
+1339371,
+2019070,
+13921820,
+16749957,
+-23687282,
+16748918,
+23687282,
+-16721660,
+6342807,
+-8688774,
+5944975,
+8688774,
+4489434,
+3855722,
+-5104454,
+3363066,
+5104454,
+9558428,
+2678286,
+-3407564,
+2140738,
+3407564,
+11958192,
+16762736,
+-23704762,
+16760861,
+23704762,
+-16746380,
+9059948,
+-12106014,
+8060542,
+12106014,
+-343274,
+6231959,
+-7847669,
+4866322,
+7847669,
+5678936,
+4678573,
+-5508603,
+3111768,
+5508603,
+8986875,
+16770353,
+-23714468,
+16766970,
+23714468,
+-16760107,
+12100768,
+-15483427,
+9796104,
+15483427,
+-5119656,
+9659401,
+-11180047,
+6151573,
+11180047,
+966242,
+8066003,
+-8371376,
+3772911,
+8371376,
+4938302,
+16775520,
+-23719855,
+16769420,
+23719855,
+-16767725,
+15410647,
+-18317794,
+10494626,
+18317794,
+-9128056,
+14477439,
+-14624233,
+6204350,
+14624233,
+-3904573,
+13754127,
+-11761419,
+2879032,
+11761419,
+144058,
+16780083,
+-23722844,
+16769084,
+23722844,
+-16771951,
+19348947,
+-20387735,
+9483664,
+20387735,
+-12055395,
+21467038,
+-17637855,
+3476656,
+17637855,
+-8166478,
+23369301,
+-15168181,
+-1918253,
+15168181,
+-4673832,
+16785673,
+-23724501,
+16765839,
+23724501,
+-16774296,
+24868547,
+-21750945,
+5891934,
+21750945,
+-13983265,
+32392543,
+-19913847,
+-4230110,
+19913847,
+-11385217,
+39938641,
+-18071353,
+-14381888,
+18071353,
+-8779537,
+16794288,
+-23725421,
+16758525,
+23725421,
+-16775596,
+33739025,
+-22588636,
+-1793870,
+22588636,
+-15167940,
+50727371,
+-21448926,
+-20394010,
+21448926,
+-13556146,
+69082218,
+-20217540,
+-40490298,
+20217540,
+-11814703,
+16809008,
+-23725931,
+16744526,
+23725931,
+-16776318,
+49053594,
+-23081666,
+-16411189,
+23081666,
+-15865189,
+82824296,
+-22406908,
+-51136143,
+22406908,
+-14910937,
+121049915,
+-21643138,
+-90441895,
+21643138,
+-13830803,
+16835099,
+-23726214,
+16718835,
+23726214,
+-16776718,
+76261468,
+-23364505,
+-43219068,
+23364505,
+-16265184,
+140080603,
+-22976059,
+-107587549,
+22976059,
+-15715838,
+214348557,
+-22524014,
+-182494791,
+22524014,
+-15076550,
+15060971,
+0,
+15060916,
+0,
+-13344671,
+137715,
+0,
+137188,
+0,
+16502313,
+62494,
+0,
+61964,
+0,
+16652757,
+35499,
+0,
+34969,
+0,
+16706748,
+15779939,
+0,
+15779837,
+0,
+-14782560,
+247059,
+0,
+245356,
+0,
+16284801,
+112726,
+0,
+111009,
+0,
+16553481,
+64282,
+0,
+62560,
+0,
+16650375,
+16209124,
+0,
+16208934,
+0,
+-15640842,
+441483,
+0,
+436010,
+0,
+15899723,
+203401,
+0,
+197848,
+0,
+16375967,
+116794,
+0,
+111212,
+0,
+16549211,
+16457433,
+0,
+16457085,
+0,
+-16137302,
+783510,
+0,
+766083,
+0,
+15227623,
+367229,
+0,
+349349,
+0,
+16060638,
+213457,
+0,
+195409,
+0,
+16368349,
+16598556,
+0,
+16597923,
+0,
+-16419263,
+1374332,
+0,
+1319705,
+0,
+14083179,
+663683,
+0,
+606536,
+0,
+15506996,
+394077,
+0,
+335974,
+0,
+16047166,
+16678051,
+0,
+16676903,
+0,
+-16577738,
+2365010,
+0,
+2198183,
+0,
+12214023,
+1201479,
+0,
+1021183,
+0,
+14554554,
+739666,
+0,
+554025,
+0,
+15483525,
+16722789,
+0,
+16720714,
+0,
+-16666287,
+3953214,
+0,
+3464275,
+0,
+9359728,
+2180807,
+0,
+1624291,
+0,
+12972118,
+1423936,
+0,
+838564,
+0,
+14514716,
+16748282,
+0,
+16744535,
+0,
+-16715601,
+6353786,
+0,
+5003926,
+0,
+5419504,
+3973108,
+0,
+2314944,
+0,
+10489165,
+2837511,
+0,
+1032284,
+0,
+12907421,
+16763496,
+0,
+16756735,
+0,
+-16743015,
+9775978,
+0,
+6325602,
+0,
+675636,
+7269959,
+0,
+2584558,
+0,
+6922698,
+5878520,
+0,
+507384,
+0,
+10391313,
+16773826,
+0,
+16761629,
+0,
+-16758239,
+14526462,
+0,
+6429723,
+0,
+-4178968,
+13351086,
+0,
+1026117,
+0,
+2400012,
+12566846,
+0,
+-2579306,
+0,
+6789676,
+16782950,
+0,
+16760954,
+0,
+-16766688,
+21346996,
+0,
+3817102,
+0,
+-8386881,
+24548257,
+0,
+-5261828,
+0,
+-2509212,
+27136746,
+0,
+-12602908,
+0,
+2243378,
+16794129,
+0,
+16754463,
+0,
+-16771376,
+31942756,
+0,
+-3625011,
+0,
+-11540529,
+45048673,
+0,
+-21256423,
+0,
+-7015034,
+57646140,
+0,
+-38203817,
+0,
+-2665107,
+16811358,
+0,
+16739835,
+0,
+-16773977,
+49676415,
+0,
+-19243342,
+0,
+-13655857,
+82339984,
+0,
+-55005915,
+0,
+-10556853,
+118287496,
+0,
+-94363999,
+0,
+-7146281,
+16840799,
+0,
+16711837,
+0,
+-16775419,
+80691383,
+0,
+-48942961,
+0,
+-14971206,
+149858505,
+0,
+-120064524,
+0,
+-13016765,
+233520652,
+0,
+-206090695,
+0,
+-10652741,
+16892981,
+0,
+16660455,
+0,
+-16776220,
+136000868,
+0,
+-103472696,
+0,
+-15750956,
+271801469,
+0,
+-240442250,
+0,
+-14582003,
+446309601,
+0,
+-416452524,
+0,
+-13079862,
diff --git a/media/libeffects/testlibs/AudioShelvingFilter.cpp b/media/libeffects/testlibs/AudioShelvingFilter.cpp
new file mode 100644
index 0000000..b8650ba
--- /dev/null
+++ b/media/libeffects/testlibs/AudioShelvingFilter.cpp
@@ -0,0 +1,109 @@
+/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.cpp
+**
+** Copyright 2009, 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.
+*/
+
+#include "AudioShelvingFilter.h"
+#include "AudioCommon.h"
+#include "EffectsMath.h"
+
+#include <new>
+#include <assert.h>
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+// Format of the coefficient tables:
+// kCoefTable[freq][gain][coef]
+// freq  - cutoff frequency, in octaves below Nyquist,from -10 to -6 in low
+//         shelf, -2 to 0 in high shelf.
+// gain  - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel.
+// coef - 0: b0
+//        1: b1
+//        2: b2
+//        3: -a1
+//        4: -a2
+static const size_t kHiInDims[2] = {3, 15};
+static const audio_coef_t kHiCoefTable[3*15*5] = {
+#include "AudioHighShelfFilterCoef.inl"
+};
+static const size_t kLoInDims[2] = {5, 15};
+static const audio_coef_t kLoCoefTable[5*15*5] = {
+#include "AudioLowShelfFilterCoef.inl"
+};
+
+AudioCoefInterpolator AudioShelvingFilter::mHiCoefInterp(2, kHiInDims, 5, (const audio_coef_t*) kHiCoefTable);
+AudioCoefInterpolator AudioShelvingFilter::mLoCoefInterp(2, kLoInDims, 5, (const audio_coef_t*) kLoCoefTable);
+
+AudioShelvingFilter::AudioShelvingFilter(ShelfType type, int nChannels,
+                                         int sampleRate)
+        : mType(type),
+          mBiquad(nChannels, sampleRate)  {
+    configure(nChannels, sampleRate);
+}
+
+void AudioShelvingFilter::configure(int nChannels, int sampleRate) {
+    mNiquistFreq = sampleRate * 500;
+    mFrequencyFactor = ((1ull) << 42) / mNiquistFreq;
+    mBiquad.configure(nChannels, sampleRate);
+    setFrequency(mNominalFrequency);
+    commit(true);
+}
+
+void AudioShelvingFilter::reset() {
+    setGain(0);
+    setFrequency(mType == kLowShelf ? 0 : mNiquistFreq);
+    commit(true);
+}
+
+void AudioShelvingFilter::setFrequency(uint32_t millihertz) {
+    mNominalFrequency = millihertz;
+    if (UNLIKELY(millihertz > mNiquistFreq / 2)) {
+        millihertz = mNiquistFreq / 2;
+    }
+    uint32_t normFreq = static_cast<uint32_t>(
+            (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10);
+    uint32_t log2minFreq = (mType == kLowShelf ? (32-10) : (32-2));
+    if (LIKELY(normFreq > (1U << log2minFreq))) {
+        mFrequency = (Effects_log2(normFreq) - (log2minFreq << 15)) << (FREQ_PRECISION_BITS - 15);
+    } else {
+        mFrequency = 0;
+    }
+}
+
+void AudioShelvingFilter::setGain(int32_t millibel) {
+    mGain = millibel + 9600;
+}
+
+void AudioShelvingFilter::commit(bool immediate) {
+    audio_coef_t coefs[5];
+    int intCoord[2] = {
+        mFrequency >> FREQ_PRECISION_BITS,
+        mGain >> GAIN_PRECISION_BITS
+    };
+    uint32_t fracCoord[2] = {
+        mFrequency << (32 - FREQ_PRECISION_BITS),
+        static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS)
+    };
+    if (mType == kHighShelf) {
+        mHiCoefInterp.getCoef(intCoord, fracCoord, coefs);
+    } else {
+        mLoCoefInterp.getCoef(intCoord, fracCoord, coefs);
+    }
+    mBiquad.setCoefs(coefs, immediate);
+}
+
+}
diff --git a/media/libeffects/testlibs/AudioShelvingFilter.h b/media/libeffects/testlibs/AudioShelvingFilter.h
new file mode 100644
index 0000000..f72d793
--- /dev/null
+++ b/media/libeffects/testlibs/AudioShelvingFilter.h
@@ -0,0 +1,146 @@
+/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.h
+**
+** Copyright 2009, 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 AUDIO_SHELVING_FILTER_H
+#define AUDIO_SHELVING_FILTER_H
+
+#include "AudioBiquadFilter.h"
+#include "AudioCoefInterpolator.h"
+
+namespace android {
+
+// A shelving audio filter, with unity skirt gain, and controllable cutoff
+// frequency and gain.
+// This filter is able to suppress introduce discontinuities and other artifacts
+// in the output, even when changing parameters abruptly.
+// Parameters can be set to any value - this class will make sure to clip them
+// when they are out of supported range.
+//
+// Implementation notes:
+// This class uses an underlying biquad filter whose parameters are determined
+// using a linear interpolation from a coefficient table, using a
+// AudioCoefInterpolator.
+// All is left for this class to do is mapping between high-level parameters to
+// fractional indices into the coefficient table.
+class AudioShelvingFilter {
+public:
+    // Shelf type
+    enum ShelfType {
+        kLowShelf,
+        kHighShelf
+    };
+
+    // Constructor. Resets the filter (see reset()).
+    // type       Type of the filter (high shelf or low shelf).
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    AudioShelvingFilter(ShelfType type, int nChannels, int sampleRate);
+
+    // Reconfiguration of the filter. Changes input/output format, but does not
+    // alter current parameter values. Clears delay lines.
+    // nChannels  Number of input/output channels (interlaced).
+    // sampleRate The input/output sample rate, in Hz.
+    void configure(int nChannels, int sampleRate);
+
+    // Resets the filter parameters to the following values:
+    // frequency: 0
+    // gain: 0
+    // It also disables the filter. Does not clear the delay lines.
+    void reset();
+
+    // Clears delay lines. Does not alter parameter values.
+    void clear() { mBiquad.clear(); }
+
+    // Sets gain value. Actual change will only take place upon commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // millibel Gain value in millibel (1/100 of decibel).
+    void setGain(int32_t millibel);
+
+    // Gets the gain, in millibel, as set.
+    int32_t getGain() const { return mGain - 9600; }
+
+    // Sets cutoff frequency value. Actual change will only take place upon
+    // commit().
+    // This value will be remembered even if the filter is in disabled() state.
+    // millihertz Frequency value in mHz.
+    void setFrequency(uint32_t millihertz);
+
+    // Gets the frequency, in mHz, as set.
+    uint32_t getFrequency() const { return mNominalFrequency; }
+
+    // Applies all parameter changes done to this point in time.
+    // If the filter is disabled, the new parameters will take place when it is
+    // enabled again. Does not introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly (ignored if filter is
+    // disabled).
+   void commit(bool immediate = false);
+
+    // Process a buffer of input data. The input and output should contain
+    // frameCount * nChannels interlaced samples. Processing can be done
+    // in-place, by passing the same buffer as both arguments.
+    // in   Input buffer.
+    // out  Output buffer.
+   // frameCount   Number of frames to produce.
+   void process(const audio_sample_t in[], audio_sample_t out[],
+                 int frameCount) { mBiquad.process(in, out, frameCount); }
+
+    // Enables the filter, so it would start processing input. Does not
+    // introduce artifacts, unless immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void enable(bool immediate = false) { mBiquad.enable(immediate); }
+
+    // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+    // immediate is set.
+    // immediate    Whether to apply change abruptly.
+    void disable(bool immediate = false) { mBiquad.disable(immediate); }
+
+private:
+    // Precision for the mFrequency member.
+    static const int FREQ_PRECISION_BITS = 26;
+    // Precision for the mGain member.
+    static const int GAIN_PRECISION_BITS = 10;
+
+    // Shelf type.
+    ShelfType mType;
+    // Nyquist, in mHz.
+    uint32_t mNiquistFreq;
+    // Fractional index into the gain dimension of the coef table in
+    // GAIN_PRECISION_BITS precision.
+    int32_t mGain;
+    // Fractional index into the frequency dimension of the coef table in
+    // FREQ_PRECISION_BITS precision.
+    uint32_t mFrequency;
+    // Nominal value of frequency, as set.
+    uint32_t mNominalFrequency;
+   // 1/Nyquist[mHz], in 42-bit precision (very small).
+    // Used for scaling the frequency.
+    uint32_t mFrequencyFactor;
+
+    // A biquad filter, used for the actual processing.
+    AudioBiquadFilter mBiquad;
+    // A coefficient interpolator, used for mapping the high level parameters to
+    // the low-level biquad coefficients. This one is used for the high shelf.
+    static AudioCoefInterpolator mHiCoefInterp;
+    // A coefficient interpolator, used for mapping the high level parameters to
+    // the low-level biquad coefficients. This one is used for the low shelf.
+    static AudioCoefInterpolator mLoCoefInterp;
+};
+
+}
+
+
+#endif // AUDIO_SHELVING_FILTER_H
diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp
new file mode 100644
index 0000000..f8e4357
--- /dev/null
+++ b/media/libeffects/testlibs/EffectEqualizer.cpp
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2009 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_TAG "Equalizer"
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+//
+#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include "AudioEqualizer.h"
+#include "AudioBiquadFilter.h"
+#include "AudioFormatAdapter.h"
+#include <media/EffectEqualizerApi.h>
+
+// effect_interface_t interface implementation for equalizer effect
+extern "C" const struct effect_interface_s gEqualizerInterface;
+
+enum equalizer_state_e {
+    EQUALIZER_STATE_UNINITIALIZED,
+    EQUALIZER_STATE_INITIALIZED,
+    EQUALIZER_STATE_ACTIVE,
+};
+
+namespace android {
+namespace {
+
+// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
+const effect_descriptor_t gEqualizerDescriptor = {
+        {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+        {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+        EFFECT_API_VERSION,
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
+        0, // TODO
+        1,
+        "Graphic Equalizer",
+        "Google Inc.",
+};
+
+/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
+const int kNumBands = 5;
+const uint32_t gFreqs[kNumBands] =      { 50000, 125000, 900000, 3200000, 6300000 };
+const uint32_t gBandwidths[kNumBands] = { 0,     3600,   3600,   2400,    0       };
+
+const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
+    { 300,  gFreqs[0], gBandwidths[0] },
+    { 400,  gFreqs[1], gBandwidths[1] },
+    { 0,    gFreqs[2], gBandwidths[2] },
+    { 200,  gFreqs[3], gBandwidths[3] },
+    { -300, gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
+    { -600, gFreqs[0], gBandwidths[0] },
+    { 200,  gFreqs[1], gBandwidths[1] },
+    { 400,  gFreqs[2], gBandwidths[2] },
+    { -400, gFreqs[3], gBandwidths[3] },
+    { -600, gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
+    { 400,  gFreqs[0], gBandwidths[0] },
+    { -400, gFreqs[1], gBandwidths[1] },
+    { 300,  gFreqs[2], gBandwidths[2] },
+    { -400, gFreqs[3], gBandwidths[3] },
+    { 600,  gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
+    { 700,  gFreqs[0], gBandwidths[0] },
+    { 400,  gFreqs[1], gBandwidths[1] },
+    { -400, gFreqs[2], gBandwidths[2] },
+    { 400,  gFreqs[3], gBandwidths[3] },
+    { 200,  gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::PresetConfig gEqualizerPresets[] = {
+    { "Classic", gBandsClassic },
+    { "Jazz",    gBandsJazz    },
+    { "Pop",     gBandsPop     },
+    { "Rock",    gBandsRock    }
+};
+
+/////////////////// END EQ PRESETS /////////////////////////////////////////////
+
+static const size_t kBufferSize = 32;
+
+typedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
+
+struct EqualizerContext {
+    const struct effect_interface_s *itfe;
+    effect_config_t config;
+    FormatAdapter adapter;
+    AudioEqualizer * pEqualizer;
+    uint32_t state;
+};
+
+//--- local function prototypes
+
+int Equalizer_init(EqualizerContext *pContext);
+int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig);
+int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue);
+int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
+
+
+//
+//--- Effect Library Interface Implementation
+//
+
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
+    *pNumEffects = 1;
+    return 0;
+} /* end EffectQueryNumberEffects */
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+    if (pDescriptor == NULL) {
+        return -EINVAL;
+    }
+    if (index > 0) {
+        return -EINVAL;
+    }
+    memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
+    return 0;
+} /* end EffectQueryNext */
+
+extern "C" int EffectCreate(effect_uuid_t *uuid,
+        int32_t sessionId,
+        int32_t ioId,
+        effect_interface_t *pInterface) {
+    int ret;
+    int i;
+
+    LOGV("EffectLibCreateEffect start");
+
+    if (pInterface == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+
+    if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
+        return -EINVAL;
+    }
+
+    EqualizerContext *pContext = new EqualizerContext;
+
+    pContext->itfe = &gEqualizerInterface;
+    pContext->pEqualizer = NULL;
+    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
+
+    ret = Equalizer_init(pContext);
+    if (ret < 0) {
+        LOGW("EffectLibCreateEffect() init failed");
+        delete pContext;
+        return ret;
+    }
+
+    *pInterface = (effect_interface_t)pContext;
+    pContext->state = EQUALIZER_STATE_INITIALIZED;
+
+    LOGV("EffectLibCreateEffect %p, size %d", pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
+
+    return 0;
+
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_interface_t interface) {
+    EqualizerContext * pContext = (EqualizerContext *)interface;
+
+    LOGV("EffectLibReleaseEffect %p", interface);
+    if (pContext == NULL) {
+        return -EINVAL;
+    }
+
+    pContext->state = EQUALIZER_STATE_UNINITIALIZED;
+    pContext->pEqualizer->free();
+    delete pContext;
+
+    return 0;
+} /* end EffectRelease */
+
+
+//
+//--- local functions
+//
+
+#define CHECK_ARG(cond) {                     \
+    if (!(cond)) {                            \
+        LOGV("Invalid argument: "#cond);      \
+        return -EINVAL;                       \
+    }                                         \
+}
+
+//----------------------------------------------------------------------------
+// Equalizer_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+//  pContext:   effect engine context
+//  pConfig:    pointer to effect_config_t structure holding input and output
+//      configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig)
+{
+    LOGV("Equalizer_configure start");
+
+    CHECK_ARG(pContext != NULL);
+    CHECK_ARG(pConfig != NULL);
+
+    CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
+    CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
+    CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+    CHECK_ARG((pConfig->inputCfg.channels == CHANNEL_MONO) || (pConfig->inputCfg.channels == CHANNEL_STEREO));
+    CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+              || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+    CHECK_ARG(pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S7_24
+              || pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S15);
+
+    int channelCount;
+    if (pConfig->inputCfg.channels == CHANNEL_MONO) {
+        channelCount = 1;
+    } else {
+        channelCount = 2;
+    }
+    CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
+
+    memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
+
+    pContext->pEqualizer->configure(channelCount,
+                          pConfig->inputCfg.samplingRate);
+
+    pContext->adapter.configure(*pContext->pEqualizer, channelCount,
+                        pConfig->inputCfg.format,
+                        pConfig->outputCfg.accessMode);
+
+    return 0;
+}   // end Equalizer_configure
+
+
+//----------------------------------------------------------------------------
+// Equalizer_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration and creates
+//     AudioEqualizer instance.
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_init(EqualizerContext *pContext)
+{
+    int status;
+
+    LOGV("Equalizer_init start");
+
+    CHECK_ARG(pContext != NULL);
+
+    if (pContext->pEqualizer != NULL) {
+        pContext->pEqualizer->free();
+    }
+
+    pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+    pContext->config.inputCfg.channels = CHANNEL_STEREO;
+    pContext->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+    pContext->config.inputCfg.samplingRate = 44100;
+    pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
+    pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+    pContext->config.inputCfg.bufferProvider.cookie = NULL;
+    pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+    pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+    pContext->config.outputCfg.channels = CHANNEL_STEREO;
+    pContext->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+    pContext->config.outputCfg.samplingRate = 44100;
+    pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
+    pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+    pContext->config.outputCfg.bufferProvider.cookie = NULL;
+    pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+    pContext->pEqualizer = AudioEqualizer::CreateInstance(
+        NULL,
+        kNumBands,
+        AudioBiquadFilter::MAX_CHANNELS,
+        44100,
+        gEqualizerPresets,
+        ARRAY_SIZE(gEqualizerPresets));
+
+    for (int i = 0; i < kNumBands; ++i) {
+        pContext->pEqualizer->setFrequency(i, gFreqs[i]);
+        pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
+    }
+
+    pContext->pEqualizer->enable(true);
+
+    Equalizer_configure(pContext, &pContext->config);
+
+    return 0;
+}   // end Equalizer_init
+
+
+//----------------------------------------------------------------------------
+// Equalizer_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Equalizer parameter
+//
+// Inputs:
+//  pEqualizer       - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to variable to hold retrieved value
+//  pValueSize       - pointer to value size: maximum size as input
+//
+// Outputs:
+//  *pValue updated with parameter value
+//  *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue)
+{
+    int status = 0;
+    int32_t param = *pParam++;
+    int32_t param2;
+    char *name;
+
+    switch (param) {
+    case EQ_PARAM_NUM_BANDS:
+    case EQ_PARAM_CUR_PRESET:
+    case EQ_PARAM_GET_NUM_OF_PRESETS:
+    case EQ_PARAM_BAND_LEVEL:
+    case EQ_PARAM_GET_BAND:
+        if (*pValueSize < sizeof(int16_t)) {
+            return -EINVAL;
+        }
+        *pValueSize = sizeof(int16_t);
+        break;
+
+    case EQ_PARAM_LEVEL_RANGE:
+        if (*pValueSize < 2 * sizeof(int16_t)) {
+            return -EINVAL;
+        }
+        *pValueSize = 2 * sizeof(int16_t);
+        break;
+
+    case EQ_PARAM_BAND_FREQ_RANGE:
+        if (*pValueSize < 2 * sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        *pValueSize = 2 * sizeof(int32_t);
+        break;
+
+    case EQ_PARAM_CENTER_FREQ:
+        if (*pValueSize < sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        *pValueSize = sizeof(int32_t);
+        break;
+
+    case EQ_PARAM_GET_PRESET_NAME:
+        break;
+
+    case EQ_PARAM_PROPERTIES:
+        if (*pValueSize < (2 + kNumBands) * sizeof(uint16_t)) {
+            return -EINVAL;
+        }
+        *pValueSize = (2 + kNumBands) * sizeof(uint16_t);
+        break;
+
+    default:
+        return -EINVAL;
+    }
+
+    switch (param) {
+    case EQ_PARAM_NUM_BANDS:
+        *(uint16_t *)pValue = (uint16_t)kNumBands;
+        LOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
+        break;
+
+    case EQ_PARAM_LEVEL_RANGE:
+        *(int16_t *)pValue = -9600;
+        *((int16_t *)pValue + 1) = 4800;
+        LOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d", *(int32_t *)pValue, *((int32_t *)pValue + 1));
+        break;
+
+    case EQ_PARAM_BAND_LEVEL:
+        param2 = *pParam;
+        if (param2 >= kNumBands) {
+            status = -EINVAL;
+            break;
+        }
+        *(int16_t *)pValue = (int16_t)pEqualizer->getGain(param2);
+        LOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_CENTER_FREQ:
+        param2 = *pParam;
+        if (param2 >= kNumBands) {
+            status = -EINVAL;
+            break;
+        }
+        *(int32_t *)pValue = pEqualizer->getFrequency(param2);
+        LOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d", param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_BAND_FREQ_RANGE:
+        param2 = *pParam;
+        if (param2 >= kNumBands) {
+            status = -EINVAL;
+            break;
+        }
+        pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
+        LOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d", param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
+        break;
+
+    case EQ_PARAM_GET_BAND:
+        param2 = *pParam;
+        *(uint16_t *)pValue = (uint16_t)pEqualizer->getMostRelevantBand(param2);
+        LOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d", param2, *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_CUR_PRESET:
+        *(uint16_t *)pValue = (uint16_t)pEqualizer->getPreset();
+        LOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
+        break;
+
+    case EQ_PARAM_GET_NUM_OF_PRESETS:
+        *(uint16_t *)pValue = (uint16_t)pEqualizer->getNumPresets();
+        LOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
+        break;
+
+    case EQ_PARAM_GET_PRESET_NAME:
+        param2 = *pParam;
+        if (param2 >= pEqualizer->getNumPresets()) {
+            status = -EINVAL;
+            break;
+        }
+        name = (char *)pValue;
+        strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
+        name[*pValueSize - 1] = 0;
+        *pValueSize = strlen(name) + 1;
+        LOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d", param2, gEqualizerPresets[param2].name, *pValueSize);
+        break;
+
+    case EQ_PARAM_PROPERTIES: {
+        int16_t *p = (int16_t *)pValue;
+        LOGV("Equalizer_getParameter() EQ_PARAM_PROPERTIES");
+        p[0] = (int16_t)pEqualizer->getPreset();
+        p[1] = (int16_t)kNumBands;
+        for (int i = 0; i < kNumBands; i++) {
+            p[2 + i] = (int16_t)pEqualizer->getGain(i);
+        }
+    } break;
+
+    default:
+        LOGV("Equalizer_getParameter() invalid param %d", param);
+        status = -EINVAL;
+        break;
+    }
+
+    return status;
+} // end Equalizer_getParameter
+
+
+//----------------------------------------------------------------------------
+// Equalizer_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Equalizer parameter
+//
+// Inputs:
+//  pEqualizer       - handle to instance data
+//  pParam           - pointer to parameter
+//  pValue           - pointer to value
+//
+// Outputs:
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
+{
+    int status = 0;
+    int32_t preset;
+    int32_t band;
+    int32_t level;
+    int32_t param = *pParam++;
+
+
+    switch (param) {
+    case EQ_PARAM_CUR_PRESET:
+        preset = (int32_t)(*(uint16_t *)pValue);
+
+        LOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
+        if (preset < 0 || preset >= pEqualizer->getNumPresets()) {
+            status = -EINVAL;
+            break;
+        }
+        pEqualizer->setPreset(preset);
+        pEqualizer->commit(true);
+        break;
+    case EQ_PARAM_BAND_LEVEL:
+        band =  *pParam;
+        level = (int32_t)(*(int16_t *)pValue);
+        LOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
+        if (band >= kNumBands) {
+            status = -EINVAL;
+            break;
+        }
+        pEqualizer->setGain(band, level);
+        pEqualizer->commit(true);
+       break;
+    case EQ_PARAM_PROPERTIES: {
+        LOGV("setParameter() EQ_PARAM_PROPERTIES");
+        int16_t *p = (int16_t *)pValue;
+        if ((int)p[0] >= pEqualizer->getNumPresets()) {
+            status = -EINVAL;
+            break;
+        }
+        if (p[0] >= 0) {
+            pEqualizer->setPreset((int)p[0]);
+        } else {
+            if ((int)p[1] != kNumBands) {
+                status = -EINVAL;
+                break;
+            }
+            for (int i = 0; i < kNumBands; i++) {
+                pEqualizer->setGain(i, (int32_t)p[2 + i]);
+            }
+        }
+        pEqualizer->commit(true);
+    } break;
+    default:
+        LOGV("setParameter() invalid param %d", param);
+        status = -EINVAL;
+        break;
+    }
+
+    return status;
+} // end Equalizer_setParameter
+
+} // namespace
+} // namespace
+
+
+//
+//--- Effect Control Interface Implementation
+//
+
+extern "C" int Equalizer_process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
+
+    if (pContext == NULL) {
+        return -EINVAL;
+    }
+    if (inBuffer == NULL || inBuffer->raw == NULL ||
+        outBuffer == NULL || outBuffer->raw == NULL ||
+        inBuffer->frameCount != outBuffer->frameCount) {
+        return -EINVAL;
+    }
+
+    if (pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+    if (pContext->state == EQUALIZER_STATE_INITIALIZED) {
+        return -ENODATA;
+    }
+
+    pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
+
+    return 0;
+}   // end Equalizer_process
+
+extern "C" int Equalizer_command(effect_interface_t self, uint32_t cmdCode, uint32_t cmdSize,
+        void *pCmdData, uint32_t *replySize, void *pReplyData) {
+
+    android::EqualizerContext * pContext = (android::EqualizerContext *) self;
+    int retsize;
+
+    if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+
+    android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
+
+    LOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
+
+    switch (cmdCode) {
+    case EFFECT_CMD_INIT:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Equalizer_init(pContext);
+        break;
+    case EFFECT_CMD_CONFIGURE:
+        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+                || pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Equalizer_configure(pContext,
+                (effect_config_t *) pCmdData);
+        break;
+    case EFFECT_CMD_RESET:
+        Equalizer_configure(pContext, &pContext->config);
+        break;
+    case EFFECT_CMD_GET_PARAM: {
+        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+            pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
+            return -EINVAL;
+        }
+        effect_param_t *p = (effect_param_t *)pCmdData;
+        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+        p = (effect_param_t *)pReplyData;
+        int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+        p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
+                p->data + voffset);
+        *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+        LOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
+                *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
+                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
+                *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
+
+        } break;
+    case EFFECT_CMD_SET_PARAM: {
+        LOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
+        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+            pReplyData == NULL || *replySize != sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        effect_param_t *p = (effect_param_t *) pCmdData;
+        *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
+                p->data + p->psize);
+        } break;
+    case EFFECT_CMD_ENABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pContext->state != EQUALIZER_STATE_INITIALIZED) {
+            return -ENOSYS;
+        }
+        pContext->state = EQUALIZER_STATE_ACTIVE;
+        LOGV("EFFECT_CMD_ENABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
+    case EFFECT_CMD_DISABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pContext->state != EQUALIZER_STATE_ACTIVE) {
+            return -ENOSYS;
+        }
+        pContext->state = EQUALIZER_STATE_INITIALIZED;
+        LOGV("EFFECT_CMD_DISABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
+    case EFFECT_CMD_SET_DEVICE:
+    case EFFECT_CMD_SET_VOLUME:
+    case EFFECT_CMD_SET_AUDIO_MODE:
+        break;
+    default:
+        LOGW("Equalizer_command invalid command %d",cmdCode);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+// effect_interface_t interface implementation for equalizer effect
+const struct effect_interface_s gEqualizerInterface = {
+        Equalizer_process,
+        Equalizer_command
+};
+
+
diff --git a/media/libeffects/testlibs/EffectReverb.c b/media/libeffects/testlibs/EffectReverb.c
new file mode 100644
index 0000000..3eb8b2c
--- /dev/null
+++ b/media/libeffects/testlibs/EffectReverb.c
@@ -0,0 +1,2135 @@
+/*
+ * Copyright (C) 2008 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_TAG "EffectReverb"
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "EffectReverb.h"
+#include "EffectsMath.h"
+
+// effect_interface_t interface implementation for reverb effect
+const struct effect_interface_s gReverbInterface = {
+        Reverb_Process,
+        Reverb_Command
+};
+
+// Google auxiliary environmental reverb UUID: 1f0ae2e0-4ef7-11df-bc09-0002a5d5c51b
+static const effect_descriptor_t gAuxEnvReverbDescriptor = {
+        {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+        {0x1f0ae2e0, 0x4ef7, 0x11df, 0xbc09, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        // flags other than EFFECT_FLAG_TYPE_AUXILIARY set for test purpose
+        EFFECT_FLAG_TYPE_AUXILIARY | EFFECT_FLAG_DEVICE_IND | EFFECT_FLAG_AUDIO_MODE_IND,
+        0, // TODO
+        33,
+        "Aux Environmental Reverb",
+        "Google Inc."
+};
+
+// Google insert environmental reverb UUID: aa476040-6342-11df-91a4-0002a5d5c51b
+static const effect_descriptor_t gInsertEnvReverbDescriptor = {
+        {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+        {0xaa476040, 0x6342, 0x11df, 0x91a4, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+        0, // TODO
+        33,
+        "Insert Environmental reverb",
+        "Google Inc."
+};
+
+// Google auxiliary preset reverb UUID: 63909320-53a6-11df-bdbd-0002a5d5c51b
+static const effect_descriptor_t gAuxPresetReverbDescriptor = {
+        {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        {0x63909320, 0x53a6, 0x11df, 0xbdbd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_AUXILIARY,
+        0, // TODO
+        33,
+        "Aux Preset Reverb",
+        "Google Inc."
+};
+
+// Google insert preset reverb UUID: d93dc6a0-6342-11df-b128-0002a5d5c51b
+static const effect_descriptor_t gInsertPresetReverbDescriptor = {
+        {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        {0xd93dc6a0, 0x6342, 0x11df, 0xb128, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+        EFFECT_API_VERSION,
+        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+        0, // TODO
+        33,
+        "Insert Preset Reverb",
+        "Google Inc."
+};
+
+// gDescriptors contains pointers to all defined effect descriptor in this library
+static const effect_descriptor_t * const gDescriptors[] = {
+        &gAuxEnvReverbDescriptor,
+        &gInsertEnvReverbDescriptor,
+        &gAuxPresetReverbDescriptor,
+        &gInsertPresetReverbDescriptor
+};
+
+/*----------------------------------------------------------------------------
+ * Effect API implementation
+ *--------------------------------------------------------------------------*/
+
+/*--- Effect Library Interface Implementation ---*/
+
+int EffectQueryNumberEffects(uint32_t *pNumEffects) {
+    *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+    return 0;
+}
+
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+    if (pDescriptor == NULL) {
+        return -EINVAL;
+    }
+    if (index >= sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)) {
+        return -EINVAL;
+    }
+    memcpy(pDescriptor, gDescriptors[index],
+            sizeof(effect_descriptor_t));
+    return 0;
+}
+
+int EffectCreate(effect_uuid_t *uuid,
+        int32_t sessionId,
+        int32_t ioId,
+        effect_interface_t *pInterface) {
+    int ret;
+    int i;
+    reverb_module_t *module;
+    const effect_descriptor_t *desc;
+    int aux = 0;
+    int preset = 0;
+
+    LOGV("EffectLibCreateEffect start");
+
+    if (pInterface == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+
+    for (i = 0; gDescriptors[i] != NULL; i++) {
+        desc = gDescriptors[i];
+        if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
+                == 0) {
+            break;
+        }
+    }
+
+    if (gDescriptors[i] == NULL) {
+        return -ENOENT;
+    }
+
+    module = malloc(sizeof(reverb_module_t));
+
+    module->itfe = &gReverbInterface;
+
+    module->context.mState = REVERB_STATE_UNINITIALIZED;
+
+    if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
+        preset = 1;
+    }
+    if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+        aux = 1;
+    }
+    ret = Reverb_Init(module, aux, preset);
+    if (ret < 0) {
+        LOGW("EffectLibCreateEffect() init failed");
+        free(module);
+        return ret;
+    }
+
+    *pInterface = (effect_interface_t) module;
+
+    module->context.mState = REVERB_STATE_INITIALIZED;
+
+    LOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));
+
+    return 0;
+}
+
+int EffectRelease(effect_interface_t interface) {
+    reverb_module_t *pRvbModule = (reverb_module_t *)interface;
+
+    LOGV("EffectLibReleaseEffect %p", interface);
+    if (interface == NULL) {
+        return -EINVAL;
+    }
+
+    pRvbModule->context.mState = REVERB_STATE_UNINITIALIZED;
+
+    free(pRvbModule);
+    return 0;
+}
+
+
+/*--- Effect Control Interface Implementation ---*/
+
+static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+    reverb_object_t *pReverb;
+    int16_t *pSrc, *pDst;
+    reverb_module_t *pRvbModule = (reverb_module_t *)self;
+
+    if (pRvbModule == NULL) {
+        return -EINVAL;
+    }
+
+    if (inBuffer == NULL || inBuffer->raw == NULL ||
+        outBuffer == NULL || outBuffer->raw == NULL ||
+        inBuffer->frameCount != outBuffer->frameCount) {
+        return -EINVAL;
+    }
+
+    pReverb = (reverb_object_t*) &pRvbModule->context;
+
+    if (pReverb->mState == REVERB_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+    if (pReverb->mState == REVERB_STATE_INITIALIZED) {
+        return -ENODATA;
+    }
+
+    //if bypassed or the preset forces the signal to be completely dry
+    if (pReverb->m_bBypass != 0) {
+        if (inBuffer->raw != outBuffer->raw) {
+            int16_t smp;
+            pSrc = inBuffer->s16;
+            pDst = outBuffer->s16;
+            size_t count = inBuffer->frameCount;
+            if (pRvbModule->config.inputCfg.channels == pRvbModule->config.outputCfg.channels) {
+                count *= 2;
+                while (count--) {
+                    *pDst++ = *pSrc++;
+                }
+            } else {
+                while (count--) {
+                    smp = *pSrc++;
+                    *pDst++ = smp;
+                    *pDst++ = smp;
+                }
+            }
+        }
+        return 0;
+    }
+
+    if (pReverb->m_nNextRoom != pReverb->m_nCurrentRoom) {
+        ReverbUpdateRoom(pReverb, true);
+    }
+
+    pSrc = inBuffer->s16;
+    pDst = outBuffer->s16;
+    size_t numSamples = outBuffer->frameCount;
+    while (numSamples) {
+        uint32_t processedSamples;
+        if (numSamples > (uint32_t) pReverb->m_nUpdatePeriodInSamples) {
+            processedSamples = (uint32_t) pReverb->m_nUpdatePeriodInSamples;
+        } else {
+            processedSamples = numSamples;
+        }
+
+        /* increment update counter */
+        pReverb->m_nUpdateCounter += (int16_t) processedSamples;
+        /* check if update counter needs to be reset */
+        if (pReverb->m_nUpdateCounter >= pReverb->m_nUpdatePeriodInSamples) {
+            /* update interval has elapsed, so reset counter */
+            pReverb->m_nUpdateCounter -= pReverb->m_nUpdatePeriodInSamples;
+            ReverbUpdateXfade(pReverb, pReverb->m_nUpdatePeriodInSamples);
+
+        } /* end if m_nUpdateCounter >= update interval */
+
+        Reverb(pReverb, processedSamples, pDst, pSrc);
+
+        numSamples -= processedSamples;
+        if (pReverb->m_Aux) {
+            pSrc += processedSamples;
+        } else {
+            pSrc += processedSamples * NUM_OUTPUT_CHANNELS;
+        }
+        pDst += processedSamples * NUM_OUTPUT_CHANNELS;
+    }
+
+    return 0;
+}
+
+
+static int Reverb_Command(effect_interface_t self, uint32_t cmdCode, uint32_t cmdSize,
+        void *pCmdData, uint32_t *replySize, void *pReplyData) {
+    reverb_module_t *pRvbModule = (reverb_module_t *) self;
+    reverb_object_t *pReverb;
+    int retsize;
+
+    if (pRvbModule == NULL ||
+            pRvbModule->context.mState == REVERB_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+
+    pReverb = (reverb_object_t*) &pRvbModule->context;
+
+    LOGV("Reverb_Command command %d cmdSize %d",cmdCode, cmdSize);
+
+    switch (cmdCode) {
+    case EFFECT_CMD_INIT:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Reverb_Init(pRvbModule, pReverb->m_Aux, pReverb->m_Preset);
+        if (*(int *) pReplyData == 0) {
+            pRvbModule->context.mState = REVERB_STATE_INITIALIZED;
+        }
+        break;
+    case EFFECT_CMD_CONFIGURE:
+        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+                || pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Reverb_Configure(pRvbModule,
+                (effect_config_t *)pCmdData, false);
+        break;
+    case EFFECT_CMD_RESET:
+        Reverb_Reset(pReverb, false);
+        break;
+    case EFFECT_CMD_GET_PARAM:
+        LOGV("Reverb_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p",pCmdData, *replySize, pReplyData);
+
+        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+            pReplyData == NULL || *replySize < (int) sizeof(effect_param_t)) {
+            return -EINVAL;
+        }
+        effect_param_t *rep = (effect_param_t *) pReplyData;
+        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
+        LOGV("Reverb_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",*(int32_t *)rep->data, rep->vsize);
+        rep->status = Reverb_getParameter(pReverb, *(int32_t *)rep->data, &rep->vsize,
+                rep->data + sizeof(int32_t));
+        *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize;
+        break;
+    case EFFECT_CMD_SET_PARAM:
+        LOGV("Reverb_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
+                cmdSize, pCmdData, *replySize, pReplyData);
+        if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
+                || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        effect_param_t *cmd = (effect_param_t *) pCmdData;
+        *(int *)pReplyData = Reverb_setParameter(pReverb, *(int32_t *)cmd->data,
+                cmd->vsize, cmd->data + sizeof(int32_t));
+        break;
+    case EFFECT_CMD_ENABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pReverb->mState != REVERB_STATE_INITIALIZED) {
+            return -ENOSYS;
+        }
+        pReverb->mState = REVERB_STATE_ACTIVE;
+        LOGV("EFFECT_CMD_ENABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
+    case EFFECT_CMD_DISABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pReverb->mState != REVERB_STATE_ACTIVE) {
+            return -ENOSYS;
+        }
+        pReverb->mState = REVERB_STATE_INITIALIZED;
+        LOGV("EFFECT_CMD_DISABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
+    case EFFECT_CMD_SET_DEVICE:
+        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+            return -EINVAL;
+        }
+        LOGV("Reverb_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData);
+        break;
+    case EFFECT_CMD_SET_VOLUME: {
+        // audio output is always stereo => 2 channel volumes
+        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t) * 2) {
+            return -EINVAL;
+        }
+        float left = (float)(*(uint32_t *)pCmdData) / (1 << 24);
+        float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24);
+        LOGV("Reverb_Command EFFECT_CMD_SET_VOLUME: left %f, right %f ", left, right);
+        break;
+        }
+    case EFFECT_CMD_SET_AUDIO_MODE:
+        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+            return -EINVAL;
+        }
+        LOGV("Reverb_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
+        break;
+    default:
+        LOGW("Reverb_Command invalid command %d",cmdCode);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Reverb internal functions
+ *--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Reverb_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initialize reverb context and apply default parameters
+ *
+ * Inputs:
+ *  pRvbModule    - pointer to reverb effect module
+ *  aux           - indicates if the reverb is used as auxiliary (1) or insert (0)
+ *  preset        - indicates if the reverb is used in preset (1) or environmental (0) mode
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset) {
+    int ret;
+
+    LOGV("Reverb_Init module %p, aux: %d, preset: %d", pRvbModule,aux, preset);
+
+    memset(&pRvbModule->context, 0, sizeof(reverb_object_t));
+
+    pRvbModule->context.m_Aux = (uint16_t)aux;
+    pRvbModule->context.m_Preset = (uint16_t)preset;
+
+    pRvbModule->config.inputCfg.samplingRate = 44100;
+    if (aux) {
+        pRvbModule->config.inputCfg.channels = CHANNEL_MONO;
+    } else {
+        pRvbModule->config.inputCfg.channels = CHANNEL_STEREO;
+    }
+    pRvbModule->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+    pRvbModule->config.inputCfg.bufferProvider.getBuffer = NULL;
+    pRvbModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+    pRvbModule->config.inputCfg.bufferProvider.cookie = NULL;
+    pRvbModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+    pRvbModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+    pRvbModule->config.outputCfg.samplingRate = 44100;
+    pRvbModule->config.outputCfg.channels = CHANNEL_STEREO;
+    pRvbModule->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+    pRvbModule->config.outputCfg.bufferProvider.getBuffer = NULL;
+    pRvbModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+    pRvbModule->config.outputCfg.bufferProvider.cookie = NULL;
+    pRvbModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+    pRvbModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+    ret = Reverb_Configure(pRvbModule, &pRvbModule->config, true);
+    if (ret < 0) {
+        LOGV("Reverb_Init error %d on module %p", ret, pRvbModule);
+    }
+
+    return ret;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *  Set input and output audio configuration.
+ *
+ * Inputs:
+ *  pRvbModule    - pointer to reverb effect module
+ *  pConfig       - pointer to effect_config_t structure containing input
+ *              and output audio parameters configuration
+ *  init          - true if called from init function
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig,
+        bool init) {
+    reverb_object_t *pReverb = &pRvbModule->context;
+    int bufferSizeInSamples;
+    int updatePeriodInSamples;
+    int xfadePeriodInSamples;
+
+    // Check configuration compatibility with build options
+    if (pConfig->inputCfg.samplingRate
+        != pConfig->outputCfg.samplingRate
+        || pConfig->outputCfg.channels != OUTPUT_CHANNELS
+        || pConfig->inputCfg.format != SAMPLE_FORMAT_PCM_S15
+        || pConfig->outputCfg.format != SAMPLE_FORMAT_PCM_S15) {
+        LOGV("Reverb_Configure invalid config");
+        return -EINVAL;
+    }
+    if ((pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_MONO)) ||
+        (!pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_STEREO))) {
+        LOGV("Reverb_Configure invalid config");
+        return -EINVAL;
+    }
+
+    memcpy(&pRvbModule->config, pConfig, sizeof(effect_config_t));
+
+    pReverb->m_nSamplingRate = pRvbModule->config.outputCfg.samplingRate;
+
+    switch (pReverb->m_nSamplingRate) {
+    case 8000:
+        pReverb->m_nUpdatePeriodInBits = 5;
+        bufferSizeInSamples = 4096;
+        pReverb->m_nCosWT_5KHz = -23170;
+        break;
+    case 16000:
+        pReverb->m_nUpdatePeriodInBits = 6;
+        bufferSizeInSamples = 8192;
+        pReverb->m_nCosWT_5KHz = -12540;
+        break;
+    case 22050:
+        pReverb->m_nUpdatePeriodInBits = 7;
+        bufferSizeInSamples = 8192;
+        pReverb->m_nCosWT_5KHz = 4768;
+        break;
+    case 32000:
+        pReverb->m_nUpdatePeriodInBits = 7;
+        bufferSizeInSamples = 16384;
+        pReverb->m_nCosWT_5KHz = 18205;
+        break;
+    case 44100:
+        pReverb->m_nUpdatePeriodInBits = 8;
+        bufferSizeInSamples = 16384;
+        pReverb->m_nCosWT_5KHz = 24799;
+        break;
+    case 48000:
+        pReverb->m_nUpdatePeriodInBits = 8;
+        bufferSizeInSamples = 16384;
+        pReverb->m_nCosWT_5KHz = 25997;
+        break;
+    default:
+        LOGV("Reverb_Configure invalid sampling rate %d", pReverb->m_nSamplingRate);
+        return -EINVAL;
+    }
+
+    // Define a mask for circular addressing, so that array index
+    // can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1)
+    // The buffer size MUST be a power of two
+    pReverb->m_nBufferMask = (int32_t) (bufferSizeInSamples - 1);
+    /* reverb parameters are updated every 2^(pReverb->m_nUpdatePeriodInBits) samples */
+    updatePeriodInSamples = (int32_t) (0x1L << pReverb->m_nUpdatePeriodInBits);
+    /*
+     calculate the update counter by bitwise ANDING with this value to
+     generate a 2^n modulo value
+     */
+    pReverb->m_nUpdatePeriodInSamples = (int32_t) updatePeriodInSamples;
+
+    xfadePeriodInSamples = (int32_t) (REVERB_XFADE_PERIOD_IN_SECONDS
+            * (double) pReverb->m_nSamplingRate);
+
+    // set xfade parameters
+    pReverb->m_nPhaseIncrement
+            = (int16_t) (65536 / ((int16_t) xfadePeriodInSamples
+                    / (int16_t) updatePeriodInSamples));
+
+    if (init) {
+        ReverbReadInPresets(pReverb);
+
+        // for debugging purposes, allow noise generator
+        pReverb->m_bUseNoise = true;
+
+        // for debugging purposes, allow bypass
+        pReverb->m_bBypass = 0;
+
+        pReverb->m_nNextRoom = 1;
+
+        pReverb->m_nNoise = (int16_t) 0xABCD;
+    }
+
+    Reverb_Reset(pReverb, init);
+
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *  Reset internal states and clear delay lines.
+ *
+ * Inputs:
+ *  pReverb    - pointer to reverb context
+ *  init       - true if called from init function
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void Reverb_Reset(reverb_object_t *pReverb, bool init) {
+    int bufferSizeInSamples = (int32_t) (pReverb->m_nBufferMask + 1);
+    int maxApSamples;
+    int maxDelaySamples;
+    int maxEarlySamples;
+    int ap1In;
+    int delay0In;
+    int delay1In;
+    int32_t i;
+    uint16_t nOffset;
+
+    maxApSamples = ((int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16);
+    maxDelaySamples = ((int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+            >> 16);
+    maxEarlySamples = ((int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+            >> 16);
+
+    ap1In = (AP0_IN + maxApSamples + GUARD);
+    delay0In = (ap1In + maxApSamples + GUARD);
+    delay1In = (delay0In + maxDelaySamples + GUARD);
+    // Define the max offsets for the end points of each section
+    // i.e., we don't expect a given section's taps to go beyond
+    // the following limits
+
+    pReverb->m_nEarly0in = (delay1In + maxDelaySamples + GUARD);
+    pReverb->m_nEarly1in = (pReverb->m_nEarly0in + maxEarlySamples + GUARD);
+
+    pReverb->m_sAp0.m_zApIn = AP0_IN;
+
+    pReverb->m_zD0In = delay0In;
+
+    pReverb->m_sAp1.m_zApIn = ap1In;
+
+    pReverb->m_zD1In = delay1In;
+
+    pReverb->m_zOutLpfL = 0;
+    pReverb->m_zOutLpfR = 0;
+
+    pReverb->m_nRevFbkR = 0;
+    pReverb->m_nRevFbkL = 0;
+
+    // set base index into circular buffer
+    pReverb->m_nBaseIndex = 0;
+
+    // clear the reverb delay line
+    for (i = 0; i < bufferSizeInSamples; i++) {
+        pReverb->m_nDelayLine[i] = 0;
+    }
+
+    ReverbUpdateRoom(pReverb, init);
+
+    pReverb->m_nUpdateCounter = 0;
+
+    pReverb->m_nPhase = -32768;
+
+    pReverb->m_nSin = 0;
+    pReverb->m_nCos = 0;
+    pReverb->m_nSinIncrement = 0;
+    pReverb->m_nCosIncrement = 0;
+
+    // set delay tap lengths
+    nOffset = ReverbCalculateNoise(pReverb);
+
+    pReverb->m_zD1Cross = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
+            + nOffset;
+
+    nOffset = ReverbCalculateNoise(pReverb);
+
+    pReverb->m_zD0Cross = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
+            - nOffset;
+
+    nOffset = ReverbCalculateNoise(pReverb);
+
+    pReverb->m_zD0Self = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
+            - nOffset;
+
+    nOffset = ReverbCalculateNoise(pReverb);
+
+    pReverb->m_zD1Self = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
+            + nOffset;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_getParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get a Reverb parameter
+ *
+ * Inputs:
+ *  pReverb       - handle to instance data
+ *  param         - parameter
+ *  pValue        - pointer to variable to hold retrieved value
+ *  pSize         - pointer to value size: maximum size as input
+ *
+ * Outputs:
+ *  *pValue updated with parameter value
+ *  *pSize updated with actual value size
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize,
+        void *pValue) {
+    int32_t *pValue32;
+    int16_t *pValue16;
+    t_reverb_settings *pProperties;
+    int32_t i;
+    int32_t temp;
+    int32_t temp2;
+    size_t size;
+
+    if (pReverb->m_Preset) {
+        if (param != REVERB_PARAM_PRESET || *pSize < sizeof(int16_t)) {
+            return -EINVAL;
+        }
+        size = sizeof(int16_t);
+        pValue16 = (int16_t *)pValue;
+        // REVERB_PRESET_NONE is mapped to bypass
+        if (pReverb->m_bBypass != 0) {
+            *pValue16 = (int16_t)REVERB_PRESET_NONE;
+        } else {
+            *pValue16 = (int16_t)(pReverb->m_nNextRoom + 1);
+        }
+        LOGV("get REVERB_PARAM_PRESET, preset %d", *pValue16);
+    } else {
+        switch (param) {
+        case REVERB_PARAM_ROOM_LEVEL:
+        case REVERB_PARAM_ROOM_HF_LEVEL:
+        case REVERB_PARAM_DECAY_HF_RATIO:
+        case REVERB_PARAM_REFLECTIONS_LEVEL:
+        case REVERB_PARAM_REVERB_LEVEL:
+        case REVERB_PARAM_DIFFUSION:
+        case REVERB_PARAM_DENSITY:
+            size = sizeof(int16_t);
+            break;
+
+        case REVERB_PARAM_BYPASS:
+        case REVERB_PARAM_DECAY_TIME:
+        case REVERB_PARAM_REFLECTIONS_DELAY:
+        case REVERB_PARAM_REVERB_DELAY:
+            size = sizeof(int32_t);
+            break;
+
+        case REVERB_PARAM_PROPERTIES:
+            size = sizeof(t_reverb_settings);
+            break;
+
+        default:
+            return -EINVAL;
+        }
+
+        if (*pSize < size) {
+            return -EINVAL;
+        }
+
+        pValue32 = (int32_t *) pValue;
+        pValue16 = (int16_t *) pValue;
+        pProperties = (t_reverb_settings *) pValue;
+
+        switch (param) {
+        case REVERB_PARAM_BYPASS:
+            *pValue32 = (int32_t) pReverb->m_bBypass;
+            break;
+
+        case REVERB_PARAM_PROPERTIES:
+            pValue16 = &pProperties->roomLevel;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_ROOM_LEVEL:
+            // Convert m_nRoomLpfFwd to millibels
+            temp = (pReverb->m_nRoomLpfFwd << 15)
+                    / (32767 - pReverb->m_nRoomLpfFbk);
+            *pValue16 = Effects_Linear16ToMillibels(temp);
+
+            LOGV("get REVERB_PARAM_ROOM_LEVEL %d, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", *pValue16, temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+
+            if (param == REVERB_PARAM_ROOM_LEVEL) {
+                break;
+            }
+            pValue16 = &pProperties->roomHFLevel;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_ROOM_HF_LEVEL:
+            // The ratio between linear gain at 0Hz and at 5000Hz for the room low pass is:
+            // (1 + a1) / sqrt(a1^2 + 2*C*a1 + 1) where:
+            // - a1 is minus the LP feedback gain: -pReverb->m_nRoomLpfFbk
+            // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz
+
+            temp = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFbk);
+            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 %d", temp);
+            temp2 = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nCosWT_5KHz)
+                    << 1;
+            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, 2 Cos a1 %d", temp2);
+            temp = 32767 + temp - temp2;
+            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 + 2 Cos a1 + 1 %d", temp);
+            temp = Effects_Sqrt(temp) * 181;
+            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, SQRT(a1^2 + 2 Cos a1 + 1) %d", temp);
+            temp = ((32767 - pReverb->m_nRoomLpfFbk) << 15) / temp;
+
+            LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+
+            *pValue16 = Effects_Linear16ToMillibels(temp);
+
+            if (param == REVERB_PARAM_ROOM_HF_LEVEL) {
+                break;
+            }
+            pValue32 = &pProperties->decayTime;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_DECAY_TIME:
+            // Calculate reverb feedback path gain
+            temp = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);
+            temp = Effects_Linear16ToMillibels(temp);
+
+            // Calculate decay time: g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time
+            temp = (-6000 * pReverb->m_nLateDelay) / temp;
+
+            // Convert samples to ms
+            *pValue32 = (temp * 1000) / pReverb->m_nSamplingRate;
+
+            LOGV("get REVERB_PARAM_DECAY_TIME, samples %d, ms %d", temp, *pValue32);
+
+            if (param == REVERB_PARAM_DECAY_TIME) {
+                break;
+            }
+            pValue16 = &pProperties->decayHFRatio;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_DECAY_HF_RATIO:
+            // If r is the decay HF ratio  (r = REVERB_PARAM_DECAY_HF_RATIO/1000) we have:
+            //       DT_5000Hz = DT_0Hz * r
+            //  and  G_5000Hz = -6000 * d / DT_5000Hz and G_0Hz = -6000 * d / DT_0Hz in millibels so :
+            // r = G_0Hz/G_5000Hz in millibels
+            // The linear gain at 5000Hz is b0 / sqrt(a1^2 + 2*C*a1 + 1) where:
+            // - a1 is minus the LP feedback gain: -pReverb->m_nRvbLpfFbk
+            // - b0 is the LP forward gain: pReverb->m_nRvbLpfFwd
+            // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz
+            if (pReverb->m_nRvbLpfFbk == 0) {
+                *pValue16 = 1000;
+                LOGV("get REVERB_PARAM_DECAY_HF_RATIO, pReverb->m_nRvbLpfFbk == 0, ratio %d", *pValue16);
+            } else {
+                temp = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFbk);
+                temp2 = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nCosWT_5KHz)
+                        << 1;
+                temp = 32767 + temp - temp2;
+                temp = Effects_Sqrt(temp) * 181;
+                temp = (pReverb->m_nRvbLpfFwd << 15) / temp;
+                // The linear gain at 0Hz is b0 / (a1 + 1)
+                temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767
+                        - pReverb->m_nRvbLpfFbk);
+
+                temp = Effects_Linear16ToMillibels(temp);
+                temp2 = Effects_Linear16ToMillibels(temp2);
+                LOGV("get REVERB_PARAM_DECAY_HF_RATIO, gain 5KHz %d mB, gain DC %d mB", temp, temp2);
+
+                if (temp == 0)
+                    temp = 1;
+                temp = (int16_t) ((1000 * temp2) / temp);
+                if (temp > 1000)
+                    temp = 1000;
+
+                *pValue16 = temp;
+                LOGV("get REVERB_PARAM_DECAY_HF_RATIO, ratio %d", *pValue16);
+            }
+
+            if (param == REVERB_PARAM_DECAY_HF_RATIO) {
+                break;
+            }
+            pValue16 = &pProperties->reflectionsLevel;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_REFLECTIONS_LEVEL:
+            *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nEarlyGain);
+
+            LOGV("get REVERB_PARAM_REFLECTIONS_LEVEL, %d", *pValue16);
+            if (param == REVERB_PARAM_REFLECTIONS_LEVEL) {
+                break;
+            }
+            pValue32 = &pProperties->reflectionsDelay;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_REFLECTIONS_DELAY:
+            // convert samples to ms
+            *pValue32 = (pReverb->m_nEarlyDelay * 1000) / pReverb->m_nSamplingRate;
+
+            LOGV("get REVERB_PARAM_REFLECTIONS_DELAY, samples %d, ms %d", pReverb->m_nEarlyDelay, *pValue32);
+
+            if (param == REVERB_PARAM_REFLECTIONS_DELAY) {
+                break;
+            }
+            pValue16 = &pProperties->reverbLevel;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_REVERB_LEVEL:
+            // Convert linear gain to millibels
+            *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nLateGain << 2);
+
+            LOGV("get REVERB_PARAM_REVERB_LEVEL %d", *pValue16);
+
+            if (param == REVERB_PARAM_REVERB_LEVEL) {
+                break;
+            }
+            pValue32 = &pProperties->reverbDelay;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_REVERB_DELAY:
+            // convert samples to ms
+            *pValue32 = (pReverb->m_nLateDelay * 1000) / pReverb->m_nSamplingRate;
+
+            LOGV("get REVERB_PARAM_REVERB_DELAY, samples %d, ms %d", pReverb->m_nLateDelay, *pValue32);
+
+            if (param == REVERB_PARAM_REVERB_DELAY) {
+                break;
+            }
+            pValue16 = &pProperties->diffusion;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_DIFFUSION:
+            temp = (int16_t) ((1000 * (pReverb->m_sAp0.m_nApGain - AP0_GAIN_BASE))
+                    / AP0_GAIN_RANGE);
+
+            if (temp < 0)
+                temp = 0;
+            if (temp > 1000)
+                temp = 1000;
+
+            *pValue16 = temp;
+            LOGV("get REVERB_PARAM_DIFFUSION, %d, AP0 gain %d", *pValue16, pReverb->m_sAp0.m_nApGain);
+
+            if (param == REVERB_PARAM_DIFFUSION) {
+                break;
+            }
+            pValue16 = &pProperties->density;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_DENSITY:
+            // Calculate AP delay in time units
+            temp = ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) << 16)
+                    / pReverb->m_nSamplingRate;
+
+            temp = (int16_t) ((1000 * (temp - AP0_TIME_BASE)) / AP0_TIME_RANGE);
+
+            if (temp < 0)
+                temp = 0;
+            if (temp > 1000)
+                temp = 1000;
+
+            *pValue16 = temp;
+
+            LOGV("get REVERB_PARAM_DENSITY, %d, AP0 delay smps %d", *pValue16, pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn);
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    *pSize = size;
+
+    LOGV("Reverb_getParameter, context %p, param %d, value %d",
+            pReverb, param, *(int *)pValue);
+
+    return 0;
+} /* end Reverb_getParameter */
+
+/*----------------------------------------------------------------------------
+ * Reverb_setParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set a Reverb parameter
+ *
+ * Inputs:
+ *  pReverb       - handle to instance data
+ *  param         - parameter
+ *  pValue        - pointer to parameter value
+ *  size          - value size
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size,
+        void *pValue) {
+    int32_t value32;
+    int16_t value16;
+    t_reverb_settings *pProperties;
+    int32_t i;
+    int32_t temp;
+    int32_t temp2;
+    reverb_preset_t *pPreset;
+    int maxSamples;
+    int32_t averageDelay;
+    size_t paramSize;
+
+    LOGV("Reverb_setParameter, context %p, param %d, value16 %d, value32 %d",
+            pReverb, param, *(int16_t *)pValue, *(int32_t *)pValue);
+
+    if (pReverb->m_Preset) {
+        if (param != REVERB_PARAM_PRESET || size != sizeof(int16_t)) {
+            return -EINVAL;
+        }
+        value16 = *(int16_t *)pValue;
+        LOGV("set REVERB_PARAM_PRESET, preset %d", value16);
+        if (value16 < REVERB_PRESET_NONE || value16 > REVERB_PRESET_PLATE) {
+            return -EINVAL;
+        }
+        // REVERB_PRESET_NONE is mapped to bypass
+        if (value16 == REVERB_PRESET_NONE) {
+            pReverb->m_bBypass = 1;
+        } else {
+            pReverb->m_bBypass = 0;
+            pReverb->m_nNextRoom = value16 - 1;
+        }
+    } else {
+        switch (param) {
+        case REVERB_PARAM_ROOM_LEVEL:
+        case REVERB_PARAM_ROOM_HF_LEVEL:
+        case REVERB_PARAM_DECAY_HF_RATIO:
+        case REVERB_PARAM_REFLECTIONS_LEVEL:
+        case REVERB_PARAM_REVERB_LEVEL:
+        case REVERB_PARAM_DIFFUSION:
+        case REVERB_PARAM_DENSITY:
+            paramSize = sizeof(int16_t);
+            break;
+
+        case REVERB_PARAM_BYPASS:
+        case REVERB_PARAM_DECAY_TIME:
+        case REVERB_PARAM_REFLECTIONS_DELAY:
+        case REVERB_PARAM_REVERB_DELAY:
+            paramSize = sizeof(int32_t);
+            break;
+
+        case REVERB_PARAM_PROPERTIES:
+            paramSize = sizeof(t_reverb_settings);
+            break;
+
+        default:
+            return -EINVAL;
+        }
+
+        if (size != paramSize) {
+            return -EINVAL;
+        }
+
+        if (paramSize == sizeof(int16_t)) {
+            value16 = *(int16_t *) pValue;
+        } else if (paramSize == sizeof(int32_t)) {
+            value32 = *(int32_t *) pValue;
+        } else {
+            pProperties = (t_reverb_settings *) pValue;
+        }
+
+        pPreset = &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom];
+
+        switch (param) {
+        case REVERB_PARAM_BYPASS:
+            pReverb->m_bBypass = (uint16_t)value32;
+            break;
+
+        case REVERB_PARAM_PROPERTIES:
+            value16 = pProperties->roomLevel;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_ROOM_LEVEL:
+            // Convert millibels to linear 16 bit signed => m_nRoomLpfFwd
+            if (value16 > 0)
+                return -EINVAL;
+
+            temp = Effects_MillibelsToLinear16(value16);
+
+            pReverb->m_nRoomLpfFwd
+                    = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRoomLpfFbk));
+
+            LOGV("REVERB_PARAM_ROOM_LEVEL, gain %d, new m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+            if (param == REVERB_PARAM_ROOM_LEVEL)
+                break;
+            value16 = pProperties->roomHFLevel;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_ROOM_HF_LEVEL:
+
+            // Limit to 0 , -40dB range because of low pass implementation
+            if (value16 > 0 || value16 < -4000)
+                return -EINVAL;
+            // Convert attenuation @ 5000H expressed in millibels to => m_nRoomLpfFbk
+            // m_nRoomLpfFbk is -a1 where a1 is the solution of:
+            // a1^2 + 2*(C-dG^2)/(1-dG^2)*a1 + 1 = 0 where:
+            // - C is cos(2*pi*5000/Fs) (pReverb->m_nCosWT_5KHz)
+            // - dG is G0/Gf (G0 is the linear gain at DC and Gf is the wanted gain at 5000Hz)
+
+            // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged
+            // while changing HF level
+            temp2 = (pReverb->m_nRoomLpfFwd << 15) / (32767
+                    - pReverb->m_nRoomLpfFbk);
+            if (value16 == 0) {
+                pReverb->m_nRoomLpfFbk = 0;
+            } else {
+                int32_t dG2, b, delta;
+
+                // dG^2
+                temp = Effects_MillibelsToLinear16(value16);
+                LOGV("REVERB_PARAM_ROOM_HF_LEVEL, HF gain %d", temp);
+                temp = (1 << 30) / temp;
+                LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain %d", temp);
+                dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
+                LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain ^ 2 %d", dG2);
+                // b = 2*(C-dG^2)/(1-dG^2)
+                b = (int32_t) ((((int64_t) 1 << (15 + 1))
+                        * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2))
+                        / ((int64_t) 32767 - (int64_t) dG2));
+
+                // delta = b^2 - 4
+                delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15
+                        + 2)));
+
+                LOGV_IF(delta > (1<<30), " delta overflow %d", delta);
+
+                LOGV("REVERB_PARAM_ROOM_HF_LEVEL, dG2 %d, b %d, delta %d, m_nCosWT_5KHz %d", dG2, b, delta, pReverb->m_nCosWT_5KHz);
+                // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2
+                pReverb->m_nRoomLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;
+            }
+            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, olg DC gain %d new m_nRoomLpfFbk %d, old m_nRoomLpfFwd %d",
+                    temp2, pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFwd);
+
+            pReverb->m_nRoomLpfFwd
+                    = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRoomLpfFbk));
+            LOGV("REVERB_PARAM_ROOM_HF_LEVEL, new m_nRoomLpfFwd %d", pReverb->m_nRoomLpfFwd);
+
+            if (param == REVERB_PARAM_ROOM_HF_LEVEL)
+                break;
+            value32 = pProperties->decayTime;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_DECAY_TIME:
+
+            // Convert milliseconds to => m_nRvbLpfFwd (function of m_nRvbLpfFbk)
+            // convert ms to samples
+            value32 = (value32 * pReverb->m_nSamplingRate) / 1000;
+
+            // calculate valid decay time range as a function of current reverb delay and
+            // max feed back gain. Min value <=> -40dB in one pass, Max value <=> feedback gain = -1 dB
+            // Calculate attenuation for each round in late reverb given a total attenuation of -6000 millibels.
+            // g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time
+            averageDelay = pReverb->m_nLateDelay - pReverb->m_nMaxExcursion;
+            averageDelay += ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn)
+                    + (pReverb->m_sAp1.m_zApOut - pReverb->m_sAp1.m_zApIn)) >> 1;
+
+            temp = (-6000 * averageDelay) / value32;
+            LOGV("REVERB_PARAM_DECAY_TIME, delay smps %d, DT smps %d, gain mB %d",averageDelay, value32, temp);
+            if (temp < -4000 || temp > -100)
+                return -EINVAL;
+
+            // calculate low pass gain by adding reverb input attenuation (pReverb->m_nLateGain) and substrating output
+            // xfade and sum gain (max +9dB)
+            temp -= Effects_Linear16ToMillibels(pReverb->m_nLateGain) + 900;
+            temp = Effects_MillibelsToLinear16(temp);
+
+            // DC gain (temp) = b0 / (1 + a1) = pReverb->m_nRvbLpfFwd / (32767 - pReverb->m_nRvbLpfFbk)
+            pReverb->m_nRvbLpfFwd
+                    = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRvbLpfFbk));
+
+            LOGV("REVERB_PARAM_DECAY_TIME, gain %d, new m_nRvbLpfFwd %d, old m_nRvbLpfFbk %d, reverb gain %d", temp, pReverb->m_nRvbLpfFwd, pReverb->m_nRvbLpfFbk, Effects_Linear16ToMillibels(pReverb->m_nLateGain));
+
+            if (param == REVERB_PARAM_DECAY_TIME)
+                break;
+            value16 = pProperties->decayHFRatio;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_DECAY_HF_RATIO:
+
+            // We limit max value to 1000 because reverb filter is lowpass only
+            if (value16 < 100 || value16 > 1000)
+                return -EINVAL;
+            // Convert per mille to => m_nLpfFwd, m_nLpfFbk
+
+            // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged
+            // while changing HF level
+            temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);
+
+            if (value16 == 1000) {
+                pReverb->m_nRvbLpfFbk = 0;
+            } else {
+                int32_t dG2, b, delta;
+
+                temp = Effects_Linear16ToMillibels(temp2);
+                // G_5000Hz = G_DC * (1000/REVERB_PARAM_DECAY_HF_RATIO) in millibels
+
+                value32 = ((int32_t) 1000 << 15) / (int32_t) value16;
+                LOGV("REVERB_PARAM_DECAY_HF_RATIO, DC gain %d, DC gain mB %d, 1000/R %d", temp2, temp, value32);
+
+                temp = (int32_t) (((int64_t) temp * (int64_t) value32) >> 15);
+
+                if (temp < -4000) {
+                    LOGV("REVERB_PARAM_DECAY_HF_RATIO HF gain overflow %d mB", temp);
+                    temp = -4000;
+                }
+
+                temp = Effects_MillibelsToLinear16(temp);
+                LOGV("REVERB_PARAM_DECAY_HF_RATIO, HF gain %d", temp);
+                // dG^2
+                temp = (temp2 << 15) / temp;
+                dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
+
+                // b = 2*(C-dG^2)/(1-dG^2)
+                b = (int32_t) ((((int64_t) 1 << (15 + 1))
+                        * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2))
+                        / ((int64_t) 32767 - (int64_t) dG2));
+
+                // delta = b^2 - 4
+                delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15
+                        + 2)));
+
+                // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2
+                pReverb->m_nRvbLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;
+
+                LOGV("REVERB_PARAM_DECAY_HF_RATIO, dG2 %d, b %d, delta %d", dG2, b, delta);
+
+            }
+
+            LOGV("REVERB_PARAM_DECAY_HF_RATIO, gain %d, m_nRvbLpfFbk %d, m_nRvbLpfFwd %d", temp2, pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFwd);
+
+            pReverb->m_nRvbLpfFwd
+                    = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRvbLpfFbk));
+
+            if (param == REVERB_PARAM_DECAY_HF_RATIO)
+                break;
+            value16 = pProperties->reflectionsLevel;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_REFLECTIONS_LEVEL:
+            // We limit max value to 0 because gain is limited to 0dB
+            if (value16 > 0 || value16 < -6000)
+                return -EINVAL;
+
+            // Convert millibels to linear 16 bit signed and recompute m_sEarlyL.m_nGain[i] and m_sEarlyR.m_nGain[i].
+            value16 = Effects_MillibelsToLinear16(value16);
+            for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+                pReverb->m_sEarlyL.m_nGain[i]
+                        = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],value16);
+                pReverb->m_sEarlyR.m_nGain[i]
+                        = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],value16);
+            }
+            pReverb->m_nEarlyGain = value16;
+            LOGV("REVERB_PARAM_REFLECTIONS_LEVEL, m_nEarlyGain %d", pReverb->m_nEarlyGain);
+
+            if (param == REVERB_PARAM_REFLECTIONS_LEVEL)
+                break;
+            value32 = pProperties->reflectionsDelay;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_REFLECTIONS_DELAY:
+            // We limit max value MAX_EARLY_TIME
+            // convert ms to time units
+            temp = (value32 * 65536) / 1000;
+            if (temp < 0 || temp > MAX_EARLY_TIME)
+                return -EINVAL;
+
+            maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+                    >> 16;
+            temp = (temp * pReverb->m_nSamplingRate) >> 16;
+            for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+                temp2 = temp + (((int32_t) pPreset->m_sEarlyL.m_zDelay[i]
+                        * pReverb->m_nSamplingRate) >> 16);
+                if (temp2 > maxSamples)
+                    temp2 = maxSamples;
+                pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp2;
+                temp2 = temp + (((int32_t) pPreset->m_sEarlyR.m_zDelay[i]
+                        * pReverb->m_nSamplingRate) >> 16);
+                if (temp2 > maxSamples)
+                    temp2 = maxSamples;
+                pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp2;
+            }
+            pReverb->m_nEarlyDelay = temp;
+
+            LOGV("REVERB_PARAM_REFLECTIONS_DELAY, m_nEarlyDelay smps %d max smp delay %d", pReverb->m_nEarlyDelay, maxSamples);
+
+            // Convert milliseconds to sample count => m_nEarlyDelay
+            if (param == REVERB_PARAM_REFLECTIONS_DELAY)
+                break;
+            value16 = pProperties->reverbLevel;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_REVERB_LEVEL:
+            // We limit max value to 0 because gain is limited to 0dB
+            if (value16 > 0 || value16 < -6000)
+                return -EINVAL;
+            // Convert millibels to linear 16 bits (gange 0 - 8191) => m_nLateGain.
+            pReverb->m_nLateGain = Effects_MillibelsToLinear16(value16) >> 2;
+
+            LOGV("REVERB_PARAM_REVERB_LEVEL, m_nLateGain %d", pReverb->m_nLateGain);
+
+            if (param == REVERB_PARAM_REVERB_LEVEL)
+                break;
+            value32 = pProperties->reverbDelay;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_REVERB_DELAY:
+            // We limit max value to MAX_DELAY_TIME
+            // convert ms to time units
+            temp = (value32 * 65536) / 1000;
+            if (temp < 0 || temp > MAX_DELAY_TIME)
+                return -EINVAL;
+
+            maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+                    >> 16;
+            temp = (temp * pReverb->m_nSamplingRate) >> 16;
+            if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
+                temp = maxSamples - pReverb->m_nMaxExcursion;
+            }
+            if (temp < pReverb->m_nMaxExcursion) {
+                temp = pReverb->m_nMaxExcursion;
+            }
+
+            temp -= pReverb->m_nLateDelay;
+            pReverb->m_nDelay0Out += temp;
+            pReverb->m_nDelay1Out += temp;
+            pReverb->m_nLateDelay += temp;
+
+            LOGV("REVERB_PARAM_REVERB_DELAY, m_nLateDelay smps %d max smp delay %d", pReverb->m_nLateDelay, maxSamples);
+
+            // Convert milliseconds to sample count => m_nDelay1Out + m_nMaxExcursion
+            if (param == REVERB_PARAM_REVERB_DELAY)
+                break;
+
+            value16 = pProperties->diffusion;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_DIFFUSION:
+            if (value16 < 0 || value16 > 1000)
+                return -EINVAL;
+
+            // Convert per mille to m_sAp0.m_nApGain, m_sAp1.m_nApGain
+            pReverb->m_sAp0.m_nApGain = AP0_GAIN_BASE + ((int32_t) value16
+                    * AP0_GAIN_RANGE) / 1000;
+            pReverb->m_sAp1.m_nApGain = AP1_GAIN_BASE + ((int32_t) value16
+                    * AP1_GAIN_RANGE) / 1000;
+
+            LOGV("REVERB_PARAM_DIFFUSION, m_sAp0.m_nApGain %d m_sAp1.m_nApGain %d", pReverb->m_sAp0.m_nApGain, pReverb->m_sAp1.m_nApGain);
+
+            if (param == REVERB_PARAM_DIFFUSION)
+                break;
+
+            value16 = pProperties->density;
+            /* FALL THROUGH */
+
+        case REVERB_PARAM_DENSITY:
+            if (value16 < 0 || value16 > 1000)
+                return -EINVAL;
+
+            // Convert per mille to m_sAp0.m_zApOut, m_sAp1.m_zApOut
+            maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
+
+            temp = AP0_TIME_BASE + ((int32_t) value16 * AP0_TIME_RANGE) / 1000;
+            /*lint -e{702} shift for performance */
+            temp = (temp * pReverb->m_nSamplingRate) >> 16;
+            if (temp > maxSamples)
+                temp = maxSamples;
+            pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);
+
+            LOGV("REVERB_PARAM_DENSITY, Ap0 delay smps %d", temp);
+
+            temp = AP1_TIME_BASE + ((int32_t) value16 * AP1_TIME_RANGE) / 1000;
+            /*lint -e{702} shift for performance */
+            temp = (temp * pReverb->m_nSamplingRate) >> 16;
+            if (temp > maxSamples)
+                temp = maxSamples;
+            pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
+
+            LOGV("Ap1 delay smps %d", temp);
+
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    return 0;
+} /* end Reverb_setParameter */
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateXfade
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the xfade parameters as required
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to write to buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - xfade parameters will be changed
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbUpdateXfade(reverb_object_t *pReverb, int nNumSamplesToAdd) {
+    uint16_t nOffset;
+    int16_t tempCos;
+    int16_t tempSin;
+
+    if (pReverb->m_nXfadeCounter >= pReverb->m_nXfadeInterval) {
+        /* update interval has elapsed, so reset counter */
+        pReverb->m_nXfadeCounter = 0;
+
+        // Pin the sin,cos values to min / max values to ensure that the
+        // modulated taps' coefs are zero (thus no clicks)
+        if (pReverb->m_nPhaseIncrement > 0) {
+            // if phase increment > 0, then sin -> 1, cos -> 0
+            pReverb->m_nSin = 32767;
+            pReverb->m_nCos = 0;
+
+            // reset the phase to match the sin, cos values
+            pReverb->m_nPhase = 32767;
+
+            // modulate the cross taps because their tap coefs are zero
+            nOffset = ReverbCalculateNoise(pReverb);
+
+            pReverb->m_zD1Cross = pReverb->m_nDelay1Out
+                    - pReverb->m_nMaxExcursion + nOffset;
+
+            nOffset = ReverbCalculateNoise(pReverb);
+
+            pReverb->m_zD0Cross = pReverb->m_nDelay0Out
+                    - pReverb->m_nMaxExcursion - nOffset;
+        } else {
+            // if phase increment < 0, then sin -> 0, cos -> 1
+            pReverb->m_nSin = 0;
+            pReverb->m_nCos = 32767;
+
+            // reset the phase to match the sin, cos values
+            pReverb->m_nPhase = -32768;
+
+            // modulate the self taps because their tap coefs are zero
+            nOffset = ReverbCalculateNoise(pReverb);
+
+            pReverb->m_zD0Self = pReverb->m_nDelay0Out
+                    - pReverb->m_nMaxExcursion - nOffset;
+
+            nOffset = ReverbCalculateNoise(pReverb);
+
+            pReverb->m_zD1Self = pReverb->m_nDelay1Out
+                    - pReverb->m_nMaxExcursion + nOffset;
+
+        } // end if-else (pReverb->m_nPhaseIncrement > 0)
+
+        // Reverse the direction of the sin,cos so that the
+        // tap whose coef was previously increasing now decreases
+        // and vice versa
+        pReverb->m_nPhaseIncrement = -pReverb->m_nPhaseIncrement;
+
+    } // end if counter >= update interval
+
+    //compute what phase will be next time
+    pReverb->m_nPhase += pReverb->m_nPhaseIncrement;
+
+    //calculate what the new sin and cos need to reach by the next update
+    ReverbCalculateSinCos(pReverb->m_nPhase, &tempSin, &tempCos);
+
+    //calculate the per-sample increment required to get there by the next update
+    /*lint -e{702} shift for performance */
+    pReverb->m_nSinIncrement = (tempSin - pReverb->m_nSin)
+            >> pReverb->m_nUpdatePeriodInBits;
+
+    /*lint -e{702} shift for performance */
+    pReverb->m_nCosIncrement = (tempCos - pReverb->m_nCos)
+            >> pReverb->m_nUpdatePeriodInBits;
+
+    /* increment update counter */
+    pReverb->m_nXfadeCounter += (uint16_t) nNumSamplesToAdd;
+
+    return 0;
+
+} /* end ReverbUpdateXfade */
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateNoise
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a noise sample and limit its value
+ *
+ * Inputs:
+ * nMaxExcursion - noise value is limited to this value
+ * pnNoise - return new noise sample in this (not limited)
+ *
+ * Outputs:
+ * new limited noise value
+ *
+ * Side Effects:
+ * - *pnNoise noise value is updated
+ *
+ *----------------------------------------------------------------------------
+ */
+static uint16_t ReverbCalculateNoise(reverb_object_t *pReverb) {
+    int16_t nNoise = pReverb->m_nNoise;
+
+    // calculate new noise value
+    if (pReverb->m_bUseNoise) {
+        nNoise = (int16_t) (nNoise * 5 + 1);
+    } else {
+        nNoise = 0;
+    }
+
+    pReverb->m_nNoise = nNoise;
+    // return the limited noise value
+    return (pReverb->m_nMaxExcursion & nNoise);
+
+} /* end ReverbCalculateNoise */
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateSinCos
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a new sin and cosine value based on the given phase
+ *
+ * Inputs:
+ * nPhase   - phase angle
+ * pnSin    - input old value, output new value
+ * pnCos    - input old value, output new value
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - *pnSin, *pnCos are updated
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos) {
+    int32_t nTemp;
+    int32_t nNetAngle;
+
+    //  -1 <=  nPhase  < 1
+    // However, for the calculation, we need a value
+    // that ranges from -1/2 to +1/2, so divide the phase by 2
+    /*lint -e{702} shift for performance */
+    nNetAngle = nPhase >> 1;
+
+    /*
+     Implement the following
+     sin(x) = (2-4*c)*x^2 + c + x
+     cos(x) = (2-4*c)*x^2 + c - x
+
+     where  c = 1/sqrt(2)
+     using the a0 + x*(a1 + x*a2) approach
+     */
+
+    /* limit the input "angle" to be between -0.5 and +0.5 */
+    if (nNetAngle > EG1_HALF) {
+        nNetAngle = EG1_HALF;
+    } else if (nNetAngle < EG1_MINUS_HALF) {
+        nNetAngle = EG1_MINUS_HALF;
+    }
+
+    /* calculate sin */
+    nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
+    nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
+    *pnSin = (int16_t) SATURATE_EG1(nTemp);
+
+    /* calculate cos */
+    nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
+    nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
+    *pnCos = (int16_t) SATURATE_EG1(nTemp);
+
+    return 0;
+} /* end ReverbCalculateSinCos */
+
+/*----------------------------------------------------------------------------
+ * Reverb
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * apply reverb to the given signal
+ *
+ * Inputs:
+ * nNu
+ * pnSin    - input old value, output new value
+ * pnCos    - input old value, output new value
+ *
+ * Outputs:
+ * number of samples actually reverberated
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+static int Reverb(reverb_object_t *pReverb, int nNumSamplesToAdd,
+        short *pOutputBuffer, short *pInputBuffer) {
+    int32_t i;
+    int32_t nDelayOut0;
+    int32_t nDelayOut1;
+    uint16_t nBase;
+
+    uint32_t nAddr;
+    int32_t nTemp1;
+    int32_t nTemp2;
+    int32_t nApIn;
+    int32_t nApOut;
+
+    int32_t j;
+    int32_t nEarlyOut;
+
+    int32_t tempValue;
+
+    // get the base address
+    nBase = pReverb->m_nBaseIndex;
+
+    for (i = 0; i < nNumSamplesToAdd; i++) {
+        // ********** Left Allpass - start
+        nApIn = *pInputBuffer;
+        if (!pReverb->m_Aux) {
+            pInputBuffer++;
+        }
+        // store to early delay line
+        nAddr = CIRCULAR(nBase, pReverb->m_nEarly0in, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nApIn;
+
+        // left input = (left dry * m_nLateGain) + right feedback from previous period
+
+        nApIn = SATURATE(nApIn + pReverb->m_nRevFbkR);
+        nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain);
+
+        // fetch allpass delay line out
+        //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, pReverb->m_nBufferMask);
+        nAddr
+                = CIRCULAR(nBase, pReverb->m_sAp0.m_zApOut, pReverb->m_nBufferMask);
+        nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate allpass feedforward; subtract the feedforward result
+        nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp0.m_nApGain);
+        nApOut = SATURATE(nDelayOut0 - nTemp1); // allpass output
+
+        // calculate allpass feedback; add the feedback result
+        nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp0.m_nApGain);
+        nTemp1 = SATURATE(nApIn + nTemp1);
+
+        // inject into allpass delay
+        nAddr
+                = CIRCULAR(nBase, pReverb->m_sAp0.m_zApIn, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nTemp1;
+
+        // inject allpass output into delay line
+        nAddr = CIRCULAR(nBase, pReverb->m_zD0In, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nApOut;
+
+        // ********** Left Allpass - end
+
+        // ********** Right Allpass - start
+        nApIn = (*pInputBuffer++);
+        // store to early delay line
+        nAddr = CIRCULAR(nBase, pReverb->m_nEarly1in, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nApIn;
+
+        // right input = (right dry * m_nLateGain) + left feedback from previous period
+        /*lint -e{702} use shift for performance */
+        nApIn = SATURATE(nApIn + pReverb->m_nRevFbkL);
+        nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain);
+
+        // fetch allpass delay line out
+        nAddr
+                = CIRCULAR(nBase, pReverb->m_sAp1.m_zApOut, pReverb->m_nBufferMask);
+        nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate allpass feedforward; subtract the feedforward result
+        nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp1.m_nApGain);
+        nApOut = SATURATE(nDelayOut1 - nTemp1); // allpass output
+
+        // calculate allpass feedback; add the feedback result
+        nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp1.m_nApGain);
+        nTemp1 = SATURATE(nApIn + nTemp1);
+
+        // inject into allpass delay
+        nAddr
+                = CIRCULAR(nBase, pReverb->m_sAp1.m_zApIn, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nTemp1;
+
+        // inject allpass output into delay line
+        nAddr = CIRCULAR(nBase, pReverb->m_zD1In, pReverb->m_nBufferMask);
+        pReverb->m_nDelayLine[nAddr] = (short) nApOut;
+
+        // ********** Right Allpass - end
+
+        // ********** D0 output - start
+        // fetch delay line self out
+        nAddr = CIRCULAR(nBase, pReverb->m_zD0Self, pReverb->m_nBufferMask);
+        nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate delay line self out
+        nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nSin);
+
+        // fetch delay line cross out
+        nAddr = CIRCULAR(nBase, pReverb->m_zD1Cross, pReverb->m_nBufferMask);
+        nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate delay line self out
+        nTemp2 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nCos);
+
+        // calculate unfiltered delay out
+        nDelayOut0 = SATURATE(nTemp1 + nTemp2);
+
+        // ********** D0 output - end
+
+        // ********** D1 output - start
+        // fetch delay line self out
+        nAddr = CIRCULAR(nBase, pReverb->m_zD1Self, pReverb->m_nBufferMask);
+        nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate delay line self out
+        nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nSin);
+
+        // fetch delay line cross out
+        nAddr = CIRCULAR(nBase, pReverb->m_zD0Cross, pReverb->m_nBufferMask);
+        nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+        // calculate delay line self out
+        nTemp2 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nCos);
+
+        // calculate unfiltered delay out
+        nDelayOut1 = SATURATE(nTemp1 + nTemp2);
+
+        // ********** D1 output - end
+
+        // ********** mixer and feedback - start
+        // sum is fedback to right input (R + L)
+        nDelayOut0 = (short) SATURATE(nDelayOut0 + nDelayOut1);
+
+        // difference is feedback to left input (R - L)
+        /*lint -e{685} lint complains that it can't saturate negative */
+        nDelayOut1 = (short) SATURATE(nDelayOut1 - nDelayOut0);
+
+        // ********** mixer and feedback - end
+
+        // calculate lowpass filter (mixer scale factor included in LPF feedforward)
+        nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRvbLpfFwd);
+
+        nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkL, pReverb->m_nRvbLpfFbk);
+
+        // calculate filtered delay out and simultaneously update LPF state variable
+        // filtered delay output is stored in m_nRevFbkL
+        pReverb->m_nRevFbkL = (short) SATURATE(nTemp1 + nTemp2);
+
+        // calculate lowpass filter (mixer scale factor included in LPF feedforward)
+        nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRvbLpfFwd);
+
+        nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkR, pReverb->m_nRvbLpfFbk);
+
+        // calculate filtered delay out and simultaneously update LPF state variable
+        // filtered delay output is stored in m_nRevFbkR
+        pReverb->m_nRevFbkR = (short) SATURATE(nTemp1 + nTemp2);
+
+        // ********** start early reflection generator, left
+        //psEarly = &(pReverb->m_sEarlyL);
+
+
+        for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) {
+            // fetch delay line out
+            //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], pReverb->m_nBufferMask);
+            nAddr
+                    = CIRCULAR(nBase, pReverb->m_sEarlyL.m_zDelay[j], pReverb->m_nBufferMask);
+
+            nTemp1 = pReverb->m_nDelayLine[nAddr];
+
+            // calculate reflection
+            //nTemp1 = MULT_EG1_EG1(nDelayOut0, psEarly->m_nGain[j]);
+            nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyL.m_nGain[j]);
+
+            nDelayOut0 = SATURATE(nDelayOut0 + nTemp1);
+
+        } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+
+        // apply lowpass to early reflections and reverb output
+        //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nRvbLpfFwd);
+        nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRoomLpfFwd);
+
+        //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk);
+        nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfL, pReverb->m_nRoomLpfFbk);
+
+        // calculate filtered out and simultaneously update LPF state variable
+        // filtered output is stored in m_zOutLpfL
+        pReverb->m_zOutLpfL = (short) SATURATE(nTemp1 + nTemp2);
+
+        //sum with output buffer
+        tempValue = *pOutputBuffer;
+        *pOutputBuffer++ = (short) SATURATE(tempValue+pReverb->m_zOutLpfL);
+
+        // ********** end early reflection generator, left
+
+        // ********** start early reflection generator, right
+        //psEarly = &(pReverb->m_sEarlyR);
+
+        for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) {
+            // fetch delay line out
+            nAddr
+                    = CIRCULAR(nBase, pReverb->m_sEarlyR.m_zDelay[j], pReverb->m_nBufferMask);
+            nTemp1 = pReverb->m_nDelayLine[nAddr];
+
+            // calculate reflection
+            nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyR.m_nGain[j]);
+
+            nDelayOut1 = SATURATE(nDelayOut1 + nTemp1);
+
+        } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+
+        // apply lowpass to early reflections
+        nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRoomLpfFwd);
+
+        nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfR, pReverb->m_nRoomLpfFbk);
+
+        // calculate filtered out and simultaneously update LPF state variable
+        // filtered output is stored in m_zOutLpfR
+        pReverb->m_zOutLpfR = (short) SATURATE(nTemp1 + nTemp2);
+
+        //sum with output buffer
+        tempValue = *pOutputBuffer;
+        *pOutputBuffer++ = (short) SATURATE(tempValue + pReverb->m_zOutLpfR);
+
+        // ********** end early reflection generator, right
+
+        // decrement base addr for next sample period
+        nBase--;
+
+        pReverb->m_nSin += pReverb->m_nSinIncrement;
+        pReverb->m_nCos += pReverb->m_nCosIncrement;
+
+    } // end for (i=0; i < nNumSamplesToAdd; i++)
+
+    // store the most up to date version
+    pReverb->m_nBaseIndex = nBase;
+
+    return 0;
+} /* end Reverb */
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateRoom
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the room's preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - reverb paramters (fbk, fwd, etc) will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+ */
+static int ReverbUpdateRoom(reverb_object_t *pReverb, bool fullUpdate) {
+    int temp;
+    int i;
+    int maxSamples;
+    int earlyDelay;
+    int earlyGain;
+
+    reverb_preset_t *pPreset =
+            &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom];
+
+    if (fullUpdate) {
+        pReverb->m_nRvbLpfFwd = pPreset->m_nRvbLpfFwd;
+        pReverb->m_nRvbLpfFbk = pPreset->m_nRvbLpfFbk;
+
+        pReverb->m_nEarlyGain = pPreset->m_nEarlyGain;
+        //stored as time based, convert to sample based
+        pReverb->m_nLateGain = pPreset->m_nLateGain;
+        pReverb->m_nRoomLpfFbk = pPreset->m_nRoomLpfFbk;
+        pReverb->m_nRoomLpfFwd = pPreset->m_nRoomLpfFwd;
+
+        // set the early reflections gains
+        earlyGain = pPreset->m_nEarlyGain;
+        for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+            pReverb->m_sEarlyL.m_nGain[i]
+                    = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],earlyGain);
+            pReverb->m_sEarlyR.m_nGain[i]
+                    = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],earlyGain);
+        }
+
+        pReverb->m_nMaxExcursion = pPreset->m_nMaxExcursion;
+
+        pReverb->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
+        pReverb->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;
+
+        // set the early reflections delay
+        earlyDelay = ((int) pPreset->m_nEarlyDelay * pReverb->m_nSamplingRate)
+                >> 16;
+        pReverb->m_nEarlyDelay = earlyDelay;
+        maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+                >> 16;
+        for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+            //stored as time based, convert to sample based
+            temp = earlyDelay + (((int) pPreset->m_sEarlyL.m_zDelay[i]
+                    * pReverb->m_nSamplingRate) >> 16);
+            if (temp > maxSamples)
+                temp = maxSamples;
+            pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp;
+            //stored as time based, convert to sample based
+            temp = earlyDelay + (((int) pPreset->m_sEarlyR.m_zDelay[i]
+                    * pReverb->m_nSamplingRate) >> 16);
+            if (temp > maxSamples)
+                temp = maxSamples;
+            pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp;
+        }
+
+        maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+                >> 16;
+        //stored as time based, convert to sample based
+        /*lint -e{702} shift for performance */
+        temp = (pPreset->m_nLateDelay * pReverb->m_nSamplingRate) >> 16;
+        if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
+            temp = maxSamples - pReverb->m_nMaxExcursion;
+        }
+        temp -= pReverb->m_nLateDelay;
+        pReverb->m_nDelay0Out += temp;
+        pReverb->m_nDelay1Out += temp;
+        pReverb->m_nLateDelay += temp;
+
+        maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
+        //stored as time based, convert to absolute sample value
+        temp = pPreset->m_nAp0_ApOut;
+        /*lint -e{702} shift for performance */
+        temp = (temp * pReverb->m_nSamplingRate) >> 16;
+        if (temp > maxSamples)
+            temp = maxSamples;
+        pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);
+
+        //stored as time based, convert to absolute sample value
+        temp = pPreset->m_nAp1_ApOut;
+        /*lint -e{702} shift for performance */
+        temp = (temp * pReverb->m_nSamplingRate) >> 16;
+        if (temp > maxSamples)
+            temp = maxSamples;
+        pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
+        //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
+    }
+
+    //stored as time based, convert to sample based
+    temp = pPreset->m_nXfadeInterval;
+    /*lint -e{702} shift for performance */
+    temp = (temp * pReverb->m_nSamplingRate) >> 16;
+    pReverb->m_nXfadeInterval = (uint16_t) temp;
+    //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval;
+    pReverb->m_nXfadeCounter = pReverb->m_nXfadeInterval + 1; // force update on first iteration
+
+    pReverb->m_nCurrentRoom = pReverb->m_nNextRoom;
+
+    return 0;
+
+} /* end ReverbUpdateRoom */
+
+/*----------------------------------------------------------------------------
+ * ReverbReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global reverb preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbReadInPresets(reverb_object_t *pReverb) {
+
+    int preset;
+
+    // this is for test only. OpenSL ES presets are mapped to 4 presets.
+    // REVERB_PRESET_NONE is mapped to bypass
+    for (preset = 0; preset < REVERB_NUM_PRESETS; preset++) {
+        reverb_preset_t *pPreset = &pReverb->m_sPreset.m_sPreset[preset];
+        switch (preset + 1) {
+        case REVERB_PRESET_PLATE:
+        case REVERB_PRESET_SMALLROOM:
+            pPreset->m_nRvbLpfFbk = 5077;
+            pPreset->m_nRvbLpfFwd = 11076;
+            pPreset->m_nEarlyGain = 27690;
+            pPreset->m_nEarlyDelay = 1311;
+            pPreset->m_nLateGain = 8191;
+            pPreset->m_nLateDelay = 3932;
+            pPreset->m_nRoomLpfFbk = 3692;
+            pPreset->m_nRoomLpfFwd = 20474;
+            pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+            pPreset->m_sEarlyL.m_nGain[0] = 22152;
+            pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+            pPreset->m_sEarlyL.m_nGain[1] = 17537;
+            pPreset->m_sEarlyL.m_zDelay[2] = 0;
+            pPreset->m_sEarlyL.m_nGain[2] = 14768;
+            pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+            pPreset->m_sEarlyL.m_nGain[3] = 14307;
+            pPreset->m_sEarlyL.m_zDelay[4] = 0;
+            pPreset->m_sEarlyL.m_nGain[4] = 13384;
+            pPreset->m_sEarlyR.m_zDelay[0] = 721;
+            pPreset->m_sEarlyR.m_nGain[0] = 20306;
+            pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+            pPreset->m_sEarlyR.m_nGain[1] = 17537;
+            pPreset->m_sEarlyR.m_zDelay[2] = 0;
+            pPreset->m_sEarlyR.m_nGain[2] = 14768;
+            pPreset->m_sEarlyR.m_zDelay[3] = 0;
+            pPreset->m_sEarlyR.m_nGain[3] = 16153;
+            pPreset->m_sEarlyR.m_zDelay[4] = 0;
+            pPreset->m_sEarlyR.m_nGain[4] = 13384;
+            pPreset->m_nMaxExcursion = 127;
+            pPreset->m_nXfadeInterval = 6470; //6483;
+            pPreset->m_nAp0_ApGain = 14768;
+            pPreset->m_nAp0_ApOut = 792;
+            pPreset->m_nAp1_ApGain = 14777;
+            pPreset->m_nAp1_ApOut = 1191;
+            pPreset->m_rfu4 = 0;
+            pPreset->m_rfu5 = 0;
+            pPreset->m_rfu6 = 0;
+            pPreset->m_rfu7 = 0;
+            pPreset->m_rfu8 = 0;
+            pPreset->m_rfu9 = 0;
+            pPreset->m_rfu10 = 0;
+            break;
+        case REVERB_PRESET_MEDIUMROOM:
+        case REVERB_PRESET_LARGEROOM:
+            pPreset->m_nRvbLpfFbk = 5077;
+            pPreset->m_nRvbLpfFwd = 12922;
+            pPreset->m_nEarlyGain = 27690;
+            pPreset->m_nEarlyDelay = 1311;
+            pPreset->m_nLateGain = 8191;
+            pPreset->m_nLateDelay = 3932;
+            pPreset->m_nRoomLpfFbk = 3692;
+            pPreset->m_nRoomLpfFwd = 21703;
+            pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+            pPreset->m_sEarlyL.m_nGain[0] = 22152;
+            pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+            pPreset->m_sEarlyL.m_nGain[1] = 17537;
+            pPreset->m_sEarlyL.m_zDelay[2] = 0;
+            pPreset->m_sEarlyL.m_nGain[2] = 14768;
+            pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+            pPreset->m_sEarlyL.m_nGain[3] = 14307;
+            pPreset->m_sEarlyL.m_zDelay[4] = 0;
+            pPreset->m_sEarlyL.m_nGain[4] = 13384;
+            pPreset->m_sEarlyR.m_zDelay[0] = 721;
+            pPreset->m_sEarlyR.m_nGain[0] = 20306;
+            pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+            pPreset->m_sEarlyR.m_nGain[1] = 17537;
+            pPreset->m_sEarlyR.m_zDelay[2] = 0;
+            pPreset->m_sEarlyR.m_nGain[2] = 14768;
+            pPreset->m_sEarlyR.m_zDelay[3] = 0;
+            pPreset->m_sEarlyR.m_nGain[3] = 16153;
+            pPreset->m_sEarlyR.m_zDelay[4] = 0;
+            pPreset->m_sEarlyR.m_nGain[4] = 13384;
+            pPreset->m_nMaxExcursion = 127;
+            pPreset->m_nXfadeInterval = 6449;
+            pPreset->m_nAp0_ApGain = 15691;
+            pPreset->m_nAp0_ApOut = 774;
+            pPreset->m_nAp1_ApGain = 16317;
+            pPreset->m_nAp1_ApOut = 1155;
+            pPreset->m_rfu4 = 0;
+            pPreset->m_rfu5 = 0;
+            pPreset->m_rfu6 = 0;
+            pPreset->m_rfu7 = 0;
+            pPreset->m_rfu8 = 0;
+            pPreset->m_rfu9 = 0;
+            pPreset->m_rfu10 = 0;
+            break;
+        case REVERB_PRESET_MEDIUMHALL:
+            pPreset->m_nRvbLpfFbk = 6461;
+            pPreset->m_nRvbLpfFwd = 14307;
+            pPreset->m_nEarlyGain = 27690;
+            pPreset->m_nEarlyDelay = 1311;
+            pPreset->m_nLateGain = 8191;
+            pPreset->m_nLateDelay = 3932;
+            pPreset->m_nRoomLpfFbk = 3692;
+            pPreset->m_nRoomLpfFwd = 24569;
+            pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+            pPreset->m_sEarlyL.m_nGain[0] = 22152;
+            pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+            pPreset->m_sEarlyL.m_nGain[1] = 17537;
+            pPreset->m_sEarlyL.m_zDelay[2] = 0;
+            pPreset->m_sEarlyL.m_nGain[2] = 14768;
+            pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+            pPreset->m_sEarlyL.m_nGain[3] = 14307;
+            pPreset->m_sEarlyL.m_zDelay[4] = 0;
+            pPreset->m_sEarlyL.m_nGain[4] = 13384;
+            pPreset->m_sEarlyR.m_zDelay[0] = 721;
+            pPreset->m_sEarlyR.m_nGain[0] = 20306;
+            pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+            pPreset->m_sEarlyR.m_nGain[1] = 17537;
+            pPreset->m_sEarlyR.m_zDelay[2] = 0;
+            pPreset->m_sEarlyR.m_nGain[2] = 14768;
+            pPreset->m_sEarlyR.m_zDelay[3] = 0;
+            pPreset->m_sEarlyR.m_nGain[3] = 16153;
+            pPreset->m_sEarlyR.m_zDelay[4] = 0;
+            pPreset->m_sEarlyR.m_nGain[4] = 13384;
+            pPreset->m_nMaxExcursion = 127;
+            pPreset->m_nXfadeInterval = 6391;
+            pPreset->m_nAp0_ApGain = 15230;
+            pPreset->m_nAp0_ApOut = 708;
+            pPreset->m_nAp1_ApGain = 15547;
+            pPreset->m_nAp1_ApOut = 1023;
+            pPreset->m_rfu4 = 0;
+            pPreset->m_rfu5 = 0;
+            pPreset->m_rfu6 = 0;
+            pPreset->m_rfu7 = 0;
+            pPreset->m_rfu8 = 0;
+            pPreset->m_rfu9 = 0;
+            pPreset->m_rfu10 = 0;
+            break;
+        case REVERB_PRESET_LARGEHALL:
+            pPreset->m_nRvbLpfFbk = 8307;
+            pPreset->m_nRvbLpfFwd = 14768;
+            pPreset->m_nEarlyGain = 27690;
+            pPreset->m_nEarlyDelay = 1311;
+            pPreset->m_nLateGain = 8191;
+            pPreset->m_nLateDelay = 3932;
+            pPreset->m_nRoomLpfFbk = 3692;
+            pPreset->m_nRoomLpfFwd = 24569;
+            pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+            pPreset->m_sEarlyL.m_nGain[0] = 22152;
+            pPreset->m_sEarlyL.m_zDelay[1] = 2163;
+            pPreset->m_sEarlyL.m_nGain[1] = 17537;
+            pPreset->m_sEarlyL.m_zDelay[2] = 0;
+            pPreset->m_sEarlyL.m_nGain[2] = 14768;
+            pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+            pPreset->m_sEarlyL.m_nGain[3] = 14307;
+            pPreset->m_sEarlyL.m_zDelay[4] = 0;
+            pPreset->m_sEarlyL.m_nGain[4] = 13384;
+            pPreset->m_sEarlyR.m_zDelay[0] = 721;
+            pPreset->m_sEarlyR.m_nGain[0] = 20306;
+            pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+            pPreset->m_sEarlyR.m_nGain[1] = 17537;
+            pPreset->m_sEarlyR.m_zDelay[2] = 0;
+            pPreset->m_sEarlyR.m_nGain[2] = 14768;
+            pPreset->m_sEarlyR.m_zDelay[3] = 0;
+            pPreset->m_sEarlyR.m_nGain[3] = 16153;
+            pPreset->m_sEarlyR.m_zDelay[4] = 0;
+            pPreset->m_sEarlyR.m_nGain[4] = 13384;
+            pPreset->m_nMaxExcursion = 127;
+            pPreset->m_nXfadeInterval = 6388;
+            pPreset->m_nAp0_ApGain = 15691;
+            pPreset->m_nAp0_ApOut = 711;
+            pPreset->m_nAp1_ApGain = 16317;
+            pPreset->m_nAp1_ApOut = 1029;
+            pPreset->m_rfu4 = 0;
+            pPreset->m_rfu5 = 0;
+            pPreset->m_rfu6 = 0;
+            pPreset->m_rfu7 = 0;
+            pPreset->m_rfu8 = 0;
+            pPreset->m_rfu9 = 0;
+            pPreset->m_rfu10 = 0;
+            break;
+        }
+    }
+
+    return 0;
+}
diff --git a/media/libeffects/testlibs/EffectReverb.h b/media/libeffects/testlibs/EffectReverb.h
new file mode 100644
index 0000000..dbcd192
--- /dev/null
+++ b/media/libeffects/testlibs/EffectReverb.h
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2008 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 ANDROID_EFFECTREVERB_H_
+#define ANDROID_EFFECTREVERB_H_
+
+#include <media/EffectEnvironmentalReverbApi.h>
+#include <media/EffectPresetReverbApi.h>
+
+
+/*------------------------------------
+ * defines
+ *------------------------------------
+*/
+
+/*
+CIRCULAR() calculates the array index using modulo arithmetic.
+The "trick" is that modulo arithmetic is simplified by masking
+the effective address where the mask is (2^n)-1. This only works
+if the buffer size is a power of two.
+*/
+#define CIRCULAR(base,offset,size) (uint32_t)(               \
+            (                                               \
+                ((int32_t)(base)) + ((int32_t)(offset))     \
+            )                                               \
+            & size                                          \
+                                            )
+
+#define NUM_OUTPUT_CHANNELS 2
+#define OUTPUT_CHANNELS CHANNEL_STEREO
+
+#define REVERB_BUFFER_SIZE_IN_SAMPLES_MAX   16384
+
+#define REVERB_NUM_PRESETS  REVERB_PRESET_PLATE   // REVERB_PRESET_NONE is not included
+#define REVERB_MAX_NUM_REFLECTIONS      5   // max num reflections per channel
+
+
+// xfade parameters
+#define REVERB_XFADE_PERIOD_IN_SECONDS      (double) (100.0 / 1000.0)        // xfade once every this many seconds
+
+
+/**********/
+/* the entire synth uses various flags in a bit field */
+
+/* if flag is set, synth reset has been requested */
+#define REVERB_FLAG_RESET_IS_REQUESTED          0x01    /* bit 0 */
+#define MASK_REVERB_RESET_IS_REQUESTED          0x01
+#define MASK_REVERB_RESET_IS_NOT_REQUESTED      (uint32_t)(~MASK_REVERB_RESET_IS_REQUESTED)
+
+/*
+by default, we always want to update ALL channel parameters
+when we reset the synth (e.g., during GM ON)
+*/
+#define DEFAULT_REVERB_FLAGS                    0x0
+
+/* coefficients for generating sin, cos */
+#define REVERB_PAN_G2   4294940151          /* -0.82842712474619 = 2 - 4/sqrt(2) */
+/*
+int32_t nPanG1 = +1.0 for sin
+int32_t nPanG1 = -1.0 for cos
+*/
+#define REVERB_PAN_G0   23170               /* 0.707106781186547 = 1/sqrt(2) */
+
+/*************************************************************/
+// define the input injection points
+#define GUARD               5                       // safety guard of this many samples
+
+#define MAX_AP_TIME         (int) ((20*65536)/1000)  // delay time in time units (65536th of sec)
+#define MAX_DELAY_TIME      (int) ((65*65536)/1000)  // delay time in time units
+#define MAX_EARLY_TIME      (int) ((65*65536)/1000)  // delay time in time units
+
+#define AP0_IN              0
+
+
+#define REVERB_DEFAULT_ROOM_NUMBER      1       // default preset number
+#define DEFAULT_AP0_GAIN                19400
+#define DEFAULT_AP1_GAIN                -19400
+
+#define REVERB_DEFAULT_WET              32767
+#define REVERB_DEFAULT_DRY              0
+
+#define REVERB_WET_MAX              32767
+#define REVERB_WET_MIN              0
+#define REVERB_DRY_MAX              32767
+#define REVERB_DRY_MIN              0
+
+// constants for reverb density
+// The density expressed in permilles changes the Allpass delay in a linear manner in the range defined by
+// AP0_TIME_BASE to AP0_TIME_BASE + AP0_TIME_RANGE
+#define AP0_TIME_BASE (int)((9*65536)/1000)
+#define AP0_TIME_RANGE (int)((4*65536)/1000)
+#define AP1_TIME_BASE (int)((12*65536)/1000)
+#define AP1_TIME_RANGE (int)((8*65536)/1000)
+
+// constants for reverb diffusion
+// The diffusion expressed in permilles changes the Allpass gain in a linear manner in the range defined by
+// AP0_GAIN_BASE to AP0_GAIN_BASE + AP0_GAIN_RANGE
+#define AP0_GAIN_BASE (int)(9830)
+#define AP0_GAIN_RANGE (int)(19660-9830)
+#define AP1_GAIN_BASE (int)(6553)
+#define AP1_GAIN_RANGE (int)(22936-6553)
+
+
+enum reverb_state_e {
+    REVERB_STATE_UNINITIALIZED,
+    REVERB_STATE_INITIALIZED,
+    REVERB_STATE_ACTIVE,
+};
+
+/* parameters for each allpass */
+typedef struct
+{
+    uint16_t             m_zApOut;       // delay offset for ap out
+
+    int16_t             m_nApGain;      // gain for ap
+
+    uint16_t             m_zApIn;        // delay offset for ap in
+
+} allpass_object_t;
+
+
+/* parameters for early reflections */
+typedef struct
+{
+    uint16_t            m_zDelay[REVERB_MAX_NUM_REFLECTIONS];   // delay offset for ap out
+
+    int16_t             m_nGain[REVERB_MAX_NUM_REFLECTIONS];    // gain for ap
+
+} early_reflection_object_t;
+
+//demo
+typedef struct
+{
+    int16_t             m_nRvbLpfFbk;
+    int16_t             m_nRvbLpfFwd;
+    int16_t             m_nRoomLpfFbk;
+    int16_t             m_nRoomLpfFwd;
+
+    int16_t             m_nEarlyGain;
+    int16_t             m_nEarlyDelay;
+    int16_t             m_nLateGain;
+    int16_t             m_nLateDelay;
+
+    early_reflection_object_t m_sEarlyL;
+    early_reflection_object_t m_sEarlyR;
+
+    uint16_t            m_nMaxExcursion; //28
+    int16_t             m_nXfadeInterval;
+
+    int16_t             m_nAp0_ApGain; //30
+    int16_t             m_nAp0_ApOut;
+    int16_t             m_nAp1_ApGain;
+    int16_t             m_nAp1_ApOut;
+    int16_t             m_nDiffusion;
+
+    int16_t             m_rfu4;
+    int16_t             m_rfu5;
+    int16_t             m_rfu6;
+    int16_t             m_rfu7;
+    int16_t             m_rfu8;
+    int16_t             m_rfu9;
+    int16_t             m_rfu10; //43
+
+} reverb_preset_t;
+
+typedef struct
+{
+    reverb_preset_t     m_sPreset[REVERB_NUM_PRESETS]; // array of presets(does not include REVERB_PRESET_NONE)
+
+} reverb_preset_bank_t;
+
+
+/* parameters for each reverb */
+typedef struct
+{
+    /* update counter keeps track of when synth params need updating */
+    /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */
+    int16_t             m_nUpdateCounter;
+
+    uint16_t             m_nBaseIndex;                                   // base index for circular buffer
+
+    // reverb delay line offsets, allpass parameters, etc:
+
+    short             m_nRevFbkR;              // combine feedback reverb right out with dry left in
+    short             m_zOutLpfL;              // left reverb output
+
+    allpass_object_t    m_sAp0;                     // allpass 0 (left channel)
+
+    uint16_t             m_zD0In;                    // delay offset for delay line D0 in
+
+    short             m_nRevFbkL;              // combine feedback reverb left out with dry right in
+    short             m_zOutLpfR;              // right reverb output
+
+    allpass_object_t    m_sAp1;                     // allpass 1 (right channel)
+
+    uint16_t             m_zD1In;                    // delay offset for delay line D1 in
+
+    // delay output taps, notice criss cross order
+    uint16_t             m_zD0Self;                  // self feeds forward d0 --> d0
+
+    uint16_t             m_zD1Cross;                 // cross feeds across d1 --> d0
+
+    uint16_t             m_zD1Self;                  // self feeds forward d1 --> d1
+
+    uint16_t             m_zD0Cross;                 // cross feeds across d0 --> d1
+
+    int16_t             m_nSin;                     // gain for self taps
+
+    int16_t             m_nCos;                     // gain for cross taps
+
+    int16_t             m_nSinIncrement;            // increment for gain
+
+    int16_t             m_nCosIncrement;            // increment for gain
+
+    int16_t             m_nRvbLpfFwd;                  // reverb feedback lpf forward gain (includes scaling for mixer)
+
+    int16_t             m_nRvbLpfFbk;                  // reverb feedback lpf feedback gain
+
+    int16_t             m_nRoomLpfFwd;                  // room lpf forward gain (includes scaling for mixer)
+
+    int16_t             m_nRoomLpfFbk;                  // room lpf feedback gain
+
+    uint16_t            m_nXfadeInterval;           // update/xfade after this many samples
+
+    uint16_t            m_nXfadeCounter;            // keep track of when to xfade
+
+    int16_t             m_nPhase;                   // -1 <= m_nPhase < 1
+                                                    // but during sin,cos calculations
+                                                    // use m_nPhase/2
+
+    int16_t             m_nPhaseIncrement;          // add this to m_nPhase each frame
+
+    int16_t             m_nNoise;                   // random noise sample
+
+    uint16_t            m_nMaxExcursion;            // the taps can excurse +/- this amount
+
+    uint16_t            m_bUseNoise;                // if TRUE, use noise as input signal
+
+    uint16_t            m_bBypass;                  // if TRUE, then bypass reverb and copy input to output
+
+    int16_t             m_nCurrentRoom;             // preset number for current room
+
+    int16_t             m_nNextRoom;                // preset number for next room
+
+    int16_t             m_nEarlyGain;               // gain for early (widen) signal
+    int16_t             m_nEarlyDelay;              // initial dealy for early (widen) signal
+    int16_t             m_nEarly0in;
+    int16_t             m_nEarly1in;
+    int16_t             m_nLateGain;               // gain for late reverb
+    int16_t             m_nLateDelay;
+
+    int16_t             m_nDiffusion;
+
+    early_reflection_object_t   m_sEarlyL;          // left channel early reflections
+    early_reflection_object_t   m_sEarlyR;          // right channel early reflections
+
+    short             m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES_MAX];    // one large delay line for all reverb elements
+
+    reverb_preset_t     pPreset;
+
+    reverb_preset_bank_t  m_sPreset;
+
+    //int8_t            preset;
+    uint32_t            m_nSamplingRate;
+    int32_t             m_nUpdatePeriodInBits;
+    int32_t             m_nBufferMask;
+    int32_t             m_nUpdatePeriodInSamples;
+    int32_t             m_nDelay0Out;
+    int32_t             m_nDelay1Out;
+    int16_t             m_nCosWT_5KHz;
+
+    uint16_t            m_Aux;                // if TRUE, is connected as auxiliary effect
+    uint16_t            m_Preset;             // if TRUE, expose preset revert interface
+
+    uint32_t            mState;
+} reverb_object_t;
+
+
+
+typedef struct reverb_module_s {
+    const struct effect_interface_s *itfe;
+    effect_config_t config;
+    reverb_object_t context;
+} reverb_module_t;
+
+/*------------------------------------
+ * Effect API
+ *------------------------------------
+*/
+int EffectQueryNumberEffects(uint32_t *pNumEffects);
+int EffectQueryEffect(uint32_t index,
+                      effect_descriptor_t *pDescriptor);
+int EffectCreate(effect_uuid_t *effectUID,
+                 int32_t sessionId,
+                 int32_t ioId,
+                 effect_interface_t *pInterface);
+int EffectRelease(effect_interface_t interface);
+
+static int Reverb_Process(effect_interface_t self,
+                          audio_buffer_t *inBuffer,
+                          audio_buffer_t *outBuffer);
+static int Reverb_Command(effect_interface_t self,
+                          uint32_t cmdCode,
+                          uint32_t cmdSize,
+                          void *pCmdData,
+                          uint32_t *replySize,
+                          void *pReplyData);
+
+
+/*------------------------------------
+ * internal functions
+ *------------------------------------
+*/
+
+int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset);
+int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool init);
+void Reverb_Reset(reverb_object_t *pReverb, bool init);
+
+int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, size_t size, void *pValue);
+int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, void *pValue);
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateXfade
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the xfade parameters as required
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to write to buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - xfade parameters will be changed
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbUpdateXfade(reverb_object_t* pReverbData, int nNumSamplesToAdd);
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateNoise
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a noise sample and limit its value
+ *
+ * Inputs:
+ * Pointer to reverb context
+ *
+ * Outputs:
+ * new limited noise value
+ *
+ * Side Effects:
+ * - pReverbData->m_nNoise value is updated
+ *
+ *----------------------------------------------------------------------------
+*/
+static uint16_t ReverbCalculateNoise(reverb_object_t *pReverbData);
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateSinCos
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a new sin and cosine value based on the given phase
+ *
+ * Inputs:
+ * nPhase   - phase angle
+ * pnSin    - input old value, output new value
+ * pnCos    - input old value, output new value
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - *pnSin, *pnCos are updated
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos);
+
+/*----------------------------------------------------------------------------
+ * Reverb
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * apply reverb to the given signal
+ *
+ * Inputs:
+ * nNu
+ * pnSin    - input old value, output new value
+ * pnCos    - input old value, output new value
+ *
+ * Outputs:
+ * number of samples actually reverberated
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static int Reverb(reverb_object_t* pReverbData, int nNumSamplesToAdd, short *pOutputBuffer, short *pInputBuffer);
+
+/*----------------------------------------------------------------------------
+ * ReverbReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global reverb preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbReadInPresets(reverb_object_t* pReverbData);
+
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateRoom
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the room's preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - reverb paramters (fbk, fwd, etc) will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+*/
+static int ReverbUpdateRoom(reverb_object_t* pReverbData, bool fullUpdate);
+
+
+static int ReverbComputeConstants(reverb_object_t *pReverbData, uint32_t samplingRate);
+
+#endif /*ANDROID_EFFECTREVERB_H_*/
diff --git a/media/libeffects/testlibs/EffectsMath.c b/media/libeffects/testlibs/EffectsMath.c
new file mode 100644
index 0000000..41ec662
--- /dev/null
+++ b/media/libeffects/testlibs/EffectsMath.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008 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_TAG "EFFECTSMATH"
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+
+#include "EffectsMath.h"
+
+// gLogTab contains pre-calculated values of log2(1 + ai5*2^-1 + ai4*2^-2 + ai3*2^-3 + ai2*2^-4 + ai1*2^-5 + ai0*2^-6)
+// for integers in the range 0 to 63 (i = ai5*2^5 + ai4*2^4 + ai3*2^3 + ai2*2^2 + ai1*2^1 + ai0*2^0)
+// It is used for a better than piece wise approximation of lin to log2 conversion
+
+static const uint16_t gLogTab[] =
+{
+    0, 733, 1455, 2166,
+    2866, 3556, 4236, 4907,
+    5568, 6220, 6863, 7498,
+    8124, 8742, 9352, 9954,
+    10549, 11136, 11716, 12289,
+    12855, 13415, 13968, 14514,
+    15055, 15589, 16117, 16639,
+    17156, 17667, 18173, 18673,
+    19168, 19658, 20143, 20623,
+    21098, 21568, 22034, 22495,
+    22952, 23404, 23852, 24296,
+    24736, 25172, 25604, 26031,
+    26455, 26876, 27292, 27705,
+    28114, 28520, 28922, 29321,
+    29717, 30109, 30498, 30884,
+    31267, 31647, 32024, 32397,
+    32768
+};
+
+int32_t Effects_log2(uint32_t x) {
+    int32_t exp = 31 - __builtin_clz(x);
+    uint32_t segStart = x >> (exp - 6);
+    uint32_t i = segStart & 0x3F;
+    int32_t log = (int32_t)gLogTab[i];
+    int32_t logEnd = (int32_t)gLogTab[i+1];
+    segStart <<= exp - 6;
+
+    return (exp << 15) + log + (((x - segStart) * (logEnd - log)) >> (exp - 6));
+}
+
+// gExpTab[i] = (2^(i>>6)) << 22
+static const uint32_t gExpTab[] = {
+            4194304, 4239977, 4286147, 4332820,
+            4380002, 4427697, 4475911, 4524651,
+            4573921, 4623728, 4674077, 4724974,
+            4776426, 4828438, 4881016, 4934167,
+            4987896, 5042211, 5097117, 5152621,
+            5208729, 5265449, 5322786, 5380747,
+            5439339, 5498570, 5558445, 5618973,
+            5680159, 5742012, 5804539, 5867746,
+            5931642, 5996233, 6061528, 6127533,
+            6194258, 6261709, 6329894, 6398822,
+            6468501, 6538938, 6610143, 6682122,
+            6754886, 6828442, 6902799, 6977965,
+            7053950, 7130763, 7208412, 7286906,
+            7366255, 7446469, 7527555, 7609525,
+            7692387, 7776152, 7860829, 7946428,
+            8032959, 8120432, 8208857, 8298246,
+            8388608
+};
+
+
+uint32_t Effects_exp2(int32_t x) {
+    int32_t i = x >> 15;
+    assert(i < 32);
+    x &= (1 << 15) - 1;
+    int32_t j = x >> 9;
+    x &= (1 << 9) - 1;
+    uint32_t exp = gExpTab[j];
+    uint32_t expEnd = gExpTab[j+1];
+
+    return ((exp << 9) + (expEnd - exp) * x) >> (31 - i);
+}
+
+
+int16_t Effects_MillibelsToLinear16 (int32_t nGain)
+{
+    nGain = ((nGain + MB_TO_LIN_K1) << 15 ) / MB_TO_LIN_K2;
+    uint32_t exp2 = Effects_exp2(nGain);
+
+    if (exp2 > 32767) exp2 = 32767;
+
+    return (int16_t)exp2;
+}
+
+
+int16_t Effects_Linear16ToMillibels (int32_t nGain)
+{
+    return (int16_t)(((MB_TO_LIN_K2*Effects_log2(nGain))>>15)-MB_TO_LIN_K1);
+}
+
+
+int32_t Effects_Sqrt(int32_t in)
+{
+    int32_t tmp;
+    int32_t out = 0;
+    int32_t i;
+    int32_t j;
+
+
+    if (in == 0) return 0;
+
+    if (in >= 0x10000000)
+    {
+        out = 0x4000;
+        in -= 0x10000000;
+    }
+
+    j = 32 - __builtin_clz(in);
+
+    if (j & 1) j++;
+    j >>= 1;
+
+    for (i = j; i > 0; i--) {
+        tmp = (out << i) + (1 << ((i - 1)*2));
+        if (in >= tmp)
+        {
+            out += 1 << (i-1);
+            in -= tmp;
+        }
+    }
+
+    return out;
+}
+
diff --git a/media/libeffects/testlibs/EffectsMath.h b/media/libeffects/testlibs/EffectsMath.h
new file mode 100644
index 0000000..2a44399
--- /dev/null
+++ b/media/libeffects/testlibs/EffectsMath.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2008 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 ANDROID_EFFECTSMATH_H_
+#define ANDROID_EFFECTSMATH_H_
+
+#include <stdint.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/** coefs for pan, generates sin, cos */
+#define COEFF_PAN_G2    -27146    /* -0.82842712474619 = 2 - 4/sqrt(2) */
+#define COEFF_PAN_G0    23170     /* 0.707106781186547 = 1/sqrt(2) */
+
+/*
+coefficients for approximating
+2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3
+where x is a int.frac number representing number of octaves.
+Actually, we approximate only the 2^(frac) using the power series
+and implement the 2^(int) as a shift, so that
+2^x == 2^(int.frac) == 2^(int) * 2^(fract)
+    == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int)
+
+The gn2toX.. were generated using a best fit for a 3rd
+order polynomial, instead of taking the coefficients from
+a truncated Taylor (or Maclaurin?) series.
+*/
+
+#define GN2_TO_X0    32768    /*    1                    */
+#define GN2_TO_X1    22833    /*    0.696807861328125    */
+#define GN2_TO_X2    7344    /*    0.22412109375        */
+#define GN2_TO_X3    2588    /*    0.0789794921875        */
+
+/*----------------------------------------------------------------------------
+ * Fixed Point Math
+ *----------------------------------------------------------------------------
+ * These macros are used for fixed point multiplies. If the processor
+ * supports fixed point multiplies, replace these macros with inline
+ * assembly code to improve performance.
+ *----------------------------------------------------------------------------
+*/
+
+/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */
+#define FMUL_15x15(a,b) \
+    /*lint -e(704) <avoid multiply for performance>*/ \
+    (((int32_t)(a) * (int32_t)(b)) >> 15)
+
+/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */
+#define FMUL_7x7(a,b) \
+    /*lint -e(704) <avoid multiply for performance>*/ \
+    (((int32_t)(a) * (int32_t)(b) ) << 1)
+
+/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */
+#define FMUL_8x8(a,b) \
+    /*lint -e(704) <avoid multiply for performance>*/ \
+    (((int32_t)(a) * (int32_t)(b) ) >> 1)
+
+/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */
+#define FMUL_8x15(a,b) \
+    /*lint -e(704) <avoid divide for performance>*/ \
+    (((int32_t)((a) << 7) * (int32_t)(b)) >> 15)
+
+/* macros for fractional phase accumulator */
+/*
+Note: changed the _U32 to _I32 on 03/14/02. This should not
+affect the phase calculations, and should allow us to reuse these
+macros for other audio sample related math.
+*/
+#define HARDWARE_BIT_WIDTH        32
+
+#define NUM_PHASE_INT_BITS        1
+#define NUM_PHASE_FRAC_BITS       15
+
+#define PHASE_FRAC_MASK           (uint32_t) ((0x1L << NUM_PHASE_FRAC_BITS) -1)
+
+#define GET_PHASE_INT_PART(x)     (uint32_t)((uint32_t)(x) >> NUM_PHASE_FRAC_BITS)
+#define GET_PHASE_FRAC_PART(x)    (uint32_t)((uint32_t)(x) & PHASE_FRAC_MASK)
+
+#define DEFAULT_PHASE_FRAC        0
+#define DEFAULT_PHASE_INT         0
+
+/*
+Linear interpolation calculates:
+output = (1-frac) * sample[n] + (frac) * sample[n+1]
+
+where conceptually    0 <= frac < 1
+
+For a fixed point implementation, frac is actually an integer value
+with an implied binary point one position to the left. The value of
+one (unity) is given by PHASE_ONE
+one half and one quarter are useful for 4-point linear interp.
+*/
+#define PHASE_ONE                (int32_t) (0x1L << NUM_PHASE_FRAC_BITS)
+
+/*
+ Multiply the signed audio sample by the unsigned fraction.
+-  a is the signed audio sample
+-  b is the unsigned fraction (cast to signed int as long as coef
+    uses (n-1) or less bits, where n == hardware bit width)
+*/
+#define MULT_AUDIO_COEF(audio,coef)         /*lint -e704 <avoid divide for performance>*/ \
+            (int32_t)(                                    \
+            (                                            \
+                ((int32_t)(audio)) * ((int32_t)(coef))    \
+            )                                            \
+            >> NUM_PHASE_FRAC_BITS                        \
+                                        )                \
+                                        /* lint +704 <restore checking>*/
+
+/* wet / dry calculation macros */
+#define NUM_WET_DRY_FRAC_BITS       7    // 15
+#define NUM_WET_DRY_INT_BITS        9    // 1
+
+/* define a 1.0 */
+#define WET_DRY_ONE                 (int32_t) ((0x1L << NUM_WET_DRY_FRAC_BITS))
+#define WET_DRY_MINUS_ONE           (int32_t) (~WET_DRY_ONE)
+#define WET_DRY_FULL_SCALE          (int32_t) (WET_DRY_ONE - 1)
+
+#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) <avoid divide for performance>*/ \
+            (int32_t)(                                        \
+            (                                                \
+                ((int32_t)(audio)) * ((int32_t)(coef))        \
+            )                                                \
+            >> NUM_WET_DRY_FRAC_BITS                        \
+                                                     )
+
+/* Envelope 1 (EG1) calculation macros */
+#define    NUM_EG1_INT_BITS          1
+#define NUM_EG1_FRAC_BITS            15
+
+/* the max positive gain used in the synth for EG1 */
+/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas
+converter, otherwise, the values we read from the .eas file are bogus. */
+#define SYNTH_FULL_SCALE_EG1_GAIN    (int32_t) ((0x1L << NUM_EG1_FRAC_BITS) -1)
+
+/* define a 1.0 */
+#define EG1_ONE                      (int32_t) ((0x1L << NUM_EG1_FRAC_BITS))
+#define EG1_MINUS_ONE                (int32_t) (~SYNTH_FULL_SCALE_EG1_GAIN)
+
+#define EG1_HALF                     (int32_t) (EG1_ONE/2)
+#define EG1_MINUS_HALF               (int32_t) (EG1_MINUS_ONE/2)
+
+/*
+We implement the EG1 using a linear gain value, which means that the
+attack segment is handled by incrementing (adding) the linear gain.
+However, EG1 treats the Decay, Sustain, and Release differently than
+the Attack portion. For Decay, Sustain, and Release, the gain is
+linear on dB scale, which is equivalent to exponential damping on
+a linear scale. Because we use a linear gain for EG1, we implement
+the Decay and Release as multiplication (instead of incrementing
+as we did for the attack segment).
+Therefore, we need the following macro to implement the multiplication
+(i.e., exponential damping) during the Decay and Release segments of
+the EG1
+*/
+#define MULT_EG1_EG1(gain,damping)        /*lint -e(704) <avoid divide for performance>*/ \
+            (int32_t)(                                        \
+            (                                                \
+                ((int32_t)(gain)) * ((int32_t)(damping))    \
+            )                                                \
+            >> NUM_EG1_FRAC_BITS                            \
+                                        )
+
+// Use the following macro specifically for the filter, when multiplying
+// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow
+// in certain conditions because we store b1 as a 1.15 value.
+// Instead, we could store b1 as b1p (b1' == b1 "prime") where
+// b1p == b1/2, thus ensuring no potential overflow for b1p because
+// 0 <= |b1p| < 1
+// However, during the filter calculation, we must account for the fact
+// that we are using b1p instead of b1, and thereby multiply by
+// an extra factor of 2. Rather than multiply by an extra factor of 2,
+// we can instead shift the result right by one less, hence the
+// modified shift right value of (NUM_EG1_FRAC_BITS -1)
+#define MULT_EG1_EG1_X2(gain,damping)         /*lint -e(702) <avoid divide for performance>*/ \
+            (int32_t)(                                        \
+            (                                                \
+                ((int32_t)(gain)) * ((int32_t)(damping))    \
+            )                                                \
+            >> (NUM_EG1_FRAC_BITS -1)                        \
+                                        )
+
+#define SATURATE_EG1(x)        /*lint -e{734} saturation operation */                \
+    ((int32_t)(x) > SYNTH_FULL_SCALE_EG1_GAIN)    ? (SYNTH_FULL_SCALE_EG1_GAIN) :    \
+    ((int32_t)(x) < EG1_MINUS_ONE)                ? (EG1_MINUS_ONE) :    (x);
+
+
+/* use "digital cents" == "dents" instead of cents */
+/* we coudl re-use the phase frac macros, but if we do,
+we must change the phase macros to cast to _I32 instead of _U32,
+because using a _U32 cast causes problems when shifting the exponent
+for the 2^x calculation, because right shift a negative values MUST
+be sign extended, or else the 2^x calculation is wrong */
+
+/* use "digital cents" == "dents" instead of cents */
+#define NUM_DENTS_FRAC_BITS        12
+#define NUM_DENTS_INT_BITS         (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS)
+
+#define DENTS_FRAC_MASK            (int32_t) ((0x1L << NUM_DENTS_FRAC_BITS) -1)
+
+#define GET_DENTS_INT_PART(x)        /*lint -e(704) <avoid divide for performance>*/    \
+                            (int32_t)((int32_t)(x) >> NUM_DENTS_FRAC_BITS)
+
+#define GET_DENTS_FRAC_PART(x)     (int32_t)((int32_t)(x) & DENTS_FRAC_MASK)
+
+#define DENTS_ONE                  (int32_t) (0x1L << NUM_DENTS_FRAC_BITS)
+
+/* use CENTS_TO_DENTS to convert a value in cents to dents */
+#define CENTS_TO_DENTS (int32_t) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L)                            \
+
+
+/*
+For gain, the LFO generates a value that modulates in terms
+of dB. However, we use a linear gain value, so we must convert
+the LFO value in dB to a linear gain. Normally, we would use
+linear gain = 10^x, where x = LFO value in dB / 20.
+Instead, we implement 10^x using our 2^x approximation.
+because
+
+  10^x = 2^(log2(10^x)) = 2^(x * log2(10))
+
+so we need to multiply by log2(10) which is just a constant.
+Ah, but just wait -- our 2^x actually doesn't exactly implement
+2^x, but it actually assumes that the input is in cents, and within
+the 2^x approximation converts its input from cents to octaves
+by dividing its input by 1200.
+
+So, in order to convert the LFO gain value in dB to something
+that our existing 2^x approximation can use, multiply the LFO gain
+by log2(10) * 1200 / 20
+
+The divide by 20 helps convert dB to linear gain, and we might
+as well incorporate that operation into this conversion.
+Of course, we need to keep some fractional bits, so multiply
+the constant by NUM_EG1_FRAC_BITS
+*/
+
+/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */
+#if 0
+#define    DOUBLE_LOG2_10    (double) (3.32192809488736)    /* log2(10) */
+
+#define    DOUBLE_LFO_GAIN_TO_CENTS    (double)                \
+    (                                                        \
+                (DOUBLE_LOG2_10) *                            \
+                1200.0    /                                    \
+                20.0                                        \
+    )
+
+#define    LFO_GAIN_TO_CENTS    (int32_t)                        \
+    (                                                        \
+                DOUBLE_LFO_GAIN_TO_CENTS *                    \
+                (0x1L << NUM_EG1_FRAC_BITS)                    \
+    )
+#endif
+
+#define LFO_GAIN_TO_CENTS (int32_t) (1671981156L >> (23 - NUM_EG1_FRAC_BITS))
+
+
+#define MULT_DENTS_COEF(dents,coef)     /*lint -e704 <avoid divide for performance>*/    \
+            (int32_t)(                                    \
+            (                                            \
+                ((int32_t)(dents)) * ((int32_t)(coef))    \
+            )                                            \
+            >> NUM_DENTS_FRAC_BITS                        \
+                                        )                \
+                                        /* lint +e704 <restore checking>*/
+
+
+/* we use 16-bits in the PC per audio sample */
+#define BITS_PER_AUDIO_SAMPLE    16
+
+/* we define 1 as 1.0 - 1 LSbit */
+#define DISTORTION_ONE           (int32_t)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1)
+#define DISTORTION_MINUS_ONE     (int32_t)(~DISTORTION_ONE)
+
+/* drive coef is given as int.frac */
+#define NUM_DRIVE_COEF_INT_BITS  1
+#define NUM_DRIVE_COEF_FRAC_BITS 4
+
+#define MULT_AUDIO_DRIVE(audio,drive)         /*lint -e(702) <avoid divide for performance>*/ \
+            (int32_t)    (                                \
+            (                                            \
+                ((int32_t)(audio)) * ((int32_t)(drive))    \
+            )                                            \
+            >> NUM_DRIVE_COEF_FRAC_BITS                    \
+                                                )
+
+#define MULT_AUDIO_AUDIO(audio1,audio2)         /*lint -e(702) <avoid divide for performance>*/ \
+            (int32_t)    (                                    \
+            (                                                \
+                ((int32_t)(audio1)) * ((int32_t)(audio2))    \
+            )                                                \
+            >> (BITS_PER_AUDIO_SAMPLE-1)                    \
+                                                    )
+
+#define SATURATE(x)                                                            \
+    ((((int32_t)(x)) > DISTORTION_ONE)        ? (DISTORTION_ONE) :            \
+    (((int32_t)(x)) < DISTORTION_MINUS_ONE)    ? (DISTORTION_MINUS_ONE) :    ((int32_t)(x)));
+
+
+/*----------------------------------------------------------------------------
+ * Effects_log2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Fixed-point log2 function.
+ *
+ * Inputs:
+ * Input is interpreted as an integer (should not be 0).
+ *
+ * Outputs:
+ * Output is in 15-bit precision.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int32_t Effects_log2(uint32_t x);
+
+/*----------------------------------------------------------------------------
+ * Effects_exp2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Fixed-point radix-2 exponent.
+ *
+ * Inputs:
+ * Input is in 15-bit precision. Must be non-negative and less than 32.
+ *
+ * Outputs:
+ * Output is an integer.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+uint32_t Effects_exp2(int32_t x);
+
+/*----------------------------------------------------------------------------
+ * Effects_MillibelsToLinear16()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform gain in millibels to linear gain multiplier:
+ *
+ * mB = 2000*log(lin/32767)
+ *    => lin = 2^((mB+2000*log(32767))/2000*log(2))
+ *    => lin = Effects_exp2(((mB + K1) << 15) / K2)
+ * with:
+ *    K1 = 2000*log(32767) and K2 = 2000*log(2)
+ *
+ * Inputs:
+ * nGain - log scale value in millibels.
+ *
+ * Outputs:
+ * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+#define MB_TO_LIN_K1 9031
+#define MB_TO_LIN_K2 602
+int16_t Effects_MillibelsToLinear16 (int32_t nGain);
+
+/*----------------------------------------------------------------------------
+ * Effects_Linear16ToMillibels()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform linear gain multiplier to millibels
+ *  mB = 2000*log(lin/32767)
+ *     = 2000*log(2)*log2(lin)-2000*log(32767)
+ *    => mB = K1*Effects_log2(lin) + K2
+ * with:
+ *    K1 = 2000*log(2) and K2 = -2000*log(32767)
+ *
+ * Inputs:
+ * nGain - linear multiplier ranging form 0 to 32767 (corresponding to [0 1] gain range).
+ *
+ * Outputs:
+ * Returns a 16-bit log value expressed in milllibels.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int16_t Effects_Linear16ToMillibels (int32_t nGain);
+
+/*----------------------------------------------------------------------------
+ * Effects_Sqrt()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the square root of the argument given.
+ *
+ * Inputs:
+ * in - positive number in the range 0 - 2^28
+ *
+ * Outputs:
+ * Returned value: square root of in.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int32_t Effects_Sqrt(int32_t in);
+
+#if __cplusplus
+}  // extern "C"
+#endif
+
+#endif /*ANDROID_EFFECTSMATH_H_*/
+
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
new file mode 100644
index 0000000..48b45ff
--- /dev/null
+++ b/media/libeffects/visualizer/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Visualizer library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectVisualizer.cpp
+
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libvisualizer
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+	$(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
new file mode 100644
index 0000000..8ab57c9
--- /dev/null
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2010 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_TAG "Visualizer"
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <media/EffectVisualizerApi.h>
+
+namespace android {
+
+// effect_interface_t interface implementation for visualizer effect
+extern "C" const struct effect_interface_s gVisualizerInterface;
+
+// Google Visualizer UUID: d069d9e0-8329-11df-9168-0002a5d5c51b
+const effect_descriptor_t gVisualizerDescriptor = {
+        {0xe46b26a0, 0xdddd, 0x11db, 0x8afd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+        {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+        EFFECT_API_VERSION,
+        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST),
+        0, // TODO
+        1,
+        "Visualizer",
+        "Google Inc.",
+};
+
+enum visualizer_state_e {
+    VISUALIZER_STATE_UNINITIALIZED,
+    VISUALIZER_STATE_INITIALIZED,
+    VISUALIZER_STATE_ACTIVE,
+};
+
+struct VisualizerContext {
+    const struct effect_interface_s *mItfe;
+    effect_config_t mConfig;
+    uint32_t mState;
+    uint32_t mCaptureIdx;
+    uint32_t mCaptureSize;
+    uint32_t mCurrentBuf;
+    uint8_t mCaptureBuf[2][VISUALIZER_CAPTURE_SIZE_MAX];
+};
+
+
+//
+//--- Local functions
+//
+
+void Visualizer_reset(VisualizerContext *pContext)
+{
+    pContext->mCaptureIdx = 0;
+    pContext->mCurrentBuf = 0;
+    memset(pContext->mCaptureBuf[0], 0, VISUALIZER_CAPTURE_SIZE_MAX);
+    memset(pContext->mCaptureBuf[1], 0, VISUALIZER_CAPTURE_SIZE_MAX);
+}
+
+//----------------------------------------------------------------------------
+// Visualizer_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+//  pContext:   effect engine context
+//  pConfig:    pointer to effect_config_t structure holding input and output
+//      configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Visualizer_configure(VisualizerContext *pContext, effect_config_t *pConfig)
+{
+    LOGV("Visualizer_configure start");
+
+    if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL;
+    if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL;
+    if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL;
+    if (pConfig->inputCfg.channels != CHANNEL_STEREO) return -EINVAL;
+    if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
+            pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
+    if (pConfig->inputCfg.format != SAMPLE_FORMAT_PCM_S15) return -EINVAL;
+
+    memcpy(&pContext->mConfig, pConfig, sizeof(effect_config_t));
+
+    Visualizer_reset(pContext);
+
+    return 0;
+}
+
+
+//----------------------------------------------------------------------------
+// Visualizer_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration.
+//
+// Inputs:
+//  pContext:   effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Visualizer_init(VisualizerContext *pContext)
+{
+    pContext->mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+    pContext->mConfig.inputCfg.channels = CHANNEL_STEREO;
+    pContext->mConfig.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+    pContext->mConfig.inputCfg.samplingRate = 44100;
+    pContext->mConfig.inputCfg.bufferProvider.getBuffer = NULL;
+    pContext->mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
+    pContext->mConfig.inputCfg.bufferProvider.cookie = NULL;
+    pContext->mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
+    pContext->mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+    pContext->mConfig.outputCfg.channels = CHANNEL_STEREO;
+    pContext->mConfig.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+    pContext->mConfig.outputCfg.samplingRate = 44100;
+    pContext->mConfig.outputCfg.bufferProvider.getBuffer = NULL;
+    pContext->mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
+    pContext->mConfig.outputCfg.bufferProvider.cookie = NULL;
+    pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+    pContext->mCaptureSize = VISUALIZER_CAPTURE_SIZE_MAX;
+
+    Visualizer_configure(pContext, &pContext->mConfig);
+
+    return 0;
+}
+
+//
+//--- Effect Library Interface Implementation
+//
+
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
+    *pNumEffects = 1;
+    return 0;
+}
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+    if (pDescriptor == NULL) {
+        return -EINVAL;
+    }
+    if (index > 0) {
+        return -EINVAL;
+    }
+    memcpy(pDescriptor, &gVisualizerDescriptor, sizeof(effect_descriptor_t));
+    return 0;
+}
+
+extern "C" int EffectCreate(effect_uuid_t *uuid,
+        int32_t sessionId,
+        int32_t ioId,
+        effect_interface_t *pInterface) {
+    int ret;
+    int i;
+
+    if (pInterface == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+
+    if (memcmp(uuid, &gVisualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
+        return -EINVAL;
+    }
+
+    VisualizerContext *pContext = new VisualizerContext;
+
+    pContext->mItfe = &gVisualizerInterface;
+    pContext->mState = VISUALIZER_STATE_UNINITIALIZED;
+
+    ret = Visualizer_init(pContext);
+    if (ret < 0) {
+        LOGW("EffectCreate() init failed");
+        delete pContext;
+        return ret;
+    }
+
+    *pInterface = (effect_interface_t)pContext;
+
+    pContext->mState = VISUALIZER_STATE_INITIALIZED;
+
+    LOGV("EffectCreate %p", pContext);
+
+    return 0;
+
+}
+
+extern "C" int EffectRelease(effect_interface_t interface) {
+    VisualizerContext * pContext = (VisualizerContext *)interface;
+
+    LOGV("EffectRelease %p", interface);
+    if (pContext == NULL) {
+        return -EINVAL;
+    }
+    pContext->mState = VISUALIZER_STATE_UNINITIALIZED;
+    delete pContext;
+
+    return 0;
+}
+
+//
+//--- Effect Control Interface Implementation
+//
+
+static inline int16_t clamp16(int32_t sample)
+{
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
+extern "C" int Visualizer_process(
+        effect_interface_t self,audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+    android::VisualizerContext * pContext = (android::VisualizerContext *)self;
+
+    if (pContext == NULL) {
+        return -EINVAL;
+    }
+
+    if (inBuffer == NULL || inBuffer->raw == NULL ||
+        outBuffer == NULL || outBuffer->raw == NULL ||
+        inBuffer->frameCount != outBuffer->frameCount ||
+        inBuffer->frameCount == 0) {
+        return -EINVAL;
+    }
+
+    // all code below assumes stereo 16 bit PCM output and input
+    uint32_t captIdx;
+    uint32_t inIdx;
+    uint8_t *buf = pContext->mCaptureBuf[pContext->mCurrentBuf];
+    for (inIdx = 0, captIdx = pContext->mCaptureIdx;
+         inIdx < inBuffer->frameCount && captIdx < pContext->mCaptureSize;
+         inIdx++, captIdx++) {
+        int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1];
+        smp = (smp + (1 << 8)) >> 9;
+        buf[captIdx] = ((uint8_t)smp)^0x80;
+    }
+    pContext->mCaptureIdx = captIdx;
+
+    // go to next buffer when buffer full
+    if (pContext->mCaptureIdx == pContext->mCaptureSize) {
+        pContext->mCurrentBuf ^= 1;
+        pContext->mCaptureIdx = 0;
+    }
+
+    if (inBuffer->raw != outBuffer->raw) {
+        if (pContext->mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+            for (size_t i = 0; i < outBuffer->frameCount*2; i++) {
+                outBuffer->s16[i] = clamp16(outBuffer->s16[i] + inBuffer->s16[i]);
+            }
+        } else {
+            memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * 2 * sizeof(int16_t));
+        }
+    }
+    if (pContext->mState != VISUALIZER_STATE_ACTIVE) {
+        return -ENODATA;
+    }
+    return 0;
+}   // end Visualizer_process
+
+extern "C" int Visualizer_command(effect_interface_t self, uint32_t cmdCode, uint32_t cmdSize,
+        void *pCmdData, uint32_t *replySize, void *pReplyData) {
+
+    android::VisualizerContext * pContext = (android::VisualizerContext *)self;
+    int retsize;
+
+    if (pContext == NULL || pContext->mState == VISUALIZER_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+
+//    LOGV("Visualizer_command command %d cmdSize %d",cmdCode, cmdSize);
+
+    switch (cmdCode) {
+    case EFFECT_CMD_INIT:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Visualizer_init(pContext);
+        break;
+    case EFFECT_CMD_CONFIGURE:
+        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+                || pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Visualizer_configure(pContext,
+                (effect_config_t *) pCmdData);
+        break;
+    case EFFECT_CMD_RESET:
+        Visualizer_reset(pContext);
+        break;
+    case EFFECT_CMD_ENABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pContext->mState != VISUALIZER_STATE_INITIALIZED) {
+            return -ENOSYS;
+        }
+        pContext->mState = VISUALIZER_STATE_ACTIVE;
+        LOGV("EFFECT_CMD_ENABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
+    case EFFECT_CMD_DISABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pContext->mState != VISUALIZER_STATE_ACTIVE) {
+            return -ENOSYS;
+        }
+        pContext->mState = VISUALIZER_STATE_INITIALIZED;
+        LOGV("EFFECT_CMD_DISABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
+    case EFFECT_CMD_GET_PARAM: {
+        if (pCmdData == NULL ||
+            cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t)) ||
+            pReplyData == NULL ||
+            *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t))) {
+            return -EINVAL;
+        }
+        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(uint32_t));
+        effect_param_t *p = (effect_param_t *)pReplyData;
+        p->status = 0;
+        *replySize = sizeof(effect_param_t) + sizeof(uint32_t);
+        if (p->psize != sizeof(uint32_t) ||
+            *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) {
+            p->status = -EINVAL;
+            break;
+        }
+        LOGV("get mCaptureSize = %d", pContext->mCaptureSize);
+        *((uint32_t *)p->data + 1) = pContext->mCaptureSize;
+        p->vsize = sizeof(uint32_t);
+        *replySize += sizeof(uint32_t);
+        } break;
+    case EFFECT_CMD_SET_PARAM: {
+        if (pCmdData == NULL ||
+            cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t)) ||
+            pReplyData == NULL || *replySize != sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        *(int32_t *)pReplyData = 0;
+        effect_param_t *p = (effect_param_t *)pCmdData;
+        if (p->psize != sizeof(uint32_t) ||
+            p->vsize != sizeof(uint32_t) ||
+            *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) {
+            *(int32_t *)pReplyData = -EINVAL;
+            break;;
+        }
+        pContext->mCaptureSize = *((uint32_t *)p->data + 1);
+        LOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+        } break;
+    case EFFECT_CMD_SET_DEVICE:
+    case EFFECT_CMD_SET_VOLUME:
+    case EFFECT_CMD_SET_AUDIO_MODE:
+        break;
+
+
+    case VISU_CMD_CAPTURE:
+        if (pReplyData == NULL || *replySize != (int)pContext->mCaptureSize) {
+            LOGV("VISU_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d",
+                    *replySize, pContext->mCaptureSize);
+            return -EINVAL;
+        }
+        if (pContext->mState == VISUALIZER_STATE_ACTIVE) {
+            memcpy(pReplyData,
+                   pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1],
+                   pContext->mCaptureSize);
+        } else {
+            memset(pReplyData, 0x80, pContext->mCaptureSize);
+        }
+        break;
+
+    default:
+        LOGW("Visualizer_command invalid command %d",cmdCode);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+// effect_interface_t interface implementation for visualizer effect
+const struct effect_interface_s gVisualizerInterface = {
+        Visualizer_process,
+        Visualizer_command
+};
+
+} // namespace
+
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 3adabcc..977e6be 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -12,6 +12,7 @@
     mediaplayer.cpp \
     IMediaPlayerService.cpp \
     IMediaPlayerClient.cpp \
+    IMediaRecorderClient.cpp \
     IMediaPlayer.cpp \
     IMediaRecorder.cpp \
     Metadata.cpp \
@@ -26,7 +27,11 @@
     MediaScannerClient.cpp \
     autodetect.cpp \
     IMediaDeathNotifier.cpp \
-    MediaProfiles.cpp
+    MediaProfiles.cpp \
+    IEffect.cpp \
+    IEffectClient.cpp \
+    AudioEffect.cpp \
+    Visualizer.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
new file mode 100644
index 0000000..3cdf48a
--- /dev/null
+++ b/media/libmedia/AudioEffect.cpp
@@ -0,0 +1,462 @@
+/*
+**
+** Copyright 2010, 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 "AudioEffect"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <private/media/AudioEffectShared.h>
+#include <media/AudioEffect.h>
+
+#include <utils/Log.h>
+#include <cutils/atomic.h>
+#include <binder/IPCThreadState.h>
+
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+AudioEffect::AudioEffect()
+    : mStatus(NO_INIT)
+{
+}
+
+
+AudioEffect::AudioEffect(const effect_uuid_t *type,
+                const effect_uuid_t *uuid,
+                int32_t priority,
+                effect_callback_t cbf,
+                void* user,
+                int sessionId,
+                audio_io_handle_t output
+                )
+    : mStatus(NO_INIT)
+{
+    mStatus = set(type, uuid, priority, cbf, user, sessionId, output);
+}
+
+AudioEffect::AudioEffect(const char *typeStr,
+                const char *uuidStr,
+                int32_t priority,
+                effect_callback_t cbf,
+                void* user,
+                int sessionId,
+                audio_io_handle_t output
+                )
+    : mStatus(NO_INIT)
+{
+    effect_uuid_t type;
+    effect_uuid_t *pType = NULL;
+    effect_uuid_t uuid;
+    effect_uuid_t *pUuid = NULL;
+
+    LOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
+
+    if (typeStr != NULL) {
+        if (stringToGuid(typeStr, &type) == NO_ERROR) {
+            pType = &type;
+        }
+    }
+
+    if (uuidStr != NULL) {
+        if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
+            pUuid = &uuid;
+        }
+    }
+
+    mStatus = set(pType, pUuid, priority, cbf, user, sessionId, output);
+}
+
+status_t AudioEffect::set(const effect_uuid_t *type,
+                const effect_uuid_t *uuid,
+                int32_t priority,
+                effect_callback_t cbf,
+                void* user,
+                int sessionId,
+                audio_io_handle_t output)
+{
+    sp<IEffect> iEffect;
+    sp<IMemory> cblk;
+    int enabled;
+
+    LOGV("set %p mUserData: %p", this, user);
+
+    if (mIEffect != 0) {
+        LOGW("Effect already in use");
+        return INVALID_OPERATION;
+    }
+
+    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+    if (audioFlinger == 0) {
+        LOGE("set(): Could not get audioflinger");
+        return NO_INIT;
+    }
+
+    if (type == NULL && uuid == NULL) {
+        LOGW("Must specify at least type or uuid");
+        return BAD_VALUE;
+    }
+
+    mPriority = priority;
+    mCbf = cbf;
+    mUserData = user;
+    mSessionId = sessionId;
+
+    memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
+    memcpy(&mDescriptor.type, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
+    memcpy(&mDescriptor.uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
+
+    if (type != NULL) {
+        memcpy(&mDescriptor.type, type, sizeof(effect_uuid_t));
+    }
+    if (uuid != NULL) {
+        memcpy(&mDescriptor.uuid, uuid, sizeof(effect_uuid_t));
+    }
+
+    mIEffectClient = new EffectClient(this);
+
+    iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,
+            mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);
+
+    if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
+        LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
+        return mStatus;
+    }
+
+    mEnabled = (volatile int32_t)enabled;
+
+    mIEffect = iEffect;
+    cblk = iEffect->getCblk();
+    if (cblk == 0) {
+        mStatus = NO_INIT;
+        LOGE("Could not get control block");
+        return mStatus;
+    }
+
+    mIEffect = iEffect;
+    mCblkMemory = cblk;
+    mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
+    int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
+    mCblk->buffer = (uint8_t *)mCblk + bufOffset;
+
+    iEffect->asBinder()->linkToDeath(mIEffectClient);
+    LOGV("set() %p OK effect: %s id: %d status %d enabled %d, ", this, mDescriptor.name, mId, mStatus, mEnabled);
+
+    return mStatus;
+}
+
+
+AudioEffect::~AudioEffect()
+{
+    LOGV("Destructor %p", this);
+
+    if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
+        setEnabled(false);
+        if (mIEffect != NULL) {
+            mIEffect->disconnect();
+            mIEffect->asBinder()->unlinkToDeath(mIEffectClient);
+        }
+         IPCThreadState::self()->flushCommands();
+    }
+    mIEffect.clear();
+    mIEffectClient.clear();
+    mCblkMemory.clear();
+}
+
+
+status_t AudioEffect::initCheck() const
+{
+    return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+effect_descriptor_t AudioEffect::descriptor() const
+{
+    return mDescriptor;
+}
+
+bool AudioEffect::getEnabled() const
+{
+    return (mEnabled != 0);
+}
+
+status_t AudioEffect::setEnabled(bool enabled)
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+
+    if (enabled) {
+        LOGV("enable %p", this);
+        if (android_atomic_or(1, &mEnabled) == 0) {
+           return mIEffect->enable();
+        }
+    } else {
+        LOGV("disable %p", this);
+        if (android_atomic_and(~1, &mEnabled) == 1) {
+           return mIEffect->disable();
+        }
+    }
+    return INVALID_OPERATION;
+}
+
+status_t AudioEffect::command(uint32_t cmdCode,
+                              uint32_t cmdSize,
+                              void *cmdData,
+                              uint32_t *replySize,
+                              void *replyData)
+{
+    if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+        return INVALID_OPERATION;
+    }
+
+    return mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
+}
+
+
+status_t AudioEffect::setParameter(effect_param_t *param)
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+
+    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+        return BAD_VALUE;
+    }
+
+    uint32_t size = sizeof(int);
+    uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+    LOGV("setParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
+
+    return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size, &param->status);
+}
+
+status_t AudioEffect::setParameterDeferred(effect_param_t *param)
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+
+    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mCblk->lock);
+
+    int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+    int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
+
+    if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
+        return NO_MEMORY;
+    }
+    int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
+    *p++ = size;
+    memcpy(p, param, sizeof(effect_param_t) + psize);
+    mCblk->clientIndex += size;
+
+    return NO_ERROR;
+}
+
+status_t AudioEffect::setParameterCommit()
+{
+    if (mStatus != NO_ERROR) {
+        return INVALID_OPERATION;
+    }
+
+    Mutex::Autolock _l(mCblk->lock);
+    if (mCblk->clientIndex == 0) {
+        return INVALID_OPERATION;
+    }
+    uint32_t size = 0;
+    return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
+}
+
+status_t AudioEffect::getParameter(effect_param_t *param)
+{
+    if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+        return INVALID_OPERATION;
+    }
+
+    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+        return BAD_VALUE;
+    }
+
+    LOGV("getParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
+
+    uint32_t psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+    return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param, &psize, param);
+}
+
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::binderDied()
+{
+    LOGW("IEffect died");
+    mStatus = NO_INIT;
+    if (mCbf) {
+        status_t status = DEAD_OBJECT;
+        mCbf(EVENT_ERROR, mUserData, &status);
+    }
+    mIEffect.clear();
+}
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::controlStatusChanged(bool controlGranted)
+{
+    LOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf, mUserData);
+    if (controlGranted) {
+        if (mStatus == ALREADY_EXISTS) {
+            mStatus = NO_ERROR;
+        }
+    } else {
+        if (mStatus == NO_ERROR) {
+            mStatus = ALREADY_EXISTS;
+        }
+    }
+    if (mCbf) {
+        mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
+    }
+}
+
+void AudioEffect::enableStatusChanged(bool enabled)
+{
+    LOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
+    if (mStatus == ALREADY_EXISTS) {
+        mEnabled = enabled;
+        if (mCbf) {
+            mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
+        }
+    }
+}
+
+void AudioEffect::commandExecuted(uint32_t cmdCode,
+                                  uint32_t cmdSize,
+                                  void *cmdData,
+                                  uint32_t replySize,
+                                  void *replyData)
+{
+    if (cmdData == NULL || replyData == NULL) {
+        return;
+    }
+
+    if (mCbf && cmdCode == EFFECT_CMD_SET_PARAM) {
+        effect_param_t *cmd = (effect_param_t *)cmdData;
+        cmd->status = *(int32_t *)replyData;
+        mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
+    }
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioEffect::loadEffectLibrary(const char *libPath, int *handle)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->loadEffectLibrary(libPath, handle);
+}
+
+status_t AudioEffect::unloadEffectLibrary(int handle)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->unloadEffectLibrary(handle);
+}
+
+status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->queryNumberEffects(numEffects);
+}
+
+status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->queryEffect(index, descriptor);
+}
+
+status_t AudioEffect::getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor)
+{
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+    return af->getEffectDescriptor(uuid, descriptor);
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
+{
+    if (str == NULL || guid == NULL) {
+        return BAD_VALUE;
+    }
+
+    int tmp[10];
+
+    if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+            tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
+        return BAD_VALUE;
+    }
+    guid->timeLow = (uint32_t)tmp[0];
+    guid->timeMid = (uint16_t)tmp[1];
+    guid->timeHiAndVersion = (uint16_t)tmp[2];
+    guid->clockSeq = (uint16_t)tmp[3];
+    guid->node[0] = (uint8_t)tmp[4];
+    guid->node[1] = (uint8_t)tmp[5];
+    guid->node[2] = (uint8_t)tmp[6];
+    guid->node[3] = (uint8_t)tmp[7];
+    guid->node[4] = (uint8_t)tmp[8];
+    guid->node[5] = (uint8_t)tmp[9];
+
+    return NO_ERROR;
+}
+
+status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
+{
+    if (guid == NULL || str == NULL) {
+        return BAD_VALUE;
+    }
+
+    snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+            guid->timeLow,
+            guid->timeMid,
+            guid->timeHiAndVersion,
+            guid->clockSeq,
+            guid->node[0],
+            guid->node[1],
+            guid->node[2],
+            guid->node[3],
+            guid->node[4],
+            guid->node[5]);
+
+    return NO_ERROR;
+}
+
+
+}; // namespace android
+
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index ad037d6..a6c515c 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -41,11 +41,43 @@
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
 
 namespace android {
+// ---------------------------------------------------------------------------
+
+// static
+status_t AudioRecord::getMinFrameCount(
+        int* frameCount,
+        uint32_t sampleRate,
+        int format,
+        int channelCount)
+{
+    size_t size = 0;
+    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size)
+            != NO_ERROR) {
+        LOGE("AudioSystem could not query the input buffer size.");
+        return NO_INIT;
+    }
+
+    if (size == 0) {
+        LOGE("Unsupported configuration: sampleRate %d, format %d, channelCount %d",
+            sampleRate, format, channelCount);
+        return BAD_VALUE;
+    }
+
+    // We double the size of input buffer for ping pong use of record buffer.
+    size <<= 1;
+
+    if (AudioSystem::isLinearPCM(format)) {
+        size /= channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+    }
+
+    *frameCount = size;
+    return NO_ERROR;
+}
 
 // ---------------------------------------------------------------------------
 
 AudioRecord::AudioRecord()
-    : mStatus(NO_INIT)
+    : mStatus(NO_INIT), mSessionId(0)
 {
 }
 
@@ -58,11 +90,12 @@
         uint32_t flags,
         callback_t cbf,
         void* user,
-        int notificationFrames)
-    : mStatus(NO_INIT)
+        int notificationFrames,
+        int sessionId)
+    : mStatus(NO_INIT), mSessionId(0)
 {
     mStatus = set(inputSource, sampleRate, format, channels,
-            frameCount, flags, cbf, user, notificationFrames);
+            frameCount, flags, cbf, user, notificationFrames, sessionId);
 }
 
 AudioRecord::~AudioRecord()
@@ -91,7 +124,8 @@
         callback_t cbf,
         void* user,
         int notificationFrames,
-        bool threadCanCallJava)
+        bool threadCanCallJava,
+        int sessionId)
 {
 
     LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount);
@@ -119,6 +153,7 @@
     if (!AudioSystem::isInputChannel(channels)) {
         return BAD_VALUE;
     }
+
     int channelCount = AudioSystem::popCount(channels);
 
     audio_io_handle_t input = AudioSystem::getInput(inputSource,
@@ -129,29 +164,11 @@
     }
 
     // validate framecount
-    size_t inputBuffSizeInBytes = -1;
-    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
-            != NO_ERROR) {
-        LOGE("AudioSystem could not query the input buffer size.");
-        return NO_INIT;
+    int minFrameCount = 0;
+    status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount);
+    if (status != NO_ERROR) {
+        return status;
     }
-
-    if (inputBuffSizeInBytes == 0) {
-        LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
-            sampleRate, channelCount, format);
-        return BAD_VALUE;
-    }
-
-    int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
-    if (AudioSystem::isLinearPCM(format)) {
-        frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? sizeof(int16_t) : sizeof(int8_t));
-    } else {
-        frameSizeInBytes = sizeof(int8_t);
-    }
-
-
-    // We use 2* size of input buffer for ping pong use of record buffer.
-    int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
     LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
 
     if (frameCount == 0) {
@@ -164,10 +181,11 @@
         notificationFrames = frameCount/2;
     }
 
-    // create the IAudioRecord
-    status_t status = openRecord(sampleRate, format, channelCount,
-                                 frameCount, flags, input);
+    mSessionId = sessionId;
 
+    // create the IAudioRecord
+    status = openRecord(sampleRate, format, channelCount,
+                        frameCount, flags, input);
     if (status != NO_ERROR) {
         return status;
     }
@@ -414,6 +432,7 @@
                                                        channelCount,
                                                        frameCount,
                                                        ((uint16_t)flags) << 16,
+                                                       &mSessionId,
                                                        &status);
     if (record == 0) {
         LOGE("AudioFlinger could not create record track, status: %d", status);
@@ -430,7 +449,7 @@
     mCblkMemory = cblk;
     mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
     mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
-    mCblk->out = 0;
+    mCblk->flags &= ~CBLK_DIRECTION_MSK;
     mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
     mCblk->waitTimeMs = 0;
     return NO_ERROR;
@@ -532,6 +551,11 @@
     return mInput;
 }
 
+int AudioRecord::getSessionId()
+{
+    return mSessionId;
+}
+
 // -------------------------------------------------------------------------
 
 ssize_t AudioRecord::read(void* buffer, size_t userSize)
@@ -644,10 +668,10 @@
 
     // Manage overrun callback
     if (mActive && (mCblk->framesAvailable_l() == 0)) {
-        LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
-        if (mCblk->flowControlFlag == 0) {
+        LOGV("Overrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags);
+        if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
             mCbf(EVENT_OVERRUN, mUserData, 0);
-            mCblk->flowControlFlag = 1;
+            mCblk->flags |= CBLK_UNDERRUN_ON;
         }
     }
 
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 5e6ce42..7e3b743 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -364,6 +364,12 @@
     return result;
 }
 
+int AudioSystem::newAudioSessionId() {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == 0) return 0;
+    return af->newAudioSessionId();
+}
+
 // ---------------------------------------------------------------------------
 
 void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
@@ -584,18 +590,22 @@
     return output;
 }
 
-status_t AudioSystem::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+status_t AudioSystem::startOutput(audio_io_handle_t output,
+                                  AudioSystem::stream_type stream,
+                                  int session)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
-    return aps->startOutput(output, stream);
+    return aps->startOutput(output, stream, session);
 }
 
-status_t AudioSystem::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+status_t AudioSystem::stopOutput(audio_io_handle_t output,
+                                 AudioSystem::stream_type stream,
+                                 int session)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
-    return aps->stopOutput(output, stream);
+    return aps->stopOutput(output, stream, session);
 }
 
 void AudioSystem::releaseOutput(audio_io_handle_t output)
@@ -660,6 +670,38 @@
     return aps->getStreamVolumeIndex(stream, index);
 }
 
+uint32_t AudioSystem::getStrategyForStream(AudioSystem::stream_type stream)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return 0;
+    return aps->getStrategyForStream(stream);
+}
+
+audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->getOutputForEffect(desc);
+}
+
+status_t AudioSystem::registerEffect(effect_descriptor_t *desc,
+                                audio_io_handle_t output,
+                                uint32_t strategy,
+                                int session,
+                                int id)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->registerEffect(desc, output, strategy, session, id);
+}
+
+status_t AudioSystem::unregisterEffect(int id)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+    return aps->unregisterEffect(id);
+}
+
 // ---------------------------------------------------------------------------
 
 void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index cd7bcd5..890786e 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -41,6 +41,35 @@
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
 
 namespace android {
+// ---------------------------------------------------------------------------
+
+// static
+status_t AudioTrack::getMinFrameCount(
+        int* frameCount,
+        int streamType,
+        uint32_t sampleRate)
+{
+    int afSampleRate;
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+    int afFrameCount;
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+    uint32_t afLatency;
+    if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+
+    // Ensure that buffer depth covers at least audio hardware latency
+    uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);
+    if (minBufCount < 2) minBufCount = 2;
+
+    *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :
+              afFrameCount * minBufCount * sampleRate / afSampleRate;
+    return NO_ERROR;
+}
 
 // ---------------------------------------------------------------------------
 
@@ -58,11 +87,13 @@
         uint32_t flags,
         callback_t cbf,
         void* user,
-        int notificationFrames)
+        int notificationFrames,
+        int sessionId)
     : mStatus(NO_INIT)
 {
     mStatus = set(streamType, sampleRate, format, channels,
-            frameCount, flags, cbf, user, notificationFrames, 0);
+            frameCount, flags, cbf, user, notificationFrames,
+            0, false, sessionId);
 }
 
 AudioTrack::AudioTrack(
@@ -74,11 +105,13 @@
         uint32_t flags,
         callback_t cbf,
         void* user,
-        int notificationFrames)
+        int notificationFrames,
+        int sessionId)
     : mStatus(NO_INIT)
 {
     mStatus = set(streamType, sampleRate, format, channels,
-            0, flags, cbf, user, notificationFrames, sharedBuffer);
+            0, flags, cbf, user, notificationFrames,
+            sharedBuffer, false, sessionId);
 }
 
 AudioTrack::~AudioTrack()
@@ -110,7 +143,8 @@
         void* user,
         int notificationFrames,
         const sp<IMemory>& sharedBuffer,
-        bool threadCanCallJava)
+        bool threadCanCallJava,
+        int sessionId)
 {
 
     LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
@@ -124,10 +158,6 @@
     if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         return NO_INIT;
     }
-    int afFrameCount;
-    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
-        return NO_INIT;
-    }
     uint32_t afLatency;
     if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
         return NO_INIT;
@@ -173,48 +203,17 @@
         return BAD_VALUE;
     }
 
-    if (!AudioSystem::isLinearPCM(format)) {
-        if (sharedBuffer != 0) {
-            frameCount = sharedBuffer->size();
-        }
-    } else {
-        // Ensure that buffer depth covers at least audio hardware latency
-        uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
-        if (minBufCount < 2) minBufCount = 2;
-
-        int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
-
-        if (sharedBuffer == 0) {
-            if (frameCount == 0) {
-                frameCount = minFrameCount;
-            }
-            if (notificationFrames == 0) {
-                notificationFrames = frameCount/2;
-            }
-            // Make sure that application is notified with sufficient margin
-            // before underrun
-            if (notificationFrames > frameCount/2) {
-                notificationFrames = frameCount/2;
-            }
-            if (frameCount < minFrameCount) {
-              LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
-              return BAD_VALUE;
-            }
-        } else {
-            // Ensure that buffer alignment matches channelcount
-            if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
-                LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
-                return BAD_VALUE;
-            }
-            frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
-        }
-    }
-
     mVolume[LEFT] = 1.0f;
     mVolume[RIGHT] = 1.0f;
+    mSendLevel = 0;
+    mFrameCount = frameCount;
+    mNotificationFramesReq = notificationFrames;
+    mSessionId = sessionId;
+    mAuxEffectId = 0;
+
     // create the IAudioTrack
     status_t status = createTrack(streamType, sampleRate, format, channelCount,
-                                  frameCount, flags, sharedBuffer, output);
+                                  frameCount, flags, sharedBuffer, output, true);
 
     if (status != NO_ERROR) {
         return status;
@@ -238,10 +237,7 @@
     mMuted = false;
     mActive = 0;
     mCbf = cbf;
-    mNotificationFrames = notificationFrames;
-    mRemainingFrames = notificationFrames;
     mUserData = user;
-    mLatency = afLatency + (1000*mFrameCount) / sampleRate;
     mLoopCount = 0;
     mMarkerPosition = 0;
     mMarkerReached = false;
@@ -281,7 +277,7 @@
 
 uint32_t AudioTrack::frameCount() const
 {
-    return mFrameCount;
+    return mCblk->frameCount;
 }
 
 int AudioTrack::frameSize() const
@@ -303,6 +299,7 @@
 void AudioTrack::start()
 {
     sp<AudioTrackThread> t = mAudioTrackThread;
+    status_t status;
 
     LOGV("start %p", this);
     if (t != 0) {
@@ -325,11 +322,18 @@
             setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
         }
 
-        status_t status = mAudioTrack->start();
+        if (mCblk->flags & CBLK_INVALID_MSK) {
+            LOGW("start() track %p invalidated, creating a new one", this);
+            // no need to clear the invalid flag as this cblk will not be used anymore
+            // force new track creation
+            status = DEAD_OBJECT;
+        } else {
+            status = mAudioTrack->start();
+        }
         if (status == DEAD_OBJECT) {
             LOGV("start() dead IAudioTrack: creating a new one");
             status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
-                                 mFrameCount, mFlags, mSharedBuffer, getOutput());
+                                 mFrameCount, mFlags, mSharedBuffer, getOutput(), false);
             if (status == NO_ERROR) {
                 status = mAudioTrack->start();
                 if (status == NO_ERROR) {
@@ -430,19 +434,50 @@
     return mMuted;
 }
 
-void AudioTrack::setVolume(float left, float right)
+status_t AudioTrack::setVolume(float left, float right)
 {
+    if (left > 1.0f || right > 1.0f) {
+        return BAD_VALUE;
+    }
+
     mVolume[LEFT] = left;
     mVolume[RIGHT] = right;
 
     // write must be atomic
-    mCblk->volumeLR = (int32_t(int16_t(left * 0x1000)) << 16) | int16_t(right * 0x1000);
+    mCblk->volumeLR = (uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000);
+
+    return NO_ERROR;
 }
 
 void AudioTrack::getVolume(float* left, float* right)
 {
-    *left  = mVolume[LEFT];
-    *right = mVolume[RIGHT];
+    if (left != NULL) {
+        *left  = mVolume[LEFT];
+    }
+    if (right != NULL) {
+        *right = mVolume[RIGHT];
+    }
+}
+
+status_t AudioTrack::setAuxEffectSendLevel(float level)
+{
+    LOGV("setAuxEffectSendLevel(%f)", level);
+    if (level > 1.0f) {
+        return BAD_VALUE;
+    }
+
+    mSendLevel = level;
+
+    mCblk->sendLevel = uint16_t(level * 0x1000);
+
+    return NO_ERROR;
+}
+
+void AudioTrack::getAuxEffectSendLevel(float* level)
+{
+    if (level != NULL) {
+        *level  = mSendLevel;
+    }
 }
 
 status_t AudioTrack::setSampleRate(int rate)
@@ -479,14 +514,14 @@
     }
 
     if (loopStart >= loopEnd ||
-        loopEnd - loopStart > mFrameCount) {
-        LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
+        loopEnd - loopStart > cblk->frameCount) {
+        LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, cblk->frameCount, cblk->user);
         return BAD_VALUE;
     }
 
-    if ((mSharedBuffer != 0) && (loopEnd   > mFrameCount)) {
+    if ((mSharedBuffer != 0) && (loopEnd   > cblk->frameCount)) {
         LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
-            loopStart, loopEnd, mFrameCount);
+            loopStart, loopEnd, cblk->frameCount);
         return BAD_VALUE;
     }
 
@@ -566,7 +601,7 @@
     if (position > mCblk->user) return BAD_VALUE;
 
     mCblk->server = position;
-    mCblk->forceReady = 1;
+    mCblk->flags |= CBLK_FORCEREADY_ON;
 
     return NO_ERROR;
 }
@@ -586,7 +621,7 @@
 
     flush();
 
-    mCblk->stepUser(mFrameCount);
+    mCblk->stepUser(mCblk->frameCount);
 
     return NO_ERROR;
 }
@@ -597,6 +632,21 @@
             mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags);
 }
 
+int AudioTrack::getSessionId()
+{
+    return mSessionId;
+}
+
+status_t AudioTrack::attachAuxEffect(int effectId)
+{
+    LOGV("attachAuxEffect(%d)", effectId);
+    status_t status = mAudioTrack->attachAuxEffect(effectId);
+    if (status == NO_ERROR) {
+        mAuxEffectId = effectId;
+    }
+    return status;
+}
+
 // -------------------------------------------------------------------------
 
 status_t AudioTrack::createTrack(
@@ -607,7 +657,8 @@
         int frameCount,
         uint32_t flags,
         const sp<IMemory>& sharedBuffer,
-        audio_io_handle_t output)
+        audio_io_handle_t output,
+        bool enforceFrameCount)
 {
     status_t status;
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
@@ -616,6 +667,61 @@
        return NO_INIT;
     }
 
+    int afSampleRate;
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+    int afFrameCount;
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+    uint32_t afLatency;
+    if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
+        return NO_INIT;
+    }
+
+    mNotificationFramesAct = mNotificationFramesReq;
+    if (!AudioSystem::isLinearPCM(format)) {
+        if (sharedBuffer != 0) {
+            frameCount = sharedBuffer->size();
+        }
+    } else {
+        // Ensure that buffer depth covers at least audio hardware latency
+        uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+        if (minBufCount < 2) minBufCount = 2;
+
+        int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
+
+        if (sharedBuffer == 0) {
+            if (frameCount == 0) {
+                frameCount = minFrameCount;
+            }
+            if (mNotificationFramesAct == 0) {
+                mNotificationFramesAct = frameCount/2;
+            }
+            // Make sure that application is notified with sufficient margin
+            // before underrun
+            if (mNotificationFramesAct > (uint32_t)frameCount/2) {
+                mNotificationFramesAct = frameCount/2;
+            }
+            if (frameCount < minFrameCount) {
+                if (enforceFrameCount) {
+                    LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
+                    return BAD_VALUE;
+                } else {
+                    frameCount = minFrameCount;
+                }
+            }
+        } else {
+            // Ensure that buffer alignment matches channelcount
+            if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
+                LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
+                return BAD_VALUE;
+            }
+            frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+        }
+    }
+
     sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
                                                       streamType,
                                                       sampleRate,
@@ -625,6 +731,7 @@
                                                       ((uint16_t)flags) << 16,
                                                       sharedBuffer,
                                                       output,
+                                                      &mSessionId,
                                                       &status);
 
     if (track == 0) {
@@ -641,20 +748,22 @@
     mCblkMemory.clear();
     mCblkMemory = cblk;
     mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
-    mCblk->out = 1;
-    // Update buffer size in case it has been limited by AudioFlinger during track creation
-    mFrameCount = mCblk->frameCount;
+    mCblk->flags |= CBLK_DIRECTION_OUT;
     if (sharedBuffer == 0) {
         mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
     } else {
         mCblk->buffers = sharedBuffer->pointer();
          // Force buffer full condition as data is already present in shared memory
-        mCblk->stepUser(mFrameCount);
+        mCblk->stepUser(mCblk->frameCount);
     }
 
-    mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000);
+    mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000);
+    mCblk->sendLevel = uint16_t(mSendLevel * 0x1000);
+    mAudioTrack->attachAuxEffect(mAuxEffectId);
     mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
     mCblk->waitTimeMs = 0;
+    mRemainingFrames = mNotificationFramesAct;
+    mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate;
     return NO_ERROR;
 }
 
@@ -685,8 +794,15 @@
                 cblk->lock.unlock();
                 return WOULD_BLOCK;
             }
-
-            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+            if (!(cblk->flags & CBLK_INVALID_MSK)) {
+                result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+            }
+            if (cblk->flags & CBLK_INVALID_MSK) {
+                LOGW("obtainBuffer() track %p invalidated, creating a new one", this);
+                // no need to clear the invalid flag as this cblk will not be used anymore
+                cblk->lock.unlock();
+                goto create_new_track;
+            }
             if (__builtin_expect(result!=NO_ERROR, false)) {
                 cblk->waitTimeMs += waitTimeMs;
                 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
@@ -700,8 +816,9 @@
                         result = mAudioTrack->start();
                         if (result == DEAD_OBJECT) {
                             LOGW("obtainBuffer() dead IAudioTrack: creating a new one");
+create_new_track:
                             result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount,
-                                                 mFrameCount, mFlags, mSharedBuffer, getOutput());
+                                                 mFrameCount, mFlags, mSharedBuffer, getOutput(), false);
                             if (result == NO_ERROR) {
                                 cblk = mCblk;
                                 cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
@@ -826,13 +943,13 @@
 
     // Manage underrun callback
     if (mActive && (mCblk->framesReady() == 0)) {
-        LOGV("Underrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
-        if (mCblk->flowControlFlag == 0) {
+        LOGV("Underrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags);
+        if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
             mCbf(EVENT_UNDERRUN, mUserData, 0);
             if (mCblk->server == mCblk->frameCount) {
                 mCbf(EVENT_BUFFER_END, mUserData, 0);
             }
-            mCblk->flowControlFlag = 1;
+            mCblk->flags |= CBLK_UNDERRUN_ON;
             if (mSharedBuffer != 0) return false;
         }
     }
@@ -932,7 +1049,7 @@
     while (frames);
 
     if (frames == 0) {
-        mRemainingFrames = mNotificationFrames;
+        mRemainingFrames = mNotificationFramesAct;
     } else {
         mRemainingFrames = frames;
     }
@@ -949,7 +1066,7 @@
     result.append(" AudioTrack::dump\n");
     snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]);
     result.append(buffer);
-    snprintf(buffer, 255, "  format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mFrameCount);
+    snprintf(buffer, 255, "  format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mCblk->frameCount);
     result.append(buffer);
     snprintf(buffer, 255, "  sample rate(%d), status(%d), muted(%d)\n", (mCblk == 0) ? 0 : mCblk->sampleRate, mStatus, mMuted);
     result.append(buffer);
@@ -986,7 +1103,7 @@
     : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
     userBase(0), serverBase(0), buffers(0), frameCount(0),
     loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0),
-    flowControlFlag(1), forceReady(0)
+    flags(0), sendLevel(0)
 {
 }
 
@@ -996,7 +1113,7 @@
 
     u += frameCount;
     // Ensure that user is never ahead of server for AudioRecord
-    if (out) {
+    if (flags & CBLK_DIRECTION_MSK) {
         // If stepServer() has been called once, switch to normal obtainBuffer() timeout period
         if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) {
             bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
@@ -1013,7 +1130,7 @@
     this->user = u;
 
     // Clear flow control error condition as new data has been written/read to/from buffer.
-    flowControlFlag = 0;
+    flags &= ~CBLK_UNDERRUN_MSK;
 
     return u;
 }
@@ -1038,7 +1155,7 @@
     uint32_t s = this->server;
 
     s += frameCount;
-    if (out) {
+    if (flags & CBLK_DIRECTION_MSK) {
         // Mark that we have read the first buffer so that next time stepUser() is called
         // we switch to normal obtainBuffer() timeout period
         if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
@@ -1089,7 +1206,7 @@
     uint32_t u = this->user;
     uint32_t s = this->server;
 
-    if (out) {
+    if (flags & CBLK_DIRECTION_MSK) {
         uint32_t limit = (s < loopStart) ? s : loopStart;
         return limit + frameCount - u;
     } else {
@@ -1102,7 +1219,7 @@
     uint32_t u = this->user;
     uint32_t s = this->server;
 
-    if (out) {
+    if (flags & CBLK_DIRECTION_MSK) {
         if (u < loopEnd) {
             return u - s;
         } else {
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 47bcc12..3a89e25 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -62,7 +62,15 @@
     SET_STREAM_OUTPUT,
     SET_VOICE_VOLUME,
     GET_RENDER_POSITION,
-    GET_INPUT_FRAMES_LOST
+    GET_INPUT_FRAMES_LOST,
+    NEW_AUDIO_SESSION_ID,
+    LOAD_EFFECT_LIBRARY,
+    UNLOAD_EFFECT_LIBRARY,
+    QUERY_NUM_EFFECTS,
+    QUERY_EFFECT,
+    GET_EFFECT_DESCRIPTOR,
+    CREATE_EFFECT,
+    MOVE_EFFECTS
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -83,6 +91,7 @@
                                 uint32_t flags,
                                 const sp<IMemory>& sharedBuffer,
                                 int output,
+                                int *sessionId,
                                 status_t *status)
     {
         Parcel data, reply;
@@ -97,10 +106,19 @@
         data.writeInt32(flags);
         data.writeStrongBinder(sharedBuffer->asBinder());
         data.writeInt32(output);
+        int lSessionId = 0;
+        if (sessionId != NULL) {
+            lSessionId = *sessionId;
+        }
+        data.writeInt32(lSessionId);
         status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
         if (lStatus != NO_ERROR) {
             LOGE("createTrack error: %s", strerror(-lStatus));
         } else {
+            lSessionId = reply.readInt32();
+            if (sessionId != NULL) {
+                *sessionId = lSessionId;
+            }
             lStatus = reply.readInt32();
             track = interface_cast<IAudioTrack>(reply.readStrongBinder());
         }
@@ -118,6 +136,7 @@
                                 int channelCount,
                                 int frameCount,
                                 uint32_t flags,
+                                int *sessionId,
                                 status_t *status)
     {
         Parcel data, reply;
@@ -130,10 +149,19 @@
         data.writeInt32(channelCount);
         data.writeInt32(frameCount);
         data.writeInt32(flags);
+        int lSessionId = 0;
+        if (sessionId != NULL) {
+            lSessionId = *sessionId;
+        }
+        data.writeInt32(lSessionId);
         status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply);
         if (lStatus != NO_ERROR) {
             LOGE("openRecord error: %s", strerror(-lStatus));
         } else {
+            lSessionId = reply.readInt32();
+            if (sessionId != NULL) {
+                *sessionId = lSessionId;
+            }
             lStatus = reply.readInt32();
             record = interface_cast<IAudioRecord>(reply.readStrongBinder());
         }
@@ -497,6 +525,169 @@
         remote()->transact(GET_INPUT_FRAMES_LOST, data, &reply);
         return reply.readInt32();
     }
+
+    virtual int newAudioSessionId()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        status_t status = remote()->transact(NEW_AUDIO_SESSION_ID, data, &reply);
+        int id = 0;
+        if (status == NO_ERROR) {
+            id = reply.readInt32();
+        }
+        return id;
+    }
+
+    virtual status_t loadEffectLibrary(const char *libPath, int *handle)
+    {
+        if (libPath == NULL || handle == NULL) {
+            return BAD_VALUE;
+        }
+        *handle = 0;
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeCString(libPath);
+        status_t status = remote()->transact(LOAD_EFFECT_LIBRARY, data, &reply);
+        if (status == NO_ERROR) {
+            status = reply.readInt32();
+            if (status == NO_ERROR) {
+                *handle = reply.readInt32();
+            }
+        }
+        return status;
+    }
+
+    virtual status_t unloadEffectLibrary(int handle)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(handle);
+        status_t status = remote()->transact(UNLOAD_EFFECT_LIBRARY, data, &reply);
+        if (status == NO_ERROR) {
+            status = reply.readInt32();
+        }
+        return status;
+    }
+
+    virtual status_t queryNumberEffects(uint32_t *numEffects)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        status_t status = remote()->transact(QUERY_NUM_EFFECTS, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
+        if (status != NO_ERROR) {
+            return status;
+        }
+        if (numEffects) {
+            *numEffects = (uint32_t)reply.readInt32();
+        }
+        return NO_ERROR;
+    }
+
+    virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
+    {
+        if (pDescriptor == NULL) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(index);
+        status_t status = remote()->transact(QUERY_EFFECT, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
+        if (status != NO_ERROR) {
+            return status;
+        }
+        reply.read(pDescriptor, sizeof(effect_descriptor_t));
+        return NO_ERROR;
+    }
+
+    virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *pDescriptor)
+    {
+        if (pUuid == NULL || pDescriptor == NULL) {
+            return BAD_VALUE;
+        }
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.write(pUuid, sizeof(effect_uuid_t));
+        status_t status = remote()->transact(GET_EFFECT_DESCRIPTOR, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = reply.readInt32();
+        if (status != NO_ERROR) {
+            return status;
+        }
+        reply.read(pDescriptor, sizeof(effect_descriptor_t));
+        return NO_ERROR;
+    }
+
+    virtual sp<IEffect> createEffect(pid_t pid,
+                                    effect_descriptor_t *pDesc,
+                                    const sp<IEffectClient>& client,
+                                    int32_t priority,
+                                    int output,
+                                    int sessionId,
+                                    status_t *status,
+                                    int *id,
+                                    int *enabled)
+    {
+        Parcel data, reply;
+        sp<IEffect> effect;
+
+        if (pDesc == NULL) {
+             return effect;
+             if (status) {
+                 *status = BAD_VALUE;
+             }
+         }
+
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.write(pDesc, sizeof(effect_descriptor_t));
+        data.writeStrongBinder(client->asBinder());
+        data.writeInt32(priority);
+        data.writeInt32(output);
+        data.writeInt32(sessionId);
+
+        status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply);
+        if (lStatus != NO_ERROR) {
+            LOGE("createEffect error: %s", strerror(-lStatus));
+        } else {
+            lStatus = reply.readInt32();
+            int tmp = reply.readInt32();
+            if (id) {
+                *id = tmp;
+            }
+            tmp = reply.readInt32();
+            if (enabled) {
+                *enabled = tmp;
+            }
+            effect = interface_cast<IEffect>(reply.readStrongBinder());
+            reply.read(pDesc, sizeof(effect_descriptor_t));
+        }
+        if (status) {
+            *status = lStatus;
+        }
+
+        return effect;
+    }
+
+    virtual status_t moveEffects(int session, int srcOutput, int dstOutput)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(session);
+        data.writeInt32(srcOutput);
+        data.writeInt32(dstOutput);
+        remote()->transact(MOVE_EFFECTS, data, &reply);
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -518,10 +709,12 @@
             uint32_t flags = data.readInt32();
             sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
             int output = data.readInt32();
+            int sessionId = data.readInt32();
             status_t status;
             sp<IAudioTrack> track = createTrack(pid,
                     streamType, sampleRate, format,
-                    channelCount, bufferCount, flags, buffer, output, &status);
+                    channelCount, bufferCount, flags, buffer, output, &sessionId, &status);
+            reply->writeInt32(sessionId);
             reply->writeInt32(status);
             reply->writeStrongBinder(track->asBinder());
             return NO_ERROR;
@@ -535,9 +728,11 @@
             int channelCount = data.readInt32();
             size_t bufferCount = data.readInt32();
             uint32_t flags = data.readInt32();
+            int sessionId = data.readInt32();
             status_t status;
             sp<IAudioRecord> record = openRecord(pid, input,
-                    sampleRate, format, channelCount, bufferCount, flags, &status);
+                    sampleRate, format, channelCount, bufferCount, flags, &sessionId, &status);
+            reply->writeInt32(sessionId);
             reply->writeInt32(status);
             reply->writeStrongBinder(record->asBinder());
             return NO_ERROR;
@@ -768,7 +963,87 @@
             reply->writeInt32(getInputFramesLost(ioHandle));
             return NO_ERROR;
         } break;
+        case NEW_AUDIO_SESSION_ID: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32(newAudioSessionId());
+            return NO_ERROR;
+        } break;
+        case LOAD_EFFECT_LIBRARY: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int handle;
+            status_t status = loadEffectLibrary(data.readCString(), &handle);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32(handle);
+            }
+            return NO_ERROR;
+        }
+        case UNLOAD_EFFECT_LIBRARY: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32(unloadEffectLibrary(data.readInt32()));
+            return NO_ERROR;
+        }
+        case QUERY_NUM_EFFECTS: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            uint32_t numEffects;
+            status_t status = queryNumberEffects(&numEffects);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->writeInt32((int32_t)numEffects);
+            }
+            return NO_ERROR;
+        }
+        case QUERY_EFFECT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            effect_descriptor_t desc;
+            status_t status = queryEffect(data.readInt32(), &desc);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->write(&desc, sizeof(effect_descriptor_t));
+            }
+            return NO_ERROR;
+        }
+        case GET_EFFECT_DESCRIPTOR: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            effect_uuid_t uuid;
+            data.read(&uuid, sizeof(effect_uuid_t));
+            effect_descriptor_t desc;
+            status_t status = getEffectDescriptor(&uuid, &desc);
+            reply->writeInt32(status);
+            if (status == NO_ERROR) {
+                reply->write(&desc, sizeof(effect_descriptor_t));
+            }
+            return NO_ERROR;
+        }
+        case CREATE_EFFECT: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            pid_t pid = data.readInt32();
+            effect_descriptor_t desc;
+            data.read(&desc, sizeof(effect_descriptor_t));
+            sp<IEffectClient> client = interface_cast<IEffectClient>(data.readStrongBinder());
+            int32_t priority = data.readInt32();
+            int output = data.readInt32();
+            int sessionId = data.readInt32();
+            status_t status;
+            int id;
+            int enabled;
 
+            sp<IEffect> effect = createEffect(pid, &desc, client, priority, output, sessionId, &status, &id, &enabled);
+            reply->writeInt32(status);
+            reply->writeInt32(id);
+            reply->writeInt32(enabled);
+            reply->writeStrongBinder(effect->asBinder());
+            reply->write(&desc, sizeof(effect_descriptor_t));
+            return NO_ERROR;
+        } break;
+        case MOVE_EFFECTS: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            int session = data.readInt32();
+            int srcOutput = data.readInt32();
+            int dstOutput = data.readInt32();
+            reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 18dd173..950c213 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -44,7 +44,11 @@
     RELEASE_INPUT,
     INIT_STREAM_VOLUME,
     SET_STREAM_VOLUME,
-    GET_STREAM_VOLUME
+    GET_STREAM_VOLUME,
+    GET_STRATEGY_FOR_STREAM,
+    GET_OUTPUT_FOR_EFFECT,
+    REGISTER_EFFECT,
+    UNREGISTER_EFFECT
 };
 
 class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -137,22 +141,28 @@
         return static_cast <audio_io_handle_t> (reply.readInt32());
     }
 
-    virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+    virtual status_t startOutput(audio_io_handle_t output,
+                                 AudioSystem::stream_type stream,
+                                 int session)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(output);
         data.writeInt32(stream);
+        data.writeInt32(session);
         remote()->transact(START_OUTPUT, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
 
-    virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+    virtual status_t stopOutput(audio_io_handle_t output,
+                                AudioSystem::stream_type stream,
+                                int session)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(output);
         data.writeInt32(stream);
+        data.writeInt32(session);
         remote()->transact(STOP_OUTPUT, data, &reply);
         return static_cast <status_t> (reply.readInt32());
     }
@@ -242,6 +252,51 @@
         if (index) *index = lIndex;
         return static_cast <status_t> (reply.readInt32());
     }
+
+    virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(static_cast <uint32_t>(stream));
+        remote()->transact(GET_STRATEGY_FOR_STREAM, data, &reply);
+        return reply.readInt32();
+    }
+
+    virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(desc, sizeof(effect_descriptor_t));
+        remote()->transact(GET_OUTPUT_FOR_EFFECT, data, &reply);
+        return static_cast <audio_io_handle_t> (reply.readInt32());
+    }
+
+    virtual status_t registerEffect(effect_descriptor_t *desc,
+                                        audio_io_handle_t output,
+                                        uint32_t strategy,
+                                        int session,
+                                        int id)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(desc, sizeof(effect_descriptor_t));
+        data.writeInt32(output);
+        data.writeInt32(strategy);
+        data.writeInt32(session);
+        data.writeInt32(id);
+        remote()->transact(REGISTER_EFFECT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
+    virtual status_t unregisterEffect(int id)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(id);
+        remote()->transact(UNREGISTER_EFFECT, data, &reply);
+        return static_cast <status_t> (reply.readInt32());
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -255,18 +310,24 @@
     switch(code) {
         case SET_DEVICE_CONNECTION_STATE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
-            AudioSystem::device_connection_state state = static_cast <AudioSystem::device_connection_state>(data.readInt32());
+            AudioSystem::audio_devices device =
+                    static_cast <AudioSystem::audio_devices>(data.readInt32());
+            AudioSystem::device_connection_state state =
+                    static_cast <AudioSystem::device_connection_state>(data.readInt32());
             const char *device_address = data.readCString();
-            reply->writeInt32(static_cast <uint32_t>(setDeviceConnectionState(device, state, device_address)));
+            reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
+                                                                              state,
+                                                                              device_address)));
             return NO_ERROR;
         } break;
 
         case GET_DEVICE_CONNECTION_STATE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
+            AudioSystem::audio_devices device =
+                    static_cast<AudioSystem::audio_devices> (data.readInt32());
             const char *device_address = data.readCString();
-            reply->writeInt32(static_cast <uint32_t>(getDeviceConnectionState(device, device_address)));
+            reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device,
+                                                                              device_address)));
             return NO_ERROR;
         } break;
 
@@ -287,7 +348,8 @@
         case SET_FORCE_USE: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
-            AudioSystem::forced_config config = static_cast <AudioSystem::forced_config>(data.readInt32());
+            AudioSystem::forced_config config =
+                    static_cast <AudioSystem::forced_config>(data.readInt32());
             reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config)));
             return NO_ERROR;
         } break;
@@ -301,11 +363,13 @@
 
         case GET_OUTPUT: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            AudioSystem::stream_type stream =
+                    static_cast <AudioSystem::stream_type>(data.readInt32());
             uint32_t samplingRate = data.readInt32();
             uint32_t format = data.readInt32();
             uint32_t channels = data.readInt32();
-            AudioSystem::output_flags flags = static_cast <AudioSystem::output_flags>(data.readInt32());
+            AudioSystem::output_flags flags =
+                    static_cast <AudioSystem::output_flags>(data.readInt32());
 
             audio_io_handle_t output = getOutput(stream,
                                                  samplingRate,
@@ -320,7 +384,10 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
             uint32_t stream = data.readInt32();
-            reply->writeInt32(static_cast <uint32_t>(startOutput(output, (AudioSystem::stream_type)stream)));
+            int session = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(startOutput(output,
+                                                                 (AudioSystem::stream_type)stream,
+                                                                 session)));
             return NO_ERROR;
         } break;
 
@@ -328,7 +395,10 @@
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
             audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
             uint32_t stream = data.readInt32();
-            reply->writeInt32(static_cast <uint32_t>(stopOutput(output, (AudioSystem::stream_type)stream)));
+            int session = data.readInt32();
+            reply->writeInt32(static_cast <uint32_t>(stopOutput(output,
+                                                                (AudioSystem::stream_type)stream,
+                                                                session)));
             return NO_ERROR;
         } break;
 
@@ -345,7 +415,8 @@
             uint32_t samplingRate = data.readInt32();
             uint32_t format = data.readInt32();
             uint32_t channels = data.readInt32();
-            AudioSystem::audio_in_acoustics acoustics = static_cast <AudioSystem::audio_in_acoustics>(data.readInt32());
+            AudioSystem::audio_in_acoustics acoustics =
+                    static_cast <AudioSystem::audio_in_acoustics>(data.readInt32());
             audio_io_handle_t input = getInput(inputSource,
                                                samplingRate,
                                                format,
@@ -378,7 +449,8 @@
 
         case INIT_STREAM_VOLUME: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            AudioSystem::stream_type stream =
+                    static_cast <AudioSystem::stream_type>(data.readInt32());
             int indexMin = data.readInt32();
             int indexMax = data.readInt32();
             reply->writeInt32(static_cast <uint32_t>(initStreamVolume(stream, indexMin,indexMax)));
@@ -387,7 +459,8 @@
 
         case SET_STREAM_VOLUME: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            AudioSystem::stream_type stream =
+                    static_cast <AudioSystem::stream_type>(data.readInt32());
             int index = data.readInt32();
             reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, index)));
             return NO_ERROR;
@@ -395,7 +468,8 @@
 
         case GET_STREAM_VOLUME: {
             CHECK_INTERFACE(IAudioPolicyService, data, reply);
-            AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+            AudioSystem::stream_type stream =
+                    static_cast <AudioSystem::stream_type>(data.readInt32());
             int index;
             status_t status = getStreamVolumeIndex(stream, &index);
             reply->writeInt32(index);
@@ -403,6 +477,46 @@
             return NO_ERROR;
         } break;
 
+        case GET_STRATEGY_FOR_STREAM: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            AudioSystem::stream_type stream =
+                    static_cast <AudioSystem::stream_type>(data.readInt32());
+            reply->writeInt32(getStrategyForStream(stream));
+            return NO_ERROR;
+        } break;
+
+        case GET_OUTPUT_FOR_EFFECT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            effect_descriptor_t desc;
+            data.read(&desc, sizeof(effect_descriptor_t));
+            audio_io_handle_t output = getOutputForEffect(&desc);
+            reply->writeInt32(static_cast <int>(output));
+            return NO_ERROR;
+        } break;
+
+        case REGISTER_EFFECT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            effect_descriptor_t desc;
+            data.read(&desc, sizeof(effect_descriptor_t));
+            audio_io_handle_t output = data.readInt32();
+            uint32_t strategy = data.readInt32();
+            int session = data.readInt32();
+            int id = data.readInt32();
+            reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
+                                                                   output,
+                                                                   strategy,
+                                                                   session,
+                                                                   id)));
+            return NO_ERROR;
+        } break;
+
+        case UNREGISTER_EFFECT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            int id = data.readInt32();
+            reply->writeInt32(static_cast <int32_t>(unregisterEffect(id)));
+            return NO_ERROR;
+        } break;
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index 01ffd75..bc8ff34 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -34,7 +34,8 @@
     STOP,
     FLUSH,
     MUTE,
-    PAUSE
+    PAUSE,
+    ATTACH_AUX_EFFECT
 };
 
 class BpAudioTrack : public BpInterface<IAudioTrack>
@@ -97,7 +98,21 @@
             cblk = interface_cast<IMemory>(reply.readStrongBinder());
         }
         return cblk;
-    }    
+    }
+
+    virtual status_t attachAuxEffect(int effectId)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+        data.writeInt32(effectId);
+        status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
+        if (status == NO_ERROR) {
+            status = reply.readInt32();
+        } else {
+            LOGW("attachAuxEffect() error: %s", strerror(-status));
+        }
+        return status;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
@@ -138,6 +153,11 @@
             pause();
             return NO_ERROR;
         }
+        case ATTACH_AUX_EFFECT: {
+            CHECK_INTERFACE(IAudioTrack, data, reply);
+            reply->writeInt32(attachAuxEffect(data.readInt32()));
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp
new file mode 100644
index 0000000..a945b97
--- /dev/null
+++ b/media/libmedia/IEffect.cpp
@@ -0,0 +1,195 @@
+/*
+**
+** Copyright 2010, 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 "IEffect"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <media/IEffect.h>
+
+namespace android {
+
+enum {
+    ENABLE = IBinder::FIRST_CALL_TRANSACTION,
+    DISABLE,
+    COMMAND,
+    DISCONNECT,
+    GET_CBLK
+};
+
+class BpEffect: public BpInterface<IEffect>
+{
+public:
+    BpEffect(const sp<IBinder>& impl)
+        : BpInterface<IEffect>(impl)
+    {
+    }
+
+    status_t enable()
+    {
+        LOGV("enable");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        remote()->transact(ENABLE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t disable()
+    {
+        LOGV("disable");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        remote()->transact(DISABLE, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t command(uint32_t cmdCode,
+                     uint32_t cmdSize,
+                     void *pCmdData,
+                     uint32_t *pReplySize,
+                     void *pReplyData)
+    {
+        LOGV("command");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        data.writeInt32(cmdCode);
+        int size = cmdSize;
+        if (pCmdData == NULL) {
+            size = 0;
+        }
+        data.writeInt32(size);
+        if (size) {
+            data.write(pCmdData, size);
+        }
+        if (pReplySize == NULL) {
+            size = 0;
+        } else {
+            size = *pReplySize;
+        }
+        data.writeInt32(size);
+        remote()->transact(COMMAND, data, &reply);
+        status_t status = reply.readInt32();
+        size = reply.readInt32();
+        if (size != 0 && pReplyData != NULL && pReplySize != NULL) {
+            reply.read(pReplyData, size);
+            *pReplySize = size;
+        }
+        return status;
+    }
+
+    void disconnect()
+    {
+        LOGV("disconnect");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        remote()->transact(DISCONNECT, data, &reply);
+        return;
+    }
+
+    virtual sp<IMemory> getCblk() const
+    {
+        Parcel data, reply;
+        sp<IMemory> cblk;
+        data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+        status_t status = remote()->transact(GET_CBLK, data, &reply);
+        if (status == NO_ERROR) {
+            cblk = interface_cast<IMemory>(reply.readStrongBinder());
+        }
+        return cblk;
+    }
+ };
+
+IMPLEMENT_META_INTERFACE(Effect, "android.media.IEffect");
+
+// ----------------------------------------------------------------------
+
+status_t BnEffect::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case ENABLE: {
+            LOGV("ENABLE");
+            CHECK_INTERFACE(IEffect, data, reply);
+            reply->writeInt32(enable());
+            return NO_ERROR;
+        } break;
+
+        case DISABLE: {
+            LOGV("DISABLE");
+            CHECK_INTERFACE(IEffect, data, reply);
+            reply->writeInt32(disable());
+            return NO_ERROR;
+        } break;
+
+        case COMMAND: {
+            LOGV("COMMAND");
+            CHECK_INTERFACE(IEffect, data, reply);
+            uint32_t cmdCode = data.readInt32();
+            uint32_t cmdSize = data.readInt32();
+            char *cmd = NULL;
+            if (cmdSize) {
+                cmd = (char *)malloc(cmdSize);
+                data.read(cmd, cmdSize);
+            }
+            uint32_t replySize = data.readInt32();
+            uint32_t replySz = replySize;
+            char *resp = NULL;
+            if (replySize) {
+                resp = (char *)malloc(replySize);
+            }
+            status_t status = command(cmdCode, cmdSize, cmd, &replySz, resp);
+            reply->writeInt32(status);
+            if (replySz < replySize) {
+                replySize = replySz;
+            }
+            reply->writeInt32(replySize);
+            if (replySize) {
+                reply->write(resp, replySize);
+            }
+            if (cmd) {
+                free(cmd);
+            }
+            if (resp) {
+                free(resp);
+            }
+            return NO_ERROR;
+        } break;
+
+        case DISCONNECT: {
+            LOGV("DISCONNECT");
+            CHECK_INTERFACE(IEffect, data, reply);
+            disconnect();
+            return NO_ERROR;
+        } break;
+
+        case GET_CBLK: {
+             CHECK_INTERFACE(IEffect, data, reply);
+             reply->writeStrongBinder(getCblk()->asBinder());
+             return NO_ERROR;
+         } break;
+
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IEffectClient.cpp b/media/libmedia/IEffectClient.cpp
new file mode 100644
index 0000000..1fa9cbe
--- /dev/null
+++ b/media/libmedia/IEffectClient.cpp
@@ -0,0 +1,145 @@
+/*
+**
+** Copyright 2010, 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 "IEffectClient"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <media/IEffectClient.h>
+
+namespace android {
+
+enum {
+    CONTROL_STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
+    ENABLE_STATUS_CHANGED,
+    COMMAND_EXECUTED
+};
+
+class BpEffectClient: public BpInterface<IEffectClient>
+{
+public:
+    BpEffectClient(const sp<IBinder>& impl)
+        : BpInterface<IEffectClient>(impl)
+    {
+    }
+
+    void controlStatusChanged(bool controlGranted)
+    {
+        LOGV("controlStatusChanged");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+        data.writeInt32((uint32_t)controlGranted);
+        remote()->transact(CONTROL_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    void enableStatusChanged(bool enabled)
+    {
+        LOGV("enableStatusChanged");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+        data.writeInt32((uint32_t)enabled);
+        remote()->transact(ENABLE_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    void commandExecuted(uint32_t cmdCode,
+                         uint32_t cmdSize,
+                         void *pCmdData,
+                         uint32_t replySize,
+                         void *pReplyData)
+    {
+        LOGV("commandExecuted");
+        Parcel data, reply;
+        data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+        data.writeInt32(cmdCode);
+        int size = cmdSize;
+        if (pCmdData == NULL) {
+            size = 0;
+        }
+        data.writeInt32(size);
+        if (size) {
+            data.write(pCmdData, size);
+        }
+        size = replySize;
+        if (pReplyData == NULL) {
+            size = 0;
+        }
+        data.writeInt32(size);
+        if (size) {
+            data.write(pReplyData, size);
+        }
+        remote()->transact(COMMAND_EXECUTED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(EffectClient, "android.media.IEffectClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnEffectClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case CONTROL_STATUS_CHANGED: {
+            LOGV("CONTROL_STATUS_CHANGED");
+            CHECK_INTERFACE(IEffectClient, data, reply);
+            bool hasControl = (bool)data.readInt32();
+            controlStatusChanged(hasControl);
+            return NO_ERROR;
+        } break;
+        case ENABLE_STATUS_CHANGED: {
+            LOGV("ENABLE_STATUS_CHANGED");
+            CHECK_INTERFACE(IEffectClient, data, reply);
+            bool enabled = (bool)data.readInt32();
+            enableStatusChanged(enabled);
+            return NO_ERROR;
+        } break;
+        case COMMAND_EXECUTED: {
+            LOGV("COMMAND_EXECUTED");
+            CHECK_INTERFACE(IEffectClient, data, reply);
+            uint32_t cmdCode = data.readInt32();
+            uint32_t cmdSize = data.readInt32();
+            char *cmd = NULL;
+            if (cmdSize) {
+                cmd = (char *)malloc(cmdSize);
+                data.read(cmd, cmdSize);
+            }
+            uint32_t replySize = data.readInt32();
+            char *resp = NULL;
+            if (replySize) {
+                resp = (char *)malloc(replySize);
+                data.read(resp, replySize);
+            }
+            commandExecuted(cmdCode, cmdSize, cmd, replySize, resp);
+            if (cmd) {
+                free(cmd);
+            }
+            if (resp) {
+                free(resp);
+            }
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index ed792b3..0f55b19 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -45,6 +45,8 @@
     GET_METADATA,
     SUSPEND,
     RESUME,
+    SET_AUX_EFFECT_SEND_LEVEL,
+    ATTACH_AUX_EFFECT
 };
 
 class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -221,6 +223,24 @@
 
         return reply.readInt32();
     }
+
+    status_t setAuxEffectSendLevel(float level)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeFloat(level);
+        remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t attachAuxEffect(int effectId)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+        data.writeInt32(effectId);
+        remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -339,6 +359,16 @@
             reply->setDataPosition(0);
             return NO_ERROR;
         } break;
+        case SET_AUX_EFFECT_SEND_LEVEL: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
+            return NO_ERROR;
+        } break;
+        case ATTACH_AUX_EFFECT: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(attachAuxEffect(data.readInt32()));
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 71c5f86..4abfa75 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -35,8 +35,7 @@
     DECODE_FD,
     CREATE_MEDIA_RECORDER,
     CREATE_METADATA_RETRIEVER,
-    GET_OMX,
-    SNOOP
+    GET_OMX
 };
 
 class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
@@ -58,7 +57,7 @@
 
     virtual sp<IMediaPlayer> create(
             pid_t pid, const sp<IMediaPlayerClient>& client,
-            const char* url, const KeyedVector<String8, String8> *headers) {
+            const char* url, const KeyedVector<String8, String8> *headers, int audioSessionId) {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
         data.writeInt32(pid);
@@ -75,8 +74,10 @@
                 data.writeString8(headers->valueAt(i));
             }
         }
+        data.writeInt32(audioSessionId);
 
         remote()->transact(CREATE_URL, data, &reply);
+
         return interface_cast<IMediaPlayer>(reply.readStrongBinder());
     }
 
@@ -89,7 +90,8 @@
         return interface_cast<IMediaRecorder>(reply.readStrongBinder());
     }
 
-    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length)
+    virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd,
+            int64_t offset, int64_t length, int audioSessionId)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -98,8 +100,11 @@
         data.writeFileDescriptor(fd);
         data.writeInt64(offset);
         data.writeInt64(length);
+        data.writeInt32(audioSessionId);
+
         remote()->transact(CREATE_FD, data, &reply);
-        return interface_cast<IMediaPlayer>(reply.readStrongBinder());
+
+        return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
     }
 
     virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
@@ -128,14 +133,6 @@
         return interface_cast<IMemory>(reply.readStrongBinder());
     }
 
-    virtual sp<IMemory> snoop()
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
-        remote()->transact(SNOOP, data, &reply);
-        return interface_cast<IMemory>(reply.readStrongBinder());
-    }
-
     virtual sp<IOMX> getOMX() {
         Parcel data, reply;
         data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -166,9 +163,10 @@
                 String8 value = data.readString8();
                 headers.add(key, value);
             }
+            int audioSessionId = data.readInt32();
 
             sp<IMediaPlayer> player = create(
-                    pid, client, url, numHeaders > 0 ? &headers : NULL);
+                    pid, client, url, numHeaders > 0 ? &headers : NULL, audioSessionId);
 
             reply->writeStrongBinder(player->asBinder());
             return NO_ERROR;
@@ -180,7 +178,9 @@
             int fd = dup(data.readFileDescriptor());
             int64_t offset = data.readInt64();
             int64_t length = data.readInt64();
-            sp<IMediaPlayer> player = create(pid, client, fd, offset, length);
+            int audioSessionId = data.readInt32();
+
+            sp<IMediaPlayer> player = create(pid, client, fd, offset, length, audioSessionId);
             reply->writeStrongBinder(player->asBinder());
             return NO_ERROR;
         } break;
@@ -212,12 +212,6 @@
             reply->writeStrongBinder(player->asBinder());
             return NO_ERROR;
         } break;
-        case SNOOP: {
-            CHECK_INTERFACE(IMediaPlayerService, data, reply);
-            sp<IMemory> snooped_audio = snoop();
-            reply->writeStrongBinder(snooped_audio->asBinder());
-            return NO_ERROR;
-        } break;
         case CREATE_MEDIA_RECORDER: {
             CHECK_INTERFACE(IMediaPlayerService, data, reply);
             pid_t pid = data.readInt32();
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 1de9f9b..4eb63e8 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -21,7 +21,7 @@
 #include <binder/Parcel.h>
 #include <surfaceflinger/ISurface.h>
 #include <camera/ICamera.h>
-#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorderClient.h>
 #include <media/IMediaRecorder.h>
 
 namespace android {
@@ -189,7 +189,7 @@
         return reply.readInt32();
     }
 
-    status_t setListener(const sp<IMediaPlayerClient>& listener)
+    status_t setListener(const sp<IMediaRecorderClient>& listener)
     {
         LOGV("setListener(%p)", listener.get());
         Parcel data, reply;
@@ -399,8 +399,8 @@
         case SET_LISTENER: {
             LOGV("SET_LISTENER");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
-            sp<IMediaPlayerClient> listener =
-                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+            sp<IMediaRecorderClient> listener =
+                interface_cast<IMediaRecorderClient>(data.readStrongBinder());
             reply->writeInt32(setListener(listener));
             return NO_ERROR;
         } break;
diff --git a/media/libmedia/IMediaRecorderClient.cpp b/media/libmedia/IMediaRecorderClient.cpp
new file mode 100644
index 0000000..ff235c9
--- /dev/null
+++ b/media/libmedia/IMediaRecorderClient.cpp
@@ -0,0 +1,70 @@
+/*
+**
+** Copyright 2010, 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.
+*/
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <media/IMediaRecorderClient.h>
+
+namespace android {
+
+enum {
+    NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpMediaRecorderClient: public BpInterface<IMediaRecorderClient>
+{
+public:
+    BpMediaRecorderClient(const sp<IBinder>& impl)
+        : BpInterface<IMediaRecorderClient>(impl)
+    {
+    }
+
+    virtual void notify(int msg, int ext1, int ext2)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorderClient::getInterfaceDescriptor());
+        data.writeInt32(msg);
+        data.writeInt32(ext1);
+        data.writeInt32(ext2);
+        remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaRecorderClient, "android.media.IMediaRecorderClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaRecorderClient::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case NOTIFY: {
+            CHECK_INTERFACE(IMediaRecorderClient, data, reply);
+            int msg = data.readInt32();
+            int ext1 = data.readInt32();
+            int ext2 = data.readInt32();
+            notify(msg, ext1, ext2);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 01b6737..f3804b8 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -57,7 +57,7 @@
         return NULL;
     }
 
-    jfieldID surfaceID = env->GetFieldID(surfaceClass, "mSurface", "I");
+    jfieldID surfaceID = env->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
     if (surfaceID == NULL) {
         LOGE("Can't find Surface.mSurface");
         return NULL;
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 1263373..3869389 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -272,7 +272,7 @@
 }
 
 /*static*/ MediaProfiles::CamcorderProfile*
-MediaProfiles::createCamcorderProfile(const char **atts)
+MediaProfiles::createCamcorderProfile(int cameraId, const char **atts)
 {
     CHECK(!strcmp("quality",    atts[0]) &&
           !strcmp("fileFormat", atts[2]) &&
@@ -287,16 +287,47 @@
     CHECK(fileFormat != -1);
 
     MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+    profile->mCameraId = cameraId;
     profile->mFileFormat = static_cast<output_format>(fileFormat);
     profile->mQuality = static_cast<camcorder_quality>(quality);
     profile->mDuration = atoi(atts[5]);
     return profile;
 }
 
-/*static*/ int
-MediaProfiles::getImageEncodingQualityLevel(const char** atts)
+MediaProfiles::ImageEncodingQualityLevels*
+MediaProfiles::findImageEncodingQualityLevels(int cameraId) const
+{
+    int n = mImageEncodingQualityLevels.size();
+    for (int i = 0; i < n; i++) {
+        ImageEncodingQualityLevels *levels = mImageEncodingQualityLevels[i];
+        if (levels->mCameraId == cameraId) {
+            return levels;
+        }
+    }
+    return NULL;
+}
+
+void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts)
 {
     CHECK(!strcmp("quality", atts[0]));
+    int quality = atoi(atts[1]);
+    LOGV("%s: cameraId=%d, quality=%d\n", __func__, cameraId, quality);
+    ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
+
+    if (levels == NULL) {
+        levels = new ImageEncodingQualityLevels();
+        levels->mCameraId = cameraId;
+        mImageEncodingQualityLevels.add(levels);
+    }
+
+    levels->mLevels.add(quality);
+}
+
+/*static*/ int
+MediaProfiles::getCameraId(const char** atts)
+{
+    if (!atts[0]) return 0;  // default cameraId = 0
+    CHECK(!strcmp("cameraId", atts[0]));
     return atoi(atts[1]);
 }
 
@@ -322,10 +353,13 @@
         profiles->mAudioDecoders.add(createAudioDecoderCap(atts));
     } else if (strcmp("EncoderOutputFileFormat", name) == 0) {
         profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts));
+    } else if (strcmp("CamcorderProfiles", name) == 0) {
+        profiles->mCurrentCameraId = getCameraId(atts);
     } else if (strcmp("EncoderProfile", name) == 0) {
-        profiles->mCamcorderProfiles.add(createCamcorderProfile(atts));
+        profiles->mCamcorderProfiles.add(
+            createCamcorderProfile(profiles->mCurrentCameraId, atts));
     } else if (strcmp("ImageEncoding", name) == 0) {
-        profiles->mImageEncodingQualityLevels.add(getImageEncodingQualityLevel(atts));
+        profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
     }
 }
 
@@ -383,7 +417,8 @@
         new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20);
 
     AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
-    CamcorderProfile *profile = new CamcorderProfile;
+    CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+    profile->mCameraId = 0;
     profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
     profile->mQuality = CAMCORDER_QUALITY_HIGH;
     profile->mDuration = 60;
@@ -402,6 +437,7 @@
         new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
 
     MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+    profile->mCameraId = 0;
     profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
     profile->mQuality = CAMCORDER_QUALITY_LOW;
     profile->mDuration = 30;
@@ -458,9 +494,12 @@
 /*static*/ void
 MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
 {
-    profiles->mImageEncodingQualityLevels.add(70);
-    profiles->mImageEncodingQualityLevels.add(80);
-    profiles->mImageEncodingQualityLevels.add(90);
+    ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels();
+    levels->mCameraId = 0;
+    levels->mLevels.add(70);
+    levels->mLevels.add(80);
+    levels->mLevels.add(90);
+    profiles->mImageEncodingQualityLevels.add(levels);
 }
 
 /*static*/ MediaProfiles*
@@ -629,19 +668,24 @@
     return decoders;  // copy out
 }
 
-int MediaProfiles::getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const
+int MediaProfiles::getCamcorderProfileParamByName(const char *name,
+                                                  int cameraId,
+                                                  camcorder_quality quality) const
 {
-    LOGV("getCamcorderProfileParamByName: %s for quality %d", name, quality);
+    LOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d",
+         name, cameraId, quality);
 
     int index = -1;
     for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
-        if (mCamcorderProfiles[i]->mQuality == quality) {
+        if (mCamcorderProfiles[i]->mCameraId == cameraId &&
+            mCamcorderProfiles[i]->mQuality == quality) {
             index = i;
             break;
         }
     }
     if (index == -1) {
-        LOGE("The given camcorder profile quality %d is not found", quality);
+        LOGE("The given camcorder profile camera %d quality %d is not found",
+             cameraId, quality);
         return -1;
     }
 
@@ -657,13 +701,18 @@
     if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels;
     if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate;
 
-    LOGE("The given camcorder profile param name %s is not found", name);
+    LOGE("The given camcorder profile param id %d name %s is not found", cameraId, name);
     return -1;
 }
 
-Vector<int> MediaProfiles::getImageEncodingQualityLevels() const
+Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const
 {
-    return mImageEncodingQualityLevels;  // copy out
+    Vector<int> result;
+    ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
+    if (levels != NULL) {
+        result = levels->mLevels;  // copy out
+    }
+    return result;
 }
 
 MediaProfiles::~MediaProfiles()
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 843a8fd..6f581d3 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaScanner"
+#include <utils/Log.h>
+
 #include <media/mediascanner.h>
 
 #include <sys/stat.h>
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
new file mode 100644
index 0000000..32cdb49
--- /dev/null
+++ b/media/libmedia/Visualizer.cpp
@@ -0,0 +1,330 @@
+/*
+**
+** Copyright 2010, 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 "Visualizer"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <media/Visualizer.h>
+
+extern "C" {
+#define FLOATING_POINT 1
+#include "fftwrap.h"
+}
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+Visualizer::Visualizer (int32_t priority,
+         effect_callback_t cbf,
+         void* user,
+         int sessionId)
+    :   AudioEffect(SL_IID_VISUALIZATION, NULL, priority, cbf, user, sessionId),
+        mCaptureRate(CAPTURE_RATE_DEF),
+        mCaptureSize(CAPTURE_SIZE_DEF),
+        mSampleRate(44100000),
+        mCaptureCallBack(NULL),
+        mCaptureCbkUser(NULL)
+{
+    initCaptureSize();
+    if (mCaptureSize != 0) {
+        mFftTable = spx_fft_init(mCaptureSize);
+    } else {
+        mFftTable = NULL;
+    }
+}
+
+Visualizer::~Visualizer()
+{
+    if (mFftTable != NULL) {
+        spx_fft_destroy(mFftTable);
+    }
+}
+
+status_t Visualizer::setEnabled(bool enabled)
+{
+    Mutex::Autolock _l(mLock);
+
+    sp<CaptureThread> t = mCaptureThread;
+    if (t != 0) {
+        if (enabled) {
+            if (t->exitPending()) {
+                if (t->requestExitAndWait() == WOULD_BLOCK) {
+                    LOGE("Visualizer::enable() called from thread");
+                    return INVALID_OPERATION;
+                }
+            }
+        }
+        t->mLock.lock();
+     }
+
+    status_t status = AudioEffect::setEnabled(enabled);
+
+    if (status == NO_ERROR) {
+        if (t != 0) {
+            if (enabled) {
+                t->run("AudioTrackThread");
+            } else {
+                t->requestExit();
+            }
+        }
+    }
+
+    if (t != 0) {
+        t->mLock.unlock();
+    }
+
+    return status;
+}
+
+status_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate)
+{
+    if (rate > CAPTURE_RATE_MAX) {
+        return BAD_VALUE;
+    }
+    Mutex::Autolock _l(mLock);
+
+    if (mEnabled) {
+        return INVALID_OPERATION;
+    }
+
+    sp<CaptureThread> t = mCaptureThread;
+    if (t != 0) {
+        t->mLock.lock();
+    }
+    mCaptureThread.clear();
+    mCaptureCallBack = cbk;
+    mCaptureCbkUser = user;
+    mCaptureFlags = flags;
+    mCaptureRate = rate;
+
+    if (t != 0) {
+        t->mLock.unlock();
+    }
+
+    if (cbk != NULL) {
+        mCaptureThread = new CaptureThread(*this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
+        if (mCaptureThread == 0) {
+            LOGE("Could not create callback thread");
+            return NO_INIT;
+        }
+    }
+    LOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
+            rate, mCaptureThread.get(), mCaptureFlags);
+    return NO_ERROR;
+}
+
+status_t Visualizer::setCaptureSize(uint32_t size)
+{
+    if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
+        size < VISUALIZER_CAPTURE_SIZE_MIN ||
+        AudioSystem::popCount(size) != 1) {
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mLock);
+    if (mEnabled) {
+        return INVALID_OPERATION;
+    }
+
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = sizeof(uint32_t);
+    p->vsize = sizeof(uint32_t);
+    *(int32_t *)p->data = VISU_PARAM_CAPTURE_SIZE;
+    *((int32_t *)p->data + 1)= size;
+    status_t status = setParameter(p);
+
+    LOGV("setCaptureSize size %d  status %d p->status %d", size, status, p->status);
+
+    if (status == NO_ERROR) {
+        status = p->status;
+    }
+    if (status == NO_ERROR) {
+        mCaptureSize = size;
+        if (mFftTable != NULL) {
+            spx_fft_destroy(mFftTable);
+        }
+        mFftTable = spx_fft_init(mCaptureSize);
+        LOGV("setCaptureSize size %d mFftTable %p", mCaptureSize, mFftTable);
+    }
+
+    return status;
+}
+
+status_t Visualizer::getWaveForm(uint8_t *waveform)
+{
+    if (waveform == NULL) {
+        return BAD_VALUE;
+    }
+    if (mCaptureSize == 0) {
+        return NO_INIT;
+    }
+
+    status_t status = NO_ERROR;
+    if (mEnabled) {
+        uint32_t replySize = mCaptureSize;
+        status_t status = command(VISU_CMD_CAPTURE, 0, NULL, &replySize, waveform);
+        if (replySize == 0) {
+            status = NOT_ENOUGH_DATA;
+        }
+    } else {
+        memset(waveform, 0x80, mCaptureSize);
+    }
+    return status;
+}
+
+status_t Visualizer::getFft(uint8_t *fft)
+{
+    if (fft == NULL) {
+        return BAD_VALUE;
+    }
+    if (mCaptureSize == 0) {
+        return NO_INIT;
+    }
+
+    status_t status = NO_ERROR;
+    if (mEnabled) {
+        uint8_t buf[mCaptureSize];
+        status_t status = getWaveForm(buf);
+        if (status == NO_ERROR) {
+            status = doFft(fft, buf);
+        }
+    } else {
+        memset(fft, 0, mCaptureSize);
+    }
+    return status;
+}
+
+status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
+{
+    if (mFftTable == NULL) {
+        return NO_INIT;
+    }
+
+    float fsrc[mCaptureSize];
+    for (uint32_t i = 0; i < mCaptureSize; i++) {
+        fsrc[i] = (int16_t)(waveform[i] ^ 0x80) << 8;
+    }
+    float fdst[mCaptureSize];
+    spx_fft_float(mFftTable, fsrc, fdst);
+    for (uint32_t i = 0; i < mCaptureSize; i++) {
+        fft[i] = (uint8_t)((int32_t)fdst[i] >> 8);
+    }
+    return NO_ERROR;
+}
+
+void Visualizer::periodicCapture()
+{
+    Mutex::Autolock _l(mLock);
+    LOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
+            this, mCaptureCallBack, mCaptureFlags);
+    if (mCaptureCallBack != NULL &&
+        (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) &&
+        mCaptureSize != 0) {
+        uint8_t waveform[mCaptureSize];
+        status_t status = getWaveForm(waveform);
+        if (status != NO_ERROR) {
+            return;
+        }
+        uint8_t fft[mCaptureSize];
+        if (mCaptureFlags & CAPTURE_FFT) {
+            status = doFft(fft, waveform);
+        }
+        if (status != NO_ERROR) {
+            return;
+        }
+        uint8_t *wavePtr = NULL;
+        uint8_t *fftPtr = NULL;
+        uint32_t waveSize = 0;
+        uint32_t fftSize = 0;
+        if (mCaptureFlags & CAPTURE_WAVEFORM) {
+            wavePtr = waveform;
+            waveSize = mCaptureSize;
+        }
+        if (mCaptureFlags & CAPTURE_FFT) {
+            fftPtr = fft;
+            fftSize = mCaptureSize;
+        }
+        mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate);
+    }
+}
+
+uint32_t Visualizer::initCaptureSize()
+{
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t *p = (effect_param_t *)buf32;
+
+    p->psize = sizeof(uint32_t);
+    p->vsize = sizeof(uint32_t);
+    *(int32_t *)p->data = VISU_PARAM_CAPTURE_SIZE;
+    status_t status = getParameter(p);
+
+    if (status == NO_ERROR) {
+        status = p->status;
+    }
+
+    uint32_t size = 0;
+    if (status == NO_ERROR) {
+        size = *((int32_t *)p->data + 1);
+    }
+    mCaptureSize = size;
+
+    LOGV("initCaptureSize size %d status %d", mCaptureSize, status);
+
+    return size;
+}
+
+//-------------------------------------------------------------------------
+
+Visualizer::CaptureThread::CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava)
+    : Thread(bCanCallJava), mReceiver(receiver)
+{
+    mSleepTimeUs = 1000000000 / captureRate;
+    LOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
+}
+
+bool Visualizer::CaptureThread::threadLoop()
+{
+    LOGV("CaptureThread %p enter", this);
+    while (!exitPending())
+    {
+        usleep(mSleepTimeUs);
+        mReceiver.periodicCapture();
+    }
+    LOGV("CaptureThread %p exiting", this);
+    return false;
+}
+
+status_t Visualizer::CaptureThread::readyToRun()
+{
+    return NO_ERROR;
+}
+
+void Visualizer::CaptureThread::onFirstRef()
+{
+}
+
+}; // namespace android
+
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index c6bbbcc..1c99ae5 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -55,6 +55,7 @@
     mLeftVolume = mRightVolume = 1.0;
     mVideoWidth = mVideoHeight = 0;
     mLockThreadId = 0;
+    mAudioSessionId = AudioSystem::newAudioSessionId();
 }
 
 MediaPlayer::~MediaPlayer()
@@ -137,7 +138,7 @@
         const sp<IMediaPlayerService>& service(getMediaPlayerService());
         if (service != 0) {
             sp<IMediaPlayer> player(
-                    service->create(getpid(), this, url, headers));
+                    service->create(getpid(), this, url, headers, mAudioSessionId));
             err = setDataSource(player);
         }
     }
@@ -150,7 +151,7 @@
     status_t err = UNKNOWN_ERROR;
     const sp<IMediaPlayerService>& service(getMediaPlayerService());
     if (service != 0) {
-        sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length));
+        sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));
         err = setDataSource(player);
     }
     return err;
@@ -269,6 +270,7 @@
                     MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
         mPlayer->setLooping(mLoop);
         mPlayer->setVolume(mLeftVolume, mRightVolume);
+        mPlayer->setAuxEffectSendLevel(mSendLevel);
         mCurrentState = MEDIA_PLAYER_STARTED;
         status_t ret = mPlayer->start();
         if (ret != NO_ERROR) {
@@ -501,6 +503,52 @@
     return OK;
 }
 
+status_t MediaPlayer::setAudioSessionId(int sessionId)
+{
+    LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
+    Mutex::Autolock _l(mLock);
+    if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
+        LOGE("setAudioSessionId called in state %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+    if (sessionId < 0) {
+        return BAD_VALUE;
+    }
+    mAudioSessionId = sessionId;
+    return NO_ERROR;
+}
+
+int MediaPlayer::getAudioSessionId()
+{
+    Mutex::Autolock _l(mLock);
+    return mAudioSessionId;
+}
+
+status_t MediaPlayer::setAuxEffectSendLevel(float level)
+{
+    LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
+    Mutex::Autolock _l(mLock);
+    mSendLevel = level;
+    if (mPlayer != 0) {
+        return mPlayer->setAuxEffectSendLevel(level);
+    }
+    return OK;
+}
+
+status_t MediaPlayer::attachAuxEffect(int effectId)
+{
+    LOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
+    Mutex::Autolock _l(mLock);
+    if (mPlayer == 0 ||
+        (mCurrentState & MEDIA_PLAYER_IDLE) ||
+        (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
+        LOGE("attachAuxEffect called in state %d", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    return mPlayer->attachAuxEffect(effectId);
+}
+
 void MediaPlayer::notify(int msg, int ext1, int ext2)
 {
     LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
@@ -636,61 +684,4 @@
 
 }
 
-extern "C" {
-#define FLOATING_POINT 1
-#include "fftwrap.h"
-}
-
-static void *ffttable = NULL;
-
-// peeks at the audio data and fills 'data' with the requested kind
-// (currently kind=0 returns mono 16 bit PCM data, and kind=1 returns
-// 256 point FFT data). Return value is number of samples returned,
-// which may be 0.
-/*static*/ int MediaPlayer::snoop(short* data, int len, int kind) {
-
-    sp<IMemory> p;
-    const sp<IMediaPlayerService>& service = getMediaPlayerService();
-    if (service != 0) {
-        // Take a peek at the waveform. The returned data consists of 16 bit mono PCM data.
-        p = service->snoop();
-
-        if (p == NULL) {
-            return 0;
-        }
-
-        if (kind == 0) { // return waveform data
-            int plen = p->size();
-            len *= 2; // number of shorts -> number of bytes
-            short *src = (short*) p->pointer();
-            if (plen > len) {
-                plen = len;
-            }
-            memcpy(data, src, plen);
-            return plen / sizeof(short); // return number of samples
-        } else if (kind == 1) {
-            // TODO: use a more efficient FFT
-            // Right now this uses the speex library, which is compiled to do a float FFT
-            if (!ffttable) ffttable = spx_fft_init(512);
-            short *usrc = (short*) p->pointer();
-            float fsrc[512];
-            for (int i=0;i<512;i++)
-                fsrc[i] = usrc[i];
-            float fdst[512];
-            spx_fft_float(ffttable, fsrc, fdst);
-            if (len > 512) {
-                len = 512;
-            }
-            len /= 2; // only half the output data is valid
-            for (int i=0; i < len; i++)
-                data[i] = fdst[i];
-            return len;
-        }
-
-    } else {
-        LOGE("Unable to locate media service");
-    }
-    return 0;
-}
-
 }; // namespace android
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index cf97b23..8f010c9 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -11,21 +11,11 @@
     MediaPlayerService.cpp      \
     MetadataRetrieverClient.cpp \
     TestPlayerStub.cpp          \
-    VorbisPlayer.cpp            \
-    VorbisMetadataRetriever.cpp \
-    MidiMetadataRetriever.cpp 	\
-    MidiFile.cpp
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_SRC_FILES +=                      \
-    StagefrightPlayer.cpp               \
+    MidiMetadataRetriever.cpp   \
+    MidiFile.cpp                \
+    StagefrightPlayer.cpp       \
     StagefrightRecorder.cpp
 
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT=1
-
-endif
-
 ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
 LOCAL_LDLIBS += -ldl -lpthread
 endif
@@ -37,6 +27,7 @@
 	libvorbisidec         			\
 	libsonivox            			\
 	libmedia              			\
+	libcamera_client      			\
 	libandroid_runtime    			\
 	libstagefright        			\
 	libstagefright_omx    			\
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 3e1f4a5..b5972e7 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -56,7 +56,6 @@
 #include "MetadataRetrieverClient.h"
 
 #include "MidiFile.h"
-#include "VorbisPlayer.h"
 #include <media/PVPlayer.h>
 #include "TestPlayerStub.h"
 #include "StagefrightPlayer.h"
@@ -197,8 +196,6 @@
         {".rtttl", SONIVOX_PLAYER},
         {".rtx", SONIVOX_PLAYER},
         {".ota", SONIVOX_PLAYER},
-        {".ogg", VORBIS_PLAYER},
-        {".oga", VORBIS_PLAYER},
 #ifndef NO_OPENCORE
         {".wma", PV_PLAYER},
         {".wmv", PV_PLAYER},
@@ -228,14 +225,10 @@
 
 sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
 {
-#ifndef NO_OPENCORE
     sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid);
     wp<MediaRecorderClient> w = recorder;
     Mutex::Autolock lock(mLock);
     mMediaRecorderClients.add(w);
-#else
-    sp<MediaRecorderClient> recorder = NULL;
-#endif
     LOGV("Create new media recorder client from pid %d", pid);
     return recorder;
 }
@@ -256,11 +249,12 @@
 
 sp<IMediaPlayer> MediaPlayerService::create(
         pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
-        const KeyedVector<String8, String8> *headers)
+        const KeyedVector<String8, String8> *headers, int audioSessionId)
 {
     int32_t connId = android_atomic_inc(&mNextConnId);
-    sp<Client> c = new Client(this, pid, connId, client);
-    LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
+    sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+    LOGV("Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d",
+            connId, pid, url, connId, audioSessionId);
     if (NO_ERROR != c->setDataSource(url, headers))
     {
         c.clear();
@@ -273,12 +267,12 @@
 }
 
 sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
-        int fd, int64_t offset, int64_t length)
+        int fd, int64_t offset, int64_t length, int audioSessionId)
 {
     int32_t connId = android_atomic_inc(&mNextConnId);
-    sp<Client> c = new Client(this, pid, connId, client);
-    LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld",
-            connId, pid, fd, offset, length);
+    sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+    LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d",
+            connId, pid, fd, offset, length, audioSessionId);
     if (NO_ERROR != c->setDataSource(fd, offset, length)) {
         c.clear();
     } else {
@@ -335,6 +329,10 @@
     snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
             mMsecsPerFrame, mLatency);
     result.append(buffer);
+    snprintf(buffer, 255, "  aux effect id(%d), send level (%f)\n",
+            mAuxEffectId, mSendLevel);
+    result.append(buffer);
+
     ::write(fd, result.string(), result.size());
     if (mTrack != 0) {
         mTrack->dump(fd, args);
@@ -517,11 +515,17 @@
             sp<Client> c = mClients[i].promote();
             if (c != 0) c->dump(fd, args);
         }
-        for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
-            result.append(" MediaRecorderClient\n");
-            sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
-            snprintf(buffer, 255, "  pid(%d)\n\n", c->mPid);
-            result.append(buffer);
+        if (mMediaRecorderClients.size() == 0) {
+                result.append(" No media recorder client\n\n");
+        } else {
+            for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
+                sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
+                snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n", c->mPid);
+                result.append(buffer);
+                write(fd, result.string(), result.size());
+                result = "\n";
+                c->dump(fd, args);
+            }
         }
 
         result.append(" Files opened and/or mapped:\n");
@@ -613,7 +617,7 @@
 }
 
 MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,
-        int32_t connId, const sp<IMediaPlayerClient>& client)
+        int32_t connId, const sp<IMediaPlayerClient>& client, int audioSessionId)
 {
     LOGV("Client(%d) constructor", connId);
     mPid = pid;
@@ -622,6 +626,8 @@
     mClient = client;
     mLoop = false;
     mStatus = NO_INIT;
+    mAudioSessionId = audioSessionId;
+
 #if CALLBACK_ANTAGONIZER
     LOGD("create Antagonizer");
     mAntagonizer = new Antagonizer(notify, this);
@@ -667,37 +673,9 @@
 }
 
 static player_type getDefaultPlayerType() {
-#if BUILD_WITH_FULL_STAGEFRIGHT
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("media.stagefright.enable-player", value, NULL)
-        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
-        return STAGEFRIGHT_PLAYER;
-    }
-#endif
-
-    return PV_PLAYER;
+    return STAGEFRIGHT_PLAYER;
 }
 
-// By default we use the VORBIS_PLAYER for vorbis playback (duh!),
-// but if the magic property is set we will use our new experimental
-// stagefright code instead.
-static player_type OverrideStagefrightForVorbis(player_type player) {
-    if (player != VORBIS_PLAYER) {
-        return player;
-    }
-
-#if BUILD_WITH_FULL_STAGEFRIGHT
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("media.stagefright.enable-vorbis", value, NULL)
-        && (!strcmp(value, "1") || !strcmp(value, "true"))) {
-        return STAGEFRIGHT_PLAYER;
-    }
-#endif
-
-    return VORBIS_PLAYER;
-}
-
-
 player_type getPlayerType(int fd, int64_t offset, int64_t length)
 {
     char buf[20];
@@ -709,7 +687,7 @@
 
     // Ogg vorbis?
     if (ident == 0x5367674f) // 'OggS'
-        return OverrideStagefrightForVorbis(VORBIS_PLAYER);
+        return STAGEFRIGHT_PLAYER;
 
 #ifndef NO_OPENCORE
     if (ident == 0x75b22630) {
@@ -745,41 +723,28 @@
         return TEST_PLAYER;
     }
 
-    bool useStagefrightForHTTP = false;
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("media.stagefright.enable-http", value, NULL)
-        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
-        useStagefrightForHTTP = true;
-    }
-
     // use MidiFile for MIDI extensions
     int lenURL = strlen(url);
     for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
         int len = strlen(FILE_EXTS[i].extension);
         int start = lenURL - len;
         if (start > 0) {
-            if (!strncmp(url + start, FILE_EXTS[i].extension, len)) {
-                if (FILE_EXTS[i].playertype == VORBIS_PLAYER
-                    && !strncasecmp(url, "http://", 7)
-                    && useStagefrightForHTTP) {
-                    return STAGEFRIGHT_PLAYER;
-                }
-                return OverrideStagefrightForVorbis(FILE_EXTS[i].playertype);
+            if (!strncasecmp(url + start, FILE_EXTS[i].extension, len)) {
+                return FILE_EXTS[i].playertype;
             }
         }
     }
 
-    if (!strncasecmp(url, "http://", 7)) {
-        if (!useStagefrightForHTTP) {
+    if (!strncasecmp(url, "rtsp://", 7)) {
+        char value[PROPERTY_VALUE_MAX];
+        if (!property_get("media.stagefright.enable-rtsp", value, NULL)
+            || (strcmp(value, "1") && strcasecmp(value, "true"))) {
+            // For now, we're going to use PV for rtsp-based playback
+            // by default until we can clear up a few more issues.
             return PV_PLAYER;
         }
     }
 
-    // Use PV_PLAYER for rtsp for now
-    if (!strncasecmp(url, "rtsp://", 7)) {
-        return PV_PLAYER;
-    }
-
     return getDefaultPlayerType();
 }
 
@@ -798,16 +763,10 @@
             LOGV(" create MidiFile");
             p = new MidiFile();
             break;
-        case VORBIS_PLAYER:
-            LOGV(" create VorbisPlayer");
-            p = new VorbisPlayer();
-            break;
-#if BUILD_WITH_FULL_STAGEFRIGHT
         case STAGEFRIGHT_PLAYER:
             LOGV(" create StagefrightPlayer");
             p = new StagefrightPlayer;
             break;
-#endif
         case TEST_PLAYER:
             LOGV("Create Test Player stub");
             p = new TestPlayerStub();
@@ -870,7 +829,7 @@
         if (p == NULL) return NO_INIT;
 
         if (!p->hardwareOutput()) {
-            mAudioOutput = new AudioOutput();
+            mAudioOutput = new AudioOutput(mAudioSessionId);
             static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
         }
 
@@ -920,7 +879,7 @@
     if (p == NULL) return NO_INIT;
 
     if (!p->hardwareOutput()) {
-        mAudioOutput = new AudioOutput();
+        mAudioOutput = new AudioOutput(mAudioSessionId);
         static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
     }
 
@@ -1138,6 +1097,21 @@
     return NO_ERROR;
 }
 
+status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
+{
+    LOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
+    Mutex::Autolock l(mLock);
+    if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
+    return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
+{
+    LOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
+    Mutex::Autolock l(mLock);
+    if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
+    return NO_ERROR;
+}
 
 void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
 {
@@ -1316,111 +1290,22 @@
     return mem;
 }
 
-/*
- * Avert your eyes, ugly hack ahead.
- * The following is to support music visualizations.
- */
-
-static const int NUMVIZBUF = 32;
-static const int VIZBUFFRAMES = 1024;
-static const int BUFTIMEMSEC = NUMVIZBUF * VIZBUFFRAMES * 1000 / 44100;
-static const int TOTALBUFTIMEMSEC = NUMVIZBUF * BUFTIMEMSEC;
-
-static bool gotMem = false;
-static sp<MemoryHeapBase> heap; 
-static sp<MemoryBase> mem[NUMVIZBUF];
-static uint64_t endTime;
-static uint64_t lastReadTime;
-static uint64_t lastWriteTime;
-static int writeIdx = 0;
-
-static void allocVizBufs() {
-    if (!gotMem) {
-        heap = new MemoryHeapBase(NUMVIZBUF * VIZBUFFRAMES * 2, 0, "snooper");
-        for (int i=0;i<NUMVIZBUF;i++) {
-            mem[i] = new MemoryBase(heap, VIZBUFFRAMES * 2 * i, VIZBUFFRAMES * 2);
-        }
-        endTime = 0;
-        gotMem = true;
-    }
-}
-
-
-/*
- * Get a buffer of audio data that is about to be played.
- * We don't synchronize this because in practice the writer
- * is ahead of the reader, and even if we did happen to catch
- * a buffer while it's being written, it's just a visualization,
- * so no harm done.
- */
-static sp<MemoryBase> getVizBuffer() {
-
-    allocVizBufs();
-
-    lastReadTime = uptimeMillis();
-
-    // if there is no recent buffer (yet), just return empty handed
-    if (lastWriteTime + TOTALBUFTIMEMSEC < lastReadTime) {
-        //LOGI("@@@@    no audio data to look at yet: %d + %d < %d", (int)lastWriteTime, TOTALBUFTIMEMSEC, (int)lastReadTime);
-        return NULL;
-    }
-
-    int timedelta = endTime - lastReadTime;
-    if (timedelta < 0) timedelta = 0;
-    int framedelta = timedelta * 44100 / 1000;
-    int headIdx = (writeIdx - framedelta) / VIZBUFFRAMES - 1;
-    while (headIdx < 0) {
-        headIdx += NUMVIZBUF;
-    }
-    return mem[headIdx];
-}
-
-// Append the data to the vizualization buffer
-static void makeVizBuffers(const char *data, int len, uint64_t time) {
-
-    allocVizBufs();
-
-    uint64_t startTime = time;
-    const int frameSize = 4; // 16 bit stereo sample is 4 bytes
-    int offset = writeIdx;
-    int maxoff = heap->getSize() / 2; // in shorts
-    short *base = (short*)heap->getBase();
-    short *src = (short*)data;
-    while (len > 0) {
-        
-        // Degrade quality by mixing to mono and clearing the lowest 3 bits.
-        // This should still be good enough for a visualization
-        base[offset++] = ((int(src[0]) + int(src[1])) >> 1) & ~0x7;
-        src += 2;
-        len -= frameSize;
-        if (offset >= maxoff) {
-            offset = 0;
-        }
-    }
-    writeIdx = offset;
-    endTime = time + (len / frameSize) / 44;
-    //LOGI("@@@ stored buffers from %d to %d", uint32_t(startTime), uint32_t(time));
-}
-
-sp<IMemory> MediaPlayerService::snoop()
-{
-    sp<MemoryBase> mem = getVizBuffer();
-    return mem;
-}
-
 
 #undef LOG_TAG
 #define LOG_TAG "AudioSink"
-MediaPlayerService::AudioOutput::AudioOutput()
+MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
     : mCallback(NULL),
-      mCallbackCookie(NULL) {
+      mCallbackCookie(NULL),
+      mSessionId(sessionId) {
+    LOGV("AudioOutput(%d)", sessionId);
     mTrack = 0;
     mStreamType = AudioSystem::MUSIC;
     mLeftVolume = 1.0;
     mRightVolume = 1.0;
     mLatency = 0;
     mMsecsPerFrame = 0;
-    mNumFramesWritten = 0;
+    mAuxEffectId = 0;
+    mSendLevel = 0.0;
     setMinBufferCount();
 }
 
@@ -1503,7 +1388,7 @@
         bufferCount = mMinBufferCount;
 
     }
-    LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+    LOGV("open(%u, %d, %d, %d, %d)", sampleRate, channelCount, format, bufferCount,mSessionId);
     if (mTrack) close();
     int afSampleRate;
     int afFrameCount;
@@ -1528,14 +1413,21 @@
                 frameCount,
                 0 /* flags */,
                 CallbackWrapper,
-                this);
+                this,
+                0,
+                mSessionId);
     } else {
         t = new AudioTrack(
                 mStreamType,
                 sampleRate,
                 format,
                 (channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
-                frameCount);
+                frameCount,
+                0,
+                NULL,
+                NULL,
+                0,
+                mSessionId);
     }
 
     if ((t == 0) || (t->initCheck() != NO_ERROR)) {
@@ -1546,10 +1438,13 @@
 
     LOGV("setVolume");
     t->setVolume(mLeftVolume, mRightVolume);
+
     mMsecsPerFrame = 1.e3 / (float) sampleRate;
     mLatency = t->latency();
     mTrack = t;
-    return NO_ERROR;
+
+    t->setAuxEffectSendLevel(mSendLevel);
+    return t->attachAuxEffect(mAuxEffectId);;
 }
 
 void MediaPlayerService::AudioOutput::start()
@@ -1557,31 +1452,11 @@
     LOGV("start");
     if (mTrack) {
         mTrack->setVolume(mLeftVolume, mRightVolume);
+        mTrack->setAuxEffectSendLevel(mSendLevel);
         mTrack->start();
-        mTrack->getPosition(&mNumFramesWritten);
     }
 }
 
-void MediaPlayerService::AudioOutput::snoopWrite(const void* buffer, size_t size) {
-    // Only make visualization buffers if anyone recently requested visualization data
-    uint64_t now = uptimeMillis();
-    if (lastReadTime + TOTALBUFTIMEMSEC >= now) {
-        // Based on the current play counter, the number of frames written and
-        // the current real time we can calculate the approximate real start
-        // time of the buffer we're about to write.
-        uint32_t pos;
-        mTrack->getPosition(&pos);
-
-        // we're writing ahead by this many frames:
-        int ahead = mNumFramesWritten - pos;
-        //LOGI("@@@ written: %d, playpos: %d, latency: %d", mNumFramesWritten, pos, mTrack->latency());
-        // which is this many milliseconds, assuming 44100 Hz:
-        ahead /= 44;
-
-        makeVizBuffers((const char*)buffer, size, now + ahead + mTrack->latency());
-        lastWriteTime = now;
-    }
-}
 
 
 ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
@@ -1590,9 +1465,7 @@
 
     //LOGV("write(%p, %u)", buffer, size);
     if (mTrack) {
-        snoopWrite(buffer, size);
         ssize_t ret = mTrack->write(buffer, size);
-        mNumFramesWritten += ret / 4; // assume 16 bit stereo
         return ret;
     }
     return NO_INIT;
@@ -1602,7 +1475,6 @@
 {
     LOGV("stop");
     if (mTrack) mTrack->stop();
-    lastWriteTime = 0;
 }
 
 void MediaPlayerService::AudioOutput::flush()
@@ -1615,7 +1487,6 @@
 {
     LOGV("pause");
     if (mTrack) mTrack->pause();
-    lastWriteTime = 0;
 }
 
 void MediaPlayerService::AudioOutput::close()
@@ -1635,6 +1506,26 @@
     }
 }
 
+status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
+{
+    LOGV("setAuxEffectSendLevel(%f)", level);
+    mSendLevel = level;
+    if (mTrack) {
+        return mTrack->setAuxEffectSendLevel(level);
+    }
+    return NO_ERROR;
+}
+
+status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
+{
+    LOGV("attachAuxEffect(%d)", effectId);
+    mAuxEffectId = effectId;
+    if (mTrack) {
+        return mTrack->attachAuxEffect(effectId);
+    }
+    return NO_ERROR;
+}
+
 // static
 void MediaPlayerService::AudioOutput::CallbackWrapper(
         int event, void *cookie, void *info) {
@@ -1651,9 +1542,6 @@
 
     buffer->size = actualSize;
 
-    if (actualSize > 0) {
-        me->snoopWrite(buffer->raw, actualSize);
-    }
 }
 
 #undef LOG_TAG
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 2408c62..a967ee2 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -65,7 +65,7 @@
     class AudioOutput : public MediaPlayerBase::AudioSink
     {
     public:
-                                AudioOutput();
+                                AudioOutput(int sessionId);
         virtual                 ~AudioOutput();
 
         virtual bool            ready() const { return mTrack != NULL; }
@@ -91,6 +91,8 @@
         virtual void            close();
                 void            setAudioStreamType(int streamType) { mStreamType = streamType; }
                 void            setVolume(float left, float right);
+                status_t        setAuxEffectSendLevel(float level);
+                status_t        attachAuxEffect(int effectId);
         virtual status_t        dump(int fd, const Vector<String16>& args) const;
 
         static bool             isOnEmulator();
@@ -108,13 +110,12 @@
         float                   mRightVolume;
         float                   mMsecsPerFrame;
         uint32_t                mLatency;
-
+        int                     mSessionId;
+        float                   mSendLevel;
+        int                     mAuxEffectId;
         static bool             mIsOnEmulator;
         static int              mMinBufferCount;  // 12 for emulator; otherwise 4
 
-        public: // visualization hack support
-        uint32_t                mNumFramesWritten;
-        void                    snoopWrite(const void*, size_t);
     };
 
     class AudioCache : public MediaPlayerBase::AudioSink
@@ -185,12 +186,11 @@
     // House keeping for media player clients
     virtual sp<IMediaPlayer>    create(
             pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
-            const KeyedVector<String8, String8> *headers);
+            const KeyedVector<String8, String8> *headers, int audioSessionId);
 
-    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
+    virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId);
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
-    virtual sp<IMemory>         snoop();
     virtual sp<IOMX>            getOMX();
 
     virtual status_t            dump(int fd, const Vector<String16>& args);
@@ -224,6 +224,8 @@
                                             Parcel *reply);
         virtual status_t        suspend();
         virtual status_t        resume();
+        virtual status_t        setAuxEffectSendLevel(float level);
+        virtual status_t        attachAuxEffect(int effectId);
 
         sp<MediaPlayerBase>     createPlayer(player_type playerType);
 
@@ -237,12 +239,15 @@
                 pid_t           pid() const { return mPid; }
         virtual status_t        dump(int fd, const Vector<String16>& args) const;
 
+                int             getAudioSessionId() { return mAudioSessionId; }
+
     private:
         friend class MediaPlayerService;
                                 Client( const sp<MediaPlayerService>& service,
                                         pid_t pid,
                                         int32_t connId,
-                                        const sp<IMediaPlayerClient>& client);
+                                        const sp<IMediaPlayerClient>& client,
+                                        int audioSessionId);
                                 Client();
         virtual                 ~Client();
 
@@ -271,6 +276,7 @@
                     status_t                    mStatus;
                     bool                        mLoop;
                     int32_t                     mConnId;
+                    int                         mAudioSessionId;
 
         // Metadata filters.
         media::Metadata::Filter mMetadataAllow;  // protected by mLock
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 12de0d9..73862c3 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -294,13 +294,11 @@
     LOGV("Client constructor");
     mPid = pid;
 
-#if BUILD_WITH_FULL_STAGEFRIGHT
     char value[PROPERTY_VALUE_MAX];
     if (property_get("media.stagefright.enable-record", value, NULL)
         && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
         mRecorder = new StagefrightRecorder;
     } else
-#endif
 #ifndef NO_OPENCORE
     {
         mRecorder = new PVMediaRecorder();
@@ -320,7 +318,7 @@
     release();
 }
 
-status_t MediaRecorderClient::setListener(const sp<IMediaPlayerClient>& listener)
+status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listener)
 {
     LOGV("setListener");
     Mutex::Autolock lock(mLock);
@@ -331,5 +329,12 @@
     return mRecorder->setListener(listener);
 }
 
+status_t MediaRecorderClient::dump(int fd, const Vector<String16>& args) const {
+    if (mRecorder != NULL) {
+        return mRecorder->dump(fd, args);
+    }
+    return OK;
+}
+
 }; // namespace android
 
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 805005d..1d1913d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -28,7 +28,7 @@
 class MediaRecorderClient : public BnMediaRecorder
 {
 public:
-    virtual	    status_t		setCamera(const sp<ICamera>& camera);
+    virtual     status_t        setCamera(const sp<ICamera>& camera);
     virtual     status_t        setPreviewSurface(const sp<ISurface>& surface);
     virtual     status_t        setVideoSource(int vs);
     virtual     status_t        setAudioSource(int as);
@@ -40,26 +40,27 @@
     virtual     status_t        setVideoSize(int width, int height);
     virtual     status_t        setVideoFrameRate(int frames_per_second);
     virtual     status_t        setParameters(const String8& params);
-    virtual     status_t        setListener(const sp<IMediaPlayerClient>& listener);
+    virtual     status_t        setListener(const sp<IMediaRecorderClient>& listener);
     virtual     status_t        prepare();
     virtual     status_t        getMaxAmplitude(int* max);
     virtual     status_t        start();
     virtual     status_t        stop();
-    virtual	    status_t        reset();
+    virtual     status_t        reset();
     virtual     status_t        init();
     virtual     status_t        close();
     virtual     status_t        release();
 
+    virtual     status_t        dump(int fd, const Vector<String16>& args) const;
 private:
-    friend class                 MediaPlayerService;  // for accessing private constructor
+    friend class                MediaPlayerService;  // for accessing private constructor
 
-                                 MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid);
-    virtual 		         ~MediaRecorderClient();
+                                MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid);
+    virtual                     ~MediaRecorderClient();
 
-    pid_t			 mPid;
-    Mutex			 mLock;
-    MediaRecorderBase            *mRecorder;
-    sp<MediaPlayerService>       mMediaPlayerService;
+    pid_t                       mPid;
+    Mutex                       mLock;
+    MediaRecorderBase           *mRecorder;
+    sp<MediaPlayerService>      mMediaPlayerService;
 };
 
 }; // namespace android
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 550b84d..ca229fa 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -37,7 +37,6 @@
 #include <media/MediaPlayerInterface.h>
 #include <media/PVMetadataRetriever.h>
 #include <private/media/VideoFrame.h>
-#include "VorbisMetadataRetriever.h"
 #include "MidiMetadataRetriever.h"
 #include "MetadataRetrieverClient.h"
 #include "StagefrightMetadataRetriever.h"
@@ -103,30 +102,17 @@
 {
     sp<MediaMetadataRetrieverBase> p;
     switch (playerType) {
-#if BUILD_WITH_FULL_STAGEFRIGHT
         case STAGEFRIGHT_PLAYER:
         {
-            char value[PROPERTY_VALUE_MAX];
-            if (property_get("media.stagefright.enable-meta", value, NULL)
-                && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
-                LOGV("create StagefrightMetadataRetriever");
-                p = new StagefrightMetadataRetriever;
-                break;
-            }
-
-            // fall through
+            p = new StagefrightMetadataRetriever;
+            break;
         }
-#endif
 #ifndef NO_OPENCORE
         case PV_PLAYER:
             LOGV("create pv metadata retriever");
             p = new PVMetadataRetriever();
             break;
 #endif
-        case VORBIS_PLAYER:
-            LOGV("create vorbis metadata retriever");
-            p = new VorbisMetadataRetriever();
-            break;
         case SONIVOX_PLAYER:
             LOGV("create midi metadata retriever");
             p = new MidiMetadataRetriever();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 531fd11..f26676d 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -20,6 +20,7 @@
 
 #include "StagefrightRecorder.h"
 
+#include <binder/IPCThreadState.h>
 #include <media/stagefright/AudioSource.h>
 #include <media/stagefright/AMRWriter.h>
 #include <media/stagefright/CameraSource.h>
@@ -29,17 +30,28 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
+#include <media/MediaProfiles.h>
 #include <camera/ICamera.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
 #include <surfaceflinger/ISurface.h>
 #include <utils/Errors.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
 
 namespace android {
 
-StagefrightRecorder::StagefrightRecorder() {
+StagefrightRecorder::StagefrightRecorder()
+    : mWriter(NULL),
+      mOutputFd(-1) {
+
+    LOGV("Constructor");
     reset();
 }
 
 StagefrightRecorder::~StagefrightRecorder() {
+    LOGV("Destructor");
     stop();
 
     if (mOutputFd >= 0) {
@@ -49,40 +61,103 @@
 }
 
 status_t StagefrightRecorder::init() {
+    LOGV("init");
     return OK;
 }
 
 status_t StagefrightRecorder::setAudioSource(audio_source as) {
-    mAudioSource = as;
+    LOGV("setAudioSource: %d", as);
+    if (as < AUDIO_SOURCE_DEFAULT ||
+        as >= AUDIO_SOURCE_LIST_END) {
+        LOGE("Invalid audio source: %d", as);
+        return BAD_VALUE;
+    }
+
+    if (as == AUDIO_SOURCE_DEFAULT) {
+        mAudioSource = AUDIO_SOURCE_MIC;
+    } else {
+        mAudioSource = as;
+    }
 
     return OK;
 }
 
 status_t StagefrightRecorder::setVideoSource(video_source vs) {
-    mVideoSource = vs;
+    LOGV("setVideoSource: %d", vs);
+    if (vs < VIDEO_SOURCE_DEFAULT ||
+        vs >= VIDEO_SOURCE_LIST_END) {
+        LOGE("Invalid video source: %d", vs);
+        return BAD_VALUE;
+    }
+
+    if (vs == VIDEO_SOURCE_DEFAULT) {
+        mVideoSource = VIDEO_SOURCE_CAMERA;
+    } else {
+        mVideoSource = vs;
+    }
 
     return OK;
 }
 
 status_t StagefrightRecorder::setOutputFormat(output_format of) {
-    mOutputFormat = of;
+    LOGV("setOutputFormat: %d", of);
+    if (of < OUTPUT_FORMAT_DEFAULT ||
+        of >= OUTPUT_FORMAT_LIST_END) {
+        LOGE("Invalid output format: %d", of);
+        return BAD_VALUE;
+    }
+
+    if (of == OUTPUT_FORMAT_DEFAULT) {
+        mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
+    } else {
+        mOutputFormat = of;
+    }
 
     return OK;
 }
 
 status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
-    mAudioEncoder = ae;
+    LOGV("setAudioEncoder: %d", ae);
+    if (ae < AUDIO_ENCODER_DEFAULT ||
+        ae >= AUDIO_ENCODER_LIST_END) {
+        LOGE("Invalid audio encoder: %d", ae);
+        return BAD_VALUE;
+    }
+
+    if (ae == AUDIO_ENCODER_DEFAULT) {
+        mAudioEncoder = AUDIO_ENCODER_AMR_NB;
+    } else {
+        mAudioEncoder = ae;
+    }
 
     return OK;
 }
 
 status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
-    mVideoEncoder = ve;
+    LOGV("setVideoEncoder: %d", ve);
+    if (ve < VIDEO_ENCODER_DEFAULT ||
+        ve >= VIDEO_ENCODER_LIST_END) {
+        LOGE("Invalid video encoder: %d", ve);
+        return BAD_VALUE;
+    }
+
+    if (ve == VIDEO_ENCODER_DEFAULT) {
+        mVideoEncoder = VIDEO_ENCODER_H263;
+    } else {
+        mVideoEncoder = ve;
+    }
 
     return OK;
 }
 
 status_t StagefrightRecorder::setVideoSize(int width, int height) {
+    LOGV("setVideoSize: %dx%d", width, height);
+    if (width <= 0 || height <= 0) {
+        LOGE("Invalid video size: %dx%d", width, height);
+        return BAD_VALUE;
+    }
+
+    // Additional check on the dimension will be performed later
     mVideoWidth = width;
     mVideoHeight = height;
 
@@ -90,35 +165,70 @@
 }
 
 status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
+    LOGV("setVideoFrameRate: %d", frames_per_second);
+    if (frames_per_second <= 0 || frames_per_second > 30) {
+        LOGE("Invalid video frame rate: %d", frames_per_second);
+        return BAD_VALUE;
+    }
+
+    // Additional check on the frame rate will be performed later
     mFrameRate = frames_per_second;
 
     return OK;
 }
 
 status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
-    mCamera = camera;
+    LOGV("setCamera");
+    if (camera == 0) {
+        LOGE("camera is NULL");
+        return BAD_VALUE;
+    }
+
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    mFlags &= ~FLAGS_HOT_CAMERA;
+    mCamera = Camera::create(camera);
+    if (mCamera == 0) {
+        LOGE("Unable to connect to camera");
+        IPCThreadState::self()->restoreCallingIdentity(token);
+        return -EBUSY;
+    }
+
+    LOGV("Connected to camera");
+    if (mCamera->previewEnabled()) {
+        LOGV("camera is hot");
+        mFlags |= FLAGS_HOT_CAMERA;
+    }
+    IPCThreadState::self()->restoreCallingIdentity(token);
 
     return OK;
 }
 
 status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) {
+    LOGV("setPreviewSurface: %p", surface.get());
     mPreviewSurface = surface;
 
     return OK;
 }
 
 status_t StagefrightRecorder::setOutputFile(const char *path) {
+    LOGE("setOutputFile(const char*) must not be called");
     // We don't actually support this at all, as the media_server process
     // no longer has permissions to create files.
 
-    return UNKNOWN_ERROR;
+    return -EPERM;
 }
 
 status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
+    LOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
     // These don't make any sense, do they?
     CHECK_EQ(offset, 0);
     CHECK_EQ(length, 0);
 
+    if (fd < 0) {
+        LOGE("Invalid file descriptor: %d", fd);
+        return -EBADF;
+    }
+
     if (mOutputFd >= 0) {
         ::close(mOutputFd);
     }
@@ -127,13 +237,366 @@
     return OK;
 }
 
-status_t StagefrightRecorder::setParameters(const String8 &params) {
-    mParams = params;
+// Attempt to parse an int64 literal optionally surrounded by whitespace,
+// returns true on success, false otherwise.
+static bool safe_strtoi64(const char *s, int64_t *val) {
+    char *end;
+    *val = strtoll(s, &end, 10);
 
+    if (end == s || errno == ERANGE) {
+        return false;
+    }
+
+    // Skip trailing whitespace
+    while (isspace(*end)) {
+        ++end;
+    }
+
+    // For a successful return, the string must contain nothing but a valid
+    // int64 literal optionally surrounded by whitespace.
+
+    return *end == '\0';
+}
+
+// Return true if the value is in [0, 0x007FFFFFFF]
+static bool safe_strtoi32(const char *s, int32_t *val) {
+    int64_t temp;
+    if (safe_strtoi64(s, &temp)) {
+        if (temp >= 0 && temp <= 0x007FFFFFFF) {
+            *val = static_cast<int32_t>(temp);
+            return true;
+        }
+    }
+    return false;
+}
+
+// Trim both leading and trailing whitespace from the given string.
+static void TrimString(String8 *s) {
+    size_t num_bytes = s->bytes();
+    const char *data = s->string();
+
+    size_t leading_space = 0;
+    while (leading_space < num_bytes && isspace(data[leading_space])) {
+        ++leading_space;
+    }
+
+    size_t i = num_bytes;
+    while (i > leading_space && isspace(data[i - 1])) {
+        --i;
+    }
+
+    s->setTo(String8(&data[leading_space], i - leading_space));
+}
+
+status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
+    LOGV("setParamAudioSamplingRate: %d", sampleRate);
+    if (sampleRate <= 0) {
+        LOGE("Invalid audio sampling rate: %d", sampleRate);
+        return BAD_VALUE;
+    }
+
+    // Additional check on the sample rate will be performed later.
+    mSampleRate = sampleRate;
     return OK;
 }
 
-status_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) {
+status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
+    LOGV("setParamAudioNumberOfChannels: %d", channels);
+    if (channels <= 0 || channels >= 3) {
+        LOGE("Invalid number of audio channels: %d", channels);
+        return BAD_VALUE;
+    }
+
+    // Additional check on the number of channels will be performed later.
+    mAudioChannels = channels;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
+    LOGV("setParamAudioEncodingBitRate: %d", bitRate);
+    if (bitRate <= 0) {
+        LOGE("Invalid audio encoding bit rate: %d", bitRate);
+        return BAD_VALUE;
+    }
+
+    // The target bit rate may not be exactly the same as the requested.
+    // It depends on many factors, such as rate control, and the bit rate
+    // range that a specific encoder supports. The mismatch between the
+    // the target and requested bit rate will NOT be treated as an error.
+    mAudioBitRate = bitRate;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
+    LOGV("setParamVideoEncodingBitRate: %d", bitRate);
+    if (bitRate <= 0) {
+        LOGE("Invalid video encoding bit rate: %d", bitRate);
+        return BAD_VALUE;
+    }
+
+    // The target bit rate may not be exactly the same as the requested.
+    // It depends on many factors, such as rate control, and the bit rate
+    // range that a specific encoder supports. The mismatch between the
+    // the target and requested bit rate will NOT be treated as an error.
+    mVideoBitRate = bitRate;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
+    LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
+    if (timeUs <= 1000000LL) {  // XXX: 1 second
+        LOGE("Max file duration is too short: %lld us", timeUs);
+        return BAD_VALUE;
+    }
+    mMaxFileDurationUs = timeUs;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
+    LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
+    if (bytes <= 1024) {  // XXX: 1 kB
+        LOGE("Max file size is too small: %lld bytes", bytes);
+        return BAD_VALUE;
+    }
+    mMaxFileSizeBytes = bytes;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
+    LOGV("setParamInterleaveDuration: %d", durationUs);
+    if (durationUs <= 500000) {           //  500 ms
+        // If interleave duration is too small, it is very inefficient to do
+        // interleaving since the metadata overhead will count for a significant
+        // portion of the saved contents
+        LOGE("Audio/video interleave duration is too small: %d us", durationUs);
+        return BAD_VALUE;
+    } else if (durationUs >= 10000000) {  // 10 seconds
+        // If interleaving duration is too large, it can cause the recording
+        // session to use too much memory since we have to save the output
+        // data before we write them out
+        LOGE("Audio/video interleave duration is too large: %d us", durationUs);
+        return BAD_VALUE;
+    }
+    mInterleaveDurationUs = durationUs;
+    return OK;
+}
+
+// If seconds <  0, only the first frame is I frame, and rest are all P frames
+// If seconds == 0, all frames are encoded as I frames. No P frames
+// If seconds >  0, it is the time spacing (seconds) between 2 neighboring I frames
+status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
+    LOGV("setParamVideoIFramesInterval: %d seconds", seconds);
+    mIFramesIntervalSec = seconds;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
+    LOGV("setParam64BitFileOffset: %s",
+        use64Bit? "use 64 bit file offset": "use 32 bit file offset");
+    mUse64BitFileOffset = use64Bit;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
+    LOGV("setParamVideoCameraId: %d", cameraId);
+    if (cameraId < 0) {
+        return BAD_VALUE;
+    }
+    mCameraId = cameraId;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
+    LOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
+    if (timeDurationUs < 20000) {  // Infeasible if shorter than 20 ms?
+        LOGE("Tracking time duration too short: %lld us", timeDurationUs);
+        return BAD_VALUE;
+    }
+    mTrackEveryTimeDurationUs = timeDurationUs;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) {
+    LOGV("setParamVideoEncoderProfile: %d", profile);
+
+    // Additional check will be done later when we load the encoder.
+    // For now, we are accepting values defined in OpenMAX IL.
+    mVideoEncoderProfile = profile;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) {
+    LOGV("setParamVideoEncoderLevel: %d", level);
+
+    // Additional check will be done later when we load the encoder.
+    // For now, we are accepting values defined in OpenMAX IL.
+    mVideoEncoderLevel = level;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
+    LOGV("setParamMovieTimeScale: %d", timeScale);
+
+    // The range is set to be the same as the audio's time scale range
+    // since audio's time scale has a wider range.
+    if (timeScale < 600 || timeScale > 96000) {
+        LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
+        return BAD_VALUE;
+    }
+    mMovieTimeScale = timeScale;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
+    LOGV("setParamVideoTimeScale: %d", timeScale);
+
+    // 60000 is chosen to make sure that each video frame from a 60-fps
+    // video has 1000 ticks.
+    if (timeScale < 600 || timeScale > 60000) {
+        LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
+        return BAD_VALUE;
+    }
+    mVideoTimeScale = timeScale;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
+    LOGV("setParamAudioTimeScale: %d", timeScale);
+
+    // 96000 Hz is the highest sampling rate support in AAC.
+    if (timeScale < 600 || timeScale > 96000) {
+        LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
+        return BAD_VALUE;
+    }
+    mAudioTimeScale = timeScale;
+    return OK;
+}
+
+status_t StagefrightRecorder::setParameter(
+        const String8 &key, const String8 &value) {
+    LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
+    if (key == "max-duration") {
+        int64_t max_duration_ms;
+        if (safe_strtoi64(value.string(), &max_duration_ms)) {
+            return setParamMaxFileDurationUs(1000LL * max_duration_ms);
+        }
+    } else if (key == "max-filesize") {
+        int64_t max_filesize_bytes;
+        if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
+            return setParamMaxFileSizeBytes(max_filesize_bytes);
+        }
+    } else if (key == "interleave-duration-us") {
+        int32_t durationUs;
+        if (safe_strtoi32(value.string(), &durationUs)) {
+            return setParamInterleaveDuration(durationUs);
+        }
+    } else if (key == "param-movie-time-scale") {
+        int32_t timeScale;
+        if (safe_strtoi32(value.string(), &timeScale)) {
+            return setParamMovieTimeScale(timeScale);
+        }
+    } else if (key == "param-use-64bit-offset") {
+        int32_t use64BitOffset;
+        if (safe_strtoi32(value.string(), &use64BitOffset)) {
+            return setParam64BitFileOffset(use64BitOffset != 0);
+        }
+    } else if (key == "param-track-time-status") {
+        int64_t timeDurationUs;
+        if (safe_strtoi64(value.string(), &timeDurationUs)) {
+            return setParamTrackTimeStatus(timeDurationUs);
+        }
+    } else if (key == "audio-param-sampling-rate") {
+        int32_t sampling_rate;
+        if (safe_strtoi32(value.string(), &sampling_rate)) {
+            return setParamAudioSamplingRate(sampling_rate);
+        }
+    } else if (key == "audio-param-number-of-channels") {
+        int32_t number_of_channels;
+        if (safe_strtoi32(value.string(), &number_of_channels)) {
+            return setParamAudioNumberOfChannels(number_of_channels);
+        }
+    } else if (key == "audio-param-encoding-bitrate") {
+        int32_t audio_bitrate;
+        if (safe_strtoi32(value.string(), &audio_bitrate)) {
+            return setParamAudioEncodingBitRate(audio_bitrate);
+        }
+    } else if (key == "audio-param-time-scale") {
+        int32_t timeScale;
+        if (safe_strtoi32(value.string(), &timeScale)) {
+            return setParamAudioTimeScale(timeScale);
+        }
+    } else if (key == "video-param-encoding-bitrate") {
+        int32_t video_bitrate;
+        if (safe_strtoi32(value.string(), &video_bitrate)) {
+            return setParamVideoEncodingBitRate(video_bitrate);
+        }
+    } else if (key == "video-param-i-frames-interval") {
+        int32_t seconds;
+        if (safe_strtoi32(value.string(), &seconds)) {
+            return setParamVideoIFramesInterval(seconds);
+        }
+    } else if (key == "video-param-encoder-profile") {
+        int32_t profile;
+        if (safe_strtoi32(value.string(), &profile)) {
+            return setParamVideoEncoderProfile(profile);
+        }
+    } else if (key == "video-param-encoder-level") {
+        int32_t level;
+        if (safe_strtoi32(value.string(), &level)) {
+            return setParamVideoEncoderLevel(level);
+        }
+    } else if (key == "video-param-camera-id") {
+        int32_t cameraId;
+        if (safe_strtoi32(value.string(), &cameraId)) {
+            return setParamVideoCameraId(cameraId);
+        }
+    } else if (key == "video-param-time-scale") {
+        int32_t timeScale;
+        if (safe_strtoi32(value.string(), &timeScale)) {
+            return setParamVideoTimeScale(timeScale);
+        }
+    } else {
+        LOGE("setParameter: failed to find key %s", key.string());
+    }
+    return BAD_VALUE;
+}
+
+status_t StagefrightRecorder::setParameters(const String8 &params) {
+    LOGV("setParameters: %s", params.string());
+    const char *cparams = params.string();
+    const char *key_start = cparams;
+    for (;;) {
+        const char *equal_pos = strchr(key_start, '=');
+        if (equal_pos == NULL) {
+            LOGE("Parameters %s miss a value", cparams);
+            return BAD_VALUE;
+        }
+        String8 key(key_start, equal_pos - key_start);
+        TrimString(&key);
+        if (key.length() == 0) {
+            LOGE("Parameters %s contains an empty key", cparams);
+            return BAD_VALUE;
+        }
+        const char *value_start = equal_pos + 1;
+        const char *semicolon_pos = strchr(value_start, ';');
+        String8 value;
+        if (semicolon_pos == NULL) {
+            value.setTo(value_start);
+        } else {
+            value.setTo(value_start, semicolon_pos - value_start);
+        }
+        if (setParameter(key, value) != OK) {
+            return BAD_VALUE;
+        }
+        if (semicolon_pos == NULL) {
+            break;  // Reaches the end
+        }
+        key_start = semicolon_pos + 1;
+    }
+    return OK;
+}
+
+status_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
     mListener = listener;
 
     return OK;
@@ -144,7 +607,10 @@
 }
 
 status_t StagefrightRecorder::start() {
+    CHECK(mOutputFd >= 0);
+
     if (mWriter != NULL) {
+        LOGE("File writer is not avaialble");
         return UNKNOWN_ERROR;
     }
 
@@ -158,40 +624,58 @@
         case OUTPUT_FORMAT_AMR_WB:
             return startAMRRecording();
 
+        case OUTPUT_FORMAT_AAC_ADIF:
+        case OUTPUT_FORMAT_AAC_ADTS:
+            return startAACRecording();
+
         default:
+            LOGE("Unsupported output file format: %d", mOutputFormat);
             return UNKNOWN_ERROR;
     }
 }
 
-sp<MediaSource> StagefrightRecorder::createAMRAudioSource() {
-    uint32_t sampleRate =
-        mAudioEncoder == AUDIO_ENCODER_AMR_NB ? 8000 : 16000;
-
+sp<MediaSource> StagefrightRecorder::createAudioSource() {
     sp<AudioSource> audioSource =
         new AudioSource(
                 mAudioSource,
-                sampleRate,
-                AudioSystem::CHANNEL_IN_MONO);
+                mSampleRate,
+                mAudioChannels);
 
     status_t err = audioSource->initCheck();
 
     if (err != OK) {
+        LOGE("audio source is not initialized");
         return NULL;
     }
 
     sp<MetaData> encMeta = new MetaData;
-    encMeta->setCString(
-            kKeyMIMEType,
-            mAudioEncoder == AUDIO_ENCODER_AMR_NB
-                ? MEDIA_MIMETYPE_AUDIO_AMR_NB : MEDIA_MIMETYPE_AUDIO_AMR_WB);
+    const char *mime;
+    switch (mAudioEncoder) {
+        case AUDIO_ENCODER_AMR_NB:
+        case AUDIO_ENCODER_DEFAULT:
+            mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
+            break;
+        case AUDIO_ENCODER_AMR_WB:
+            mime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
+            break;
+        case AUDIO_ENCODER_AAC:
+            mime = MEDIA_MIMETYPE_AUDIO_AAC;
+            break;
+        default:
+            LOGE("Unknown audio encoder: %d", mAudioEncoder);
+            return NULL;
+    }
+    encMeta->setCString(kKeyMIMEType, mime);
 
     int32_t maxInputSize;
     CHECK(audioSource->getFormat()->findInt32(
                 kKeyMaxInputSize, &maxInputSize));
 
     encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
-    encMeta->setInt32(kKeyChannelCount, 1);
-    encMeta->setInt32(kKeySampleRate, sampleRate);
+    encMeta->setInt32(kKeyChannelCount, mAudioChannels);
+    encMeta->setInt32(kKeySampleRate, mSampleRate);
+    encMeta->setInt32(kKeyBitRate, mAudioBitRate);
+    encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
 
     OMXClient client;
     CHECK_EQ(client.connect(), OK);
@@ -199,144 +683,481 @@
     sp<MediaSource> audioEncoder =
         OMXCodec::Create(client.interface(), encMeta,
                          true /* createEncoder */, audioSource);
+    mAudioSourceNode = audioSource;
 
     return audioEncoder;
 }
 
+status_t StagefrightRecorder::startAACRecording() {
+    CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF ||
+          mOutputFormat == OUTPUT_FORMAT_AAC_ADTS);
+
+    CHECK(mAudioEncoder == AUDIO_ENCODER_AAC);
+    CHECK(mAudioSource != AUDIO_SOURCE_LIST_END);
+
+    CHECK(0 == "AACWriter is not implemented yet");
+
+    return OK;
+}
+
 status_t StagefrightRecorder::startAMRRecording() {
-    if (mAudioSource == AUDIO_SOURCE_LIST_END
-        || mVideoSource != VIDEO_SOURCE_LIST_END) {
-        return UNKNOWN_ERROR;
+    CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
+          mOutputFormat == OUTPUT_FORMAT_AMR_WB);
+
+    if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
+        if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
+            mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
+            LOGE("Invalid encoder %d used for AMRNB recording",
+                    mAudioEncoder);
+            return BAD_VALUE;
+        }
+        if (mSampleRate != 8000) {
+            LOGE("Invalid sampling rate %d used for AMRNB recording",
+                    mSampleRate);
+            return BAD_VALUE;
+        }
+    } else {  // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
+        if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
+            LOGE("Invlaid encoder %d used for AMRWB recording",
+                    mAudioEncoder);
+            return BAD_VALUE;
+        }
+        if (mSampleRate != 16000) {
+            LOGE("Invalid sample rate %d used for AMRWB recording",
+                    mSampleRate);
+            return BAD_VALUE;
+        }
+    }
+    if (mAudioChannels != 1) {
+        LOGE("Invalid number of audio channels %d used for amr recording",
+                mAudioChannels);
+        return BAD_VALUE;
     }
 
-    if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
-            && mAudioEncoder != AUDIO_ENCODER_DEFAULT
-            && mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
-        return UNKNOWN_ERROR;
-    } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
-            && mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
-        return UNKNOWN_ERROR;
+    if (mAudioSource >= AUDIO_SOURCE_LIST_END) {
+        LOGE("Invalid audio source: %d", mAudioSource);
+        return BAD_VALUE;
     }
 
-    sp<MediaSource> audioEncoder = createAMRAudioSource();
+    sp<MediaSource> audioEncoder = createAudioSource();
 
     if (audioEncoder == NULL) {
         return UNKNOWN_ERROR;
     }
 
-    CHECK(mOutputFd >= 0);
     mWriter = new AMRWriter(dup(mOutputFd));
     mWriter->addSource(audioEncoder);
+
+    if (mMaxFileDurationUs != 0) {
+        mWriter->setMaxFileDuration(mMaxFileDurationUs);
+    }
+    if (mMaxFileSizeBytes != 0) {
+        mWriter->setMaxFileSize(mMaxFileSizeBytes);
+    }
+    mWriter->setListener(mListener);
     mWriter->start();
 
     return OK;
 }
 
+void StagefrightRecorder::clipVideoFrameRate() {
+    LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
+    int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
+                        "enc.vid.fps.min", mVideoEncoder);
+    int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
+                        "enc.vid.fps.max", mVideoEncoder);
+    if (mFrameRate < minFrameRate) {
+        LOGW("Intended video encoding frame rate (%d fps) is too small"
+             " and will be set to (%d fps)", mFrameRate, minFrameRate);
+        mFrameRate = minFrameRate;
+    } else if (mFrameRate > maxFrameRate) {
+        LOGW("Intended video encoding frame rate (%d fps) is too large"
+             " and will be set to (%d fps)", mFrameRate, maxFrameRate);
+        mFrameRate = maxFrameRate;
+    }
+}
+
+void StagefrightRecorder::clipVideoBitRate() {
+    LOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
+    int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
+                        "enc.vid.bps.min", mVideoEncoder);
+    int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
+                        "enc.vid.bps.max", mVideoEncoder);
+    if (mVideoBitRate < minBitRate) {
+        LOGW("Intended video encoding bit rate (%d bps) is too small"
+             " and will be set to (%d bps)", mVideoBitRate, minBitRate);
+        mVideoBitRate = minBitRate;
+    } else if (mVideoBitRate > maxBitRate) {
+        LOGW("Intended video encoding bit rate (%d bps) is too large"
+             " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
+        mVideoBitRate = maxBitRate;
+    }
+}
+
+void StagefrightRecorder::clipVideoFrameWidth() {
+    LOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
+    int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
+                        "enc.vid.width.min", mVideoEncoder);
+    int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
+                        "enc.vid.width.max", mVideoEncoder);
+    if (mVideoWidth < minFrameWidth) {
+        LOGW("Intended video encoding frame width (%d) is too small"
+             " and will be set to (%d)", mVideoWidth, minFrameWidth);
+        mVideoWidth = minFrameWidth;
+    } else if (mVideoWidth > maxFrameWidth) {
+        LOGW("Intended video encoding frame width (%d) is too large"
+             " and will be set to (%d)", mVideoWidth, maxFrameWidth);
+        mVideoWidth = maxFrameWidth;
+    }
+}
+
+status_t StagefrightRecorder::setupCameraSource() {
+    clipVideoBitRate();
+    clipVideoFrameRate();
+    clipVideoFrameWidth();
+    clipVideoFrameHeight();
+
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    if (mCamera == 0) {
+        mCamera = Camera::connect(mCameraId);
+        if (mCamera == 0) {
+            LOGE("Camera connection could not be established.");
+            return -EBUSY;
+        }
+        mFlags &= ~FLAGS_HOT_CAMERA;
+        mCamera->lock();
+    }
+
+    // Set the actual video recording frame size
+    CameraParameters params(mCamera->getParameters());
+    params.setPreviewSize(mVideoWidth, mVideoHeight);
+    params.setPreviewFrameRate(mFrameRate);
+    String8 s = params.flatten();
+    CHECK_EQ(OK, mCamera->setParameters(s));
+    CameraParameters newCameraParams(mCamera->getParameters());
+
+    // Check on video frame size
+    int frameWidth = 0, frameHeight = 0;
+    newCameraParams.getPreviewSize(&frameWidth, &frameHeight);
+    if (frameWidth  < 0 || frameWidth  != mVideoWidth ||
+        frameHeight < 0 || frameHeight != mVideoHeight) {
+        LOGE("Failed to set the video frame size to %dx%d",
+                mVideoWidth, mVideoHeight);
+        IPCThreadState::self()->restoreCallingIdentity(token);
+        return UNKNOWN_ERROR;
+    }
+
+    // Check on video frame rate
+    int frameRate = newCameraParams.getPreviewFrameRate();
+    if (frameRate < 0 || (frameRate - mFrameRate) != 0) {
+        LOGE("Failed to set frame rate to %d fps. The actual "
+             "frame rate is %d", mFrameRate, frameRate);
+    }
+
+    CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface));
+    IPCThreadState::self()->restoreCallingIdentity(token);
+    return OK;
+}
+
+void StagefrightRecorder::clipVideoFrameHeight() {
+    LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
+    int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
+                        "enc.vid.height.min", mVideoEncoder);
+    int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
+                        "enc.vid.height.max", mVideoEncoder);
+    if (mVideoHeight < minFrameHeight) {
+        LOGW("Intended video encoding frame height (%d) is too small"
+             " and will be set to (%d)", mVideoHeight, minFrameHeight);
+        mVideoHeight = minFrameHeight;
+    } else if (mVideoHeight > maxFrameHeight) {
+        LOGW("Intended video encoding frame height (%d) is too large"
+             " and will be set to (%d)", mVideoHeight, maxFrameHeight);
+        mVideoHeight = maxFrameHeight;
+    }
+}
+
+status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) {
+    status_t err = setupCameraSource();
+    if (err != OK) return err;
+
+    sp<CameraSource> cameraSource = CameraSource::CreateFromCamera(mCamera);
+    CHECK(cameraSource != NULL);
+
+    sp<MetaData> enc_meta = new MetaData;
+    enc_meta->setInt32(kKeyBitRate, mVideoBitRate);
+    enc_meta->setInt32(kKeySampleRate, mFrameRate);
+
+    switch (mVideoEncoder) {
+        case VIDEO_ENCODER_H263:
+            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+            break;
+
+        case VIDEO_ENCODER_MPEG_4_SP:
+            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+            break;
+
+        case VIDEO_ENCODER_H264:
+            enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+            break;
+
+        default:
+            CHECK(!"Should not be here, unsupported video encoding.");
+            break;
+    }
+
+    sp<MetaData> meta = cameraSource->getFormat();
+
+    int32_t width, height, stride, sliceHeight, colorFormat;
+    CHECK(meta->findInt32(kKeyWidth, &width));
+    CHECK(meta->findInt32(kKeyHeight, &height));
+    CHECK(meta->findInt32(kKeyStride, &stride));
+    CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
+    CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
+
+    enc_meta->setInt32(kKeyWidth, width);
+    enc_meta->setInt32(kKeyHeight, height);
+    enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec);
+    enc_meta->setInt32(kKeyStride, stride);
+    enc_meta->setInt32(kKeySliceHeight, sliceHeight);
+    enc_meta->setInt32(kKeyColorFormat, colorFormat);
+    enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
+    if (mVideoEncoderProfile != -1) {
+        enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
+    }
+    if (mVideoEncoderLevel != -1) {
+        enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel);
+    }
+
+    OMXClient client;
+    CHECK_EQ(client.connect(), OK);
+
+    sp<MediaSource> encoder = OMXCodec::Create(
+            client.interface(), enc_meta,
+            true /* createEncoder */, cameraSource);
+    if (encoder == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    writer->addSource(encoder);
+    return OK;
+}
+
+status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
+    sp<MediaSource> audioEncoder;
+    switch(mAudioEncoder) {
+        case AUDIO_ENCODER_AMR_NB:
+        case AUDIO_ENCODER_AMR_WB:
+        case AUDIO_ENCODER_AAC:
+            audioEncoder = createAudioSource();
+            break;
+        default:
+            LOGE("Unsupported audio encoder: %d", mAudioEncoder);
+            return UNKNOWN_ERROR;
+    }
+
+    if (audioEncoder == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    writer->addSource(audioEncoder);
+    return OK;
+}
+
 status_t StagefrightRecorder::startMPEG4Recording() {
-    mWriter = new MPEG4Writer(dup(mOutputFd));
+    int32_t totalBitRate = 0;
+    status_t err = OK;
+    sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd));
 
+    // Add audio source first if it exists
+    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+        err = setupAudioEncoder(writer);
+        if (err != OK) return err;
+        totalBitRate += mAudioBitRate;
+    }
     if (mVideoSource == VIDEO_SOURCE_DEFAULT
             || mVideoSource == VIDEO_SOURCE_CAMERA) {
-        CHECK(mCamera != NULL);
-
-        sp<CameraSource> cameraSource =
-            CameraSource::CreateFromICamera(mCamera);
-
-        CHECK(cameraSource != NULL);
-
-        cameraSource->setPreviewSurface(mPreviewSurface);
-
-        sp<MetaData> enc_meta = new MetaData;
-        switch (mVideoEncoder) {
-            case VIDEO_ENCODER_H263:
-                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
-                break;
-
-            case VIDEO_ENCODER_MPEG_4_SP:
-                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
-                break;
-
-            case VIDEO_ENCODER_H264:
-                enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
-                break;
-
-            default:
-                CHECK(!"Should not be here, unsupported video encoding.");
-                break;
-        }
-
-        sp<MetaData> meta = cameraSource->getFormat();
-
-        int32_t width, height;
-        CHECK(meta->findInt32(kKeyWidth, &width));
-        CHECK(meta->findInt32(kKeyHeight, &height));
-
-        enc_meta->setInt32(kKeyWidth, width);
-        enc_meta->setInt32(kKeyHeight, height);
-
-        OMXClient client;
-        CHECK_EQ(client.connect(), OK);
-
-        sp<MediaSource> encoder =
-            OMXCodec::Create(
-                    client.interface(), enc_meta,
-                    true /* createEncoder */, cameraSource);
-
-        CHECK(mOutputFd >= 0);
-        mWriter->addSource(encoder);
+        err = setupVideoEncoder(writer);
+        if (err != OK) return err;
+        totalBitRate += mVideoBitRate;
     }
 
-    if (mAudioSource != AUDIO_SOURCE_LIST_END) {
-        sp<MediaSource> audioEncoder = createAMRAudioSource();
-
-        if (audioEncoder == NULL) {
-            return UNKNOWN_ERROR;
-        }
-
-        mWriter->addSource(audioEncoder);
+    if (mInterleaveDurationUs > 0) {
+        reinterpret_cast<MPEG4Writer *>(writer.get())->
+            setInterleaveDuration(mInterleaveDurationUs);
     }
 
-    mWriter->start();
+    if (mMaxFileDurationUs != 0) {
+        writer->setMaxFileDuration(mMaxFileDurationUs);
+    }
+    if (mMaxFileSizeBytes != 0) {
+        writer->setMaxFileSize(mMaxFileSizeBytes);
+    }
+    sp<MetaData> meta = new MetaData;
+    meta->setInt64(kKeyTime, systemTime() / 1000);
+    meta->setInt32(kKeyFileType, mOutputFormat);
+    meta->setInt32(kKeyBitRate, totalBitRate);
+    meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
+    meta->setInt32(kKeyTimeScale, mMovieTimeScale);
+    if (mTrackEveryTimeDurationUs > 0) {
+        meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
+    }
+    writer->setListener(mListener);
+    mWriter = writer;
+    return mWriter->start(meta.get());
+}
+
+status_t StagefrightRecorder::pause() {
+    LOGV("pause");
+    if (mWriter == NULL) {
+        return UNKNOWN_ERROR;
+    }
+    mWriter->pause();
     return OK;
 }
 
 status_t StagefrightRecorder::stop() {
-    if (mWriter == NULL) {
-        return UNKNOWN_ERROR;
+    LOGV("stop");
+    if (mWriter != NULL) {
+        mWriter->stop();
+        mWriter.clear();
     }
 
-    mWriter->stop();
-    mWriter = NULL;
+    if (mCamera != 0) {
+        LOGV("Disconnect camera");
+        int64_t token = IPCThreadState::self()->clearCallingIdentity();
+        if ((mFlags & FLAGS_HOT_CAMERA) == 0) {
+            LOGV("Camera was cold when we started, stopping preview");
+            mCamera->stopPreview();
+        }
+        mCamera->unlock();
+        mCamera.clear();
+        IPCThreadState::self()->restoreCallingIdentity(token);
+        mFlags = 0;
+    }
 
     return OK;
 }
 
 status_t StagefrightRecorder::close() {
+    LOGV("close");
     stop();
 
     return OK;
 }
 
 status_t StagefrightRecorder::reset() {
+    LOGV("reset");
     stop();
 
+    // No audio or video source by default
     mAudioSource = AUDIO_SOURCE_LIST_END;
     mVideoSource = VIDEO_SOURCE_LIST_END;
-    mOutputFormat = OUTPUT_FORMAT_LIST_END;
-    mAudioEncoder = AUDIO_ENCODER_LIST_END;
-    mVideoEncoder = VIDEO_ENCODER_LIST_END;
-    mVideoWidth = -1;
-    mVideoHeight = -1;
-    mFrameRate = -1;
+
+    // Default parameters
+    mOutputFormat  = OUTPUT_FORMAT_THREE_GPP;
+    mAudioEncoder  = AUDIO_ENCODER_AMR_NB;
+    mVideoEncoder  = VIDEO_ENCODER_H263;
+    mVideoWidth    = 176;
+    mVideoHeight   = 144;
+    mFrameRate     = 20;
+    mVideoBitRate  = 192000;
+    mSampleRate    = 8000;
+    mAudioChannels = 1;
+    mAudioBitRate  = 12200;
+    mInterleaveDurationUs = 0;
+    mIFramesIntervalSec = 1;
+    mAudioSourceNode = 0;
+    mUse64BitFileOffset = false;
+    mMovieTimeScale  = 1000;
+    mAudioTimeScale  = 1000;
+    mVideoTimeScale  = 1000;
+    mCameraId        = 0;
+    mVideoEncoderProfile = -1;
+    mVideoEncoderLevel   = -1;
+    mMaxFileDurationUs = 0;
+    mMaxFileSizeBytes = 0;
+    mTrackEveryTimeDurationUs = 0;
+    mEncoderProfiles = MediaProfiles::getInstance();
+
     mOutputFd = -1;
+    mFlags = 0;
 
     return OK;
 }
 
 status_t StagefrightRecorder::getMaxAmplitude(int *max) {
-    *max = 0;
+    LOGV("getMaxAmplitude");
+
+    if (max == NULL) {
+        LOGE("Null pointer argument");
+        return BAD_VALUE;
+    }
+
+    if (mAudioSourceNode != 0) {
+        *max = mAudioSourceNode->getMaxAmplitude();
+    } else {
+        *max = 0;
+    }
 
     return OK;
 }
 
+status_t StagefrightRecorder::dump(int fd, const Vector<String16>& args) const {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "   Recorder: %p", this);
+    snprintf(buffer, SIZE, "   Output file (fd %d):\n", mOutputFd);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     File format: %d\n", mOutputFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Max file size (bytes): %lld\n", mMaxFileSizeBytes);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Max file duration (us): %lld\n", mMaxFileDurationUs);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Interleave duration (us): %d\n", mInterleaveDurationUs);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Progress notification: %lld us\n", mTrackEveryTimeDurationUs);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "   Audio\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Source: %d\n", mAudioSource);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Encoder: %d\n", mAudioEncoder);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mAudioBitRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Sampling rate (hz): %d\n", mSampleRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Number of channels: %d\n", mAudioChannels);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "   Video\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Source: %d\n", mVideoSource);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Camera Id: %d\n", mCameraId);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Camera flags: %d\n", mFlags);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Encoder: %d\n", mVideoEncoder);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Encoder profile: %d\n", mVideoEncoderProfile);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Encoder level: %d\n", mVideoEncoderLevel);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     I frames interval (s): %d\n", mIFramesIntervalSec);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Frame rate (fps): %d\n", mFrameRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "     Bit rate (bps): %d\n", mVideoBitRate);
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return OK;
+}
 }  // namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 7ec412d..b4c5900 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -23,8 +23,11 @@
 
 namespace android {
 
+class Camera;
 struct MediaSource;
 struct MediaWriter;
+struct AudioSource;
+class MediaProfiles;
 
 struct StagefrightRecorder : public MediaRecorderBase {
     StagefrightRecorder();
@@ -43,33 +46,88 @@
     virtual status_t setOutputFile(const char *path);
     virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
     virtual status_t setParameters(const String8& params);
-    virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
+    virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
     virtual status_t prepare();
     virtual status_t start();
+    virtual status_t pause();
     virtual status_t stop();
     virtual status_t close();
     virtual status_t reset();
     virtual status_t getMaxAmplitude(int *max);
+    virtual status_t dump(int fd, const Vector<String16>& args) const;
 
 private:
-    sp<ICamera> mCamera;
+    enum CameraFlags {
+        FLAGS_SET_CAMERA = 1L << 0,
+        FLAGS_HOT_CAMERA = 1L << 1,
+    };
+
+    sp<Camera> mCamera;
     sp<ISurface> mPreviewSurface;
-    sp<IMediaPlayerClient> mListener;
+    sp<IMediaRecorderClient> mListener;
     sp<MediaWriter> mWriter;
+    sp<AudioSource> mAudioSourceNode;
 
     audio_source mAudioSource;
     video_source mVideoSource;
     output_format mOutputFormat;
     audio_encoder mAudioEncoder;
     video_encoder mVideoEncoder;
-    int mVideoWidth, mVideoHeight;
-    int mFrameRate;
+    bool mUse64BitFileOffset;
+    int32_t mVideoWidth, mVideoHeight;
+    int32_t mFrameRate;
+    int32_t mVideoBitRate;
+    int32_t mAudioBitRate;
+    int32_t mAudioChannels;
+    int32_t mSampleRate;
+    int32_t mInterleaveDurationUs;
+    int32_t mIFramesIntervalSec;
+    int32_t mCameraId;
+    int32_t mVideoEncoderProfile;
+    int32_t mVideoEncoderLevel;
+    int32_t mMovieTimeScale;
+    int32_t mVideoTimeScale;
+    int32_t mAudioTimeScale;
+    int64_t mMaxFileSizeBytes;
+    int64_t mMaxFileDurationUs;
+    int64_t mTrackEveryTimeDurationUs;
+
     String8 mParams;
     int mOutputFd;
+    int32_t mFlags;
+
+    MediaProfiles *mEncoderProfiles;
 
     status_t startMPEG4Recording();
     status_t startAMRRecording();
-    sp<MediaSource> createAMRAudioSource();
+    status_t startAACRecording();
+    sp<MediaSource> createAudioSource();
+    status_t setupCameraSource();
+    status_t setupAudioEncoder(const sp<MediaWriter>& writer);
+    status_t setupVideoEncoder(const sp<MediaWriter>& writer);
+
+    // Encoding parameter handling utilities
+    status_t setParameter(const String8 &key, const String8 &value);
+    status_t setParamAudioEncodingBitRate(int32_t bitRate);
+    status_t setParamAudioNumberOfChannels(int32_t channles);
+    status_t setParamAudioSamplingRate(int32_t sampleRate);
+    status_t setParamAudioTimeScale(int32_t timeScale);
+    status_t setParamVideoEncodingBitRate(int32_t bitRate);
+    status_t setParamVideoIFramesInterval(int32_t seconds);
+    status_t setParamVideoEncoderProfile(int32_t profile);
+    status_t setParamVideoEncoderLevel(int32_t level);
+    status_t setParamVideoCameraId(int32_t cameraId);
+    status_t setParamVideoTimeScale(int32_t timeScale);
+    status_t setParamTrackTimeStatus(int64_t timeDurationUs);
+    status_t setParamInterleaveDuration(int32_t durationUs);
+    status_t setParam64BitFileOffset(bool use64BitFileOffset);
+    status_t setParamMaxFileDurationUs(int64_t timeUs);
+    status_t setParamMaxFileSizeBytes(int64_t bytes);
+    status_t setParamMovieTimeScale(int32_t timeScale);
+    void clipVideoBitRate();
+    void clipVideoFrameRate();
+    void clipVideoFrameWidth();
+    void clipVideoFrameHeight();
 
     StagefrightRecorder(const StagefrightRecorder &);
     StagefrightRecorder &operator=(const StagefrightRecorder &);
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp b/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
deleted file mode 100644
index eac74fc..0000000
--- a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-**
-** Copyright 2009, 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 "VorbisMetadataRetriever"
-#include <utils/Log.h>
-
-#include "VorbisMetadataRetriever.h"
-#include <media/mediametadataretriever.h>
-#
-
-namespace android {
-
-void VorbisMetadataRetriever::clearMetadataValues()
-{
-    LOGV("cleearMetadataValues");
-    mMetadataValues[0][0] = '\0';
-}
-
-status_t VorbisMetadataRetriever::setDataSource(const char *url)
-{
-    LOGV("setDataSource: url(%s)", url? url: "NULL pointer");
-    Mutex::Autolock lock(mLock);
-    clearMetadataValues();
-    if (mVorbisPlayer == 0) {
-        mVorbisPlayer = new VorbisPlayer();
-    }
-    // TODO: support headers in MetadataRetriever interface!
-    return mVorbisPlayer->setDataSource(url, NULL /* headers */);
-}
-
-status_t VorbisMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
-{
-    LOGV("setDataSource: fd(%d), offset(%lld), and length(%lld)", fd, offset, length);
-    Mutex::Autolock lock(mLock);
-    clearMetadataValues();
-    if (mVorbisPlayer == 0) {
-        mVorbisPlayer = new VorbisPlayer();
-    }
-    return mVorbisPlayer->setDataSource(fd, offset, length);
-}
-
-const char* VorbisMetadataRetriever::extractMetadata(int keyCode)
-{
-    LOGV("extractMetadata: key(%d)", keyCode);
-    Mutex::Autolock lock(mLock);
-    if (mVorbisPlayer == 0 || mVorbisPlayer->initCheck() != NO_ERROR) {
-        LOGE("no vorbis player is initialized yet");
-        return NULL;
-    }
-    switch (keyCode) {
-    case METADATA_KEY_DURATION:
-        {
-            if (mMetadataValues[0][0] == '\0') {
-                int duration = -1;
-                if (mVorbisPlayer->getDuration(&duration) != NO_ERROR) {
-                    LOGE("failed to get duration");
-                    return NULL;
-                }
-                snprintf(mMetadataValues[0], MAX_METADATA_STRING_LENGTH, "%d", duration);
-            }
-            LOGV("duration: %s ms", mMetadataValues[0]);
-            return mMetadataValues[0];
-        }
-    default:
-        LOGE("Unsupported key code (%d)", keyCode);
-        return NULL;
-    }
-    return NULL;
-}
-
-};
-
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.h b/media/libmediaplayerservice/VorbisMetadataRetriever.h
deleted file mode 100644
index 1c57fe3..0000000
--- a/media/libmediaplayerservice/VorbisMetadataRetriever.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-**
-** Copyright 2009, 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 ANDROID_VORBISMETADATARETRIEVER_H
-#define ANDROID_VORBISMETADATARETRIEVER_H
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <media/MediaMetadataRetrieverInterface.h>
-
-#include "VorbisPlayer.h"
-
-namespace android {
-
-class VorbisMetadataRetriever : public MediaMetadataRetrieverInterface {
-public:
-                                   VorbisMetadataRetriever() {}
-                                   ~VorbisMetadataRetriever() {}
-
-    virtual status_t                setDataSource(const char *url);
-    virtual status_t                setDataSource(int fd, int64_t offset, int64_t length);
-    virtual const char*             extractMetadata(int keyCode);
-
-private:
-    static const uint32_t MAX_METADATA_STRING_LENGTH = 128;
-    void clearMetadataValues();
-
-    Mutex               mLock;
-    sp<VorbisPlayer>    mVorbisPlayer;
-    char                mMetadataValues[1][MAX_METADATA_STRING_LENGTH];
-};
-
-}; // namespace android
-
-#endif // ANDROID_VORBISMETADATARETRIEVER_H
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
deleted file mode 100644
index 8181999..0000000
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
-** Copyright 2007, 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 "VorbisPlayer"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-
-#include "VorbisPlayer.h"
-
-#ifdef HAVE_GETTID
-static pid_t myTid() { return gettid(); }
-#else
-static pid_t myTid() { return getpid(); }
-#endif
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-// TODO: Determine appropriate return codes
-static status_t ERROR_NOT_OPEN = -1;
-static status_t ERROR_OPEN_FAILED = -2;
-static status_t ERROR_ALLOCATE_FAILED = -4;
-static status_t ERROR_NOT_SUPPORTED = -8;
-static status_t ERROR_NOT_READY = -16;
-static status_t STATE_INIT = 0;
-static status_t STATE_ERROR = 1;
-static status_t STATE_OPEN = 2;
-
-
-VorbisPlayer::VorbisPlayer() :
-    mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
-    mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false),
-    mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
-{
-    LOGV("constructor\n");
-    memset(&mVorbisFile, 0, sizeof mVorbisFile);
-}
-
-void VorbisPlayer::onFirstRef()
-{
-    LOGV("onFirstRef");
-    // create playback thread
-    Mutex::Autolock l(mMutex);
-    createThreadEtc(renderThread, this, "vorbis decoder", ANDROID_PRIORITY_AUDIO);
-    mCondition.wait(mMutex);
-    if (mRenderTid > 0) {
-        LOGV("render thread(%d) started", mRenderTid);
-        mState = STATE_INIT;
-    }
-}
-
-status_t VorbisPlayer::initCheck()
-{
-    if (mState != STATE_ERROR) return NO_ERROR;
-    return ERROR_NOT_READY;
-}
-
-VorbisPlayer::~VorbisPlayer() {
-    LOGV("VorbisPlayer destructor\n");
-    release();
-}
-
-status_t VorbisPlayer::setDataSource(
-        const char *uri, const KeyedVector<String8, String8> *headers) {
-    return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
-}
-
-status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length)
-{
-    return setdatasource(NULL, fd, offset, length);
-}
-
-size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) {
-    VorbisPlayer *self = (VorbisPlayer*) me;
-
-    long curpos = vp_ftell(me);
-    while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) {
-        nmemb--;
-    }
-    return fread(buf, size, nmemb, self->mFile);
-}
-
-int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) {
-    VorbisPlayer *self = (VorbisPlayer*) me;
-    if (whence == SEEK_SET)
-        return fseek(self->mFile, off + self->mOffset, whence);
-    else if (whence == SEEK_CUR)
-        return fseek(self->mFile, off, whence);
-    else if (whence == SEEK_END)
-        return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET);
-    return -1;
-}
-
-int VorbisPlayer::vp_fclose(void *me) {
-    LOGV("vp_fclose");
-    VorbisPlayer *self = (VorbisPlayer*) me;
-    int ret = fclose (self->mFile);
-    self->mFile = NULL;
-    return ret;
-}
-
-long VorbisPlayer::vp_ftell(void *me) {
-    VorbisPlayer *self = (VorbisPlayer*) me;
-    return ftell(self->mFile) - self->mOffset;
-}
-
-status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
-{
-    LOGV("setDataSource url=%s, fd=%d\n", path, fd);
-
-    // file still open?
-    Mutex::Autolock l(mMutex);
-    if (mState == STATE_OPEN) {
-        reset_nosync();
-    }
-
-    // open file and set paused state
-    if (path) {
-        mFile = fopen(path, "r");
-    } else {
-        mFile = fdopen(dup(fd), "r");
-    }
-    if (mFile == NULL) {
-        return ERROR_OPEN_FAILED;
-    }
-
-    struct stat sb;
-    int ret;
-    if (path) {
-        ret = stat(path, &sb);
-    } else {
-        ret = fstat(fd, &sb);
-    }
-    if (ret != 0) {
-        mState = STATE_ERROR;
-        fclose(mFile);
-        return ERROR_OPEN_FAILED;
-    }
-    if (sb.st_size > (length + offset)) {
-        mLength = length;
-    } else {
-        mLength = sb.st_size - offset;
-    }
-
-    ov_callbacks callbacks = {
-        (size_t (*)(void *, size_t, size_t, void *))  vp_fread,
-        (int (*)(void *, ogg_int64_t, int))           vp_fseek,
-        (int (*)(void *))                             vp_fclose,
-        (long (*)(void *))                            vp_ftell
-    };
-
-    mOffset = offset;
-    fseek(mFile, offset, SEEK_SET);
-
-    int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks);
-    if (result < 0) {
-        LOGE("ov_open() failed: [%d]\n", (int)result);
-        mState = STATE_ERROR;
-        fclose(mFile);
-        return ERROR_OPEN_FAILED;
-    }
-
-    // look for the android loop tag  (for ringtones)
-    char **ptr = ov_comment(&mVorbisFile,-1)->user_comments;
-    while(*ptr) {
-        // does the comment start with ANDROID_LOOP_TAG
-        if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
-            // read the value of the tag
-            char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1;
-            mAndroidLoop = (strncmp(val, "true", 4) == 0);
-        }
-        // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG,
-        // as we could find another one  (the tag might have been appended more than once).
-        ++ptr;
-    }
-    LOGV_IF(mAndroidLoop, "looped sound");
-
-    mState = STATE_OPEN;
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::prepare()
-{
-    LOGV("prepare\n");
-    if (mState != STATE_OPEN ) {
-        return ERROR_NOT_OPEN;
-    }
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::prepareAsync() {
-    LOGV("prepareAsync\n");
-    // can't hold the lock here because of the callback
-    // it's safe because we don't change state
-    if (mState != STATE_OPEN ) {
-        sendEvent(MEDIA_ERROR);
-        return NO_ERROR;
-    }
-    sendEvent(MEDIA_PREPARED);
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::start()
-{
-    LOGV("start\n");
-    Mutex::Autolock l(mMutex);
-    if (mState != STATE_OPEN) {
-        return ERROR_NOT_OPEN;
-    }
-
-    mPaused = false;
-    mRender = true;
-
-    // wake up render thread
-    LOGV("  wakeup render thread\n");
-    mCondition.signal();
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::stop()
-{
-    LOGV("stop\n");
-    Mutex::Autolock l(mMutex);
-    if (mState != STATE_OPEN) {
-        return ERROR_NOT_OPEN;
-    }
-    mPaused = true;
-    mRender = false;
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::seekTo(int position)
-{
-    LOGV("seekTo %d\n", position);
-    Mutex::Autolock l(mMutex);
-    if (mState != STATE_OPEN) {
-        return ERROR_NOT_OPEN;
-    }
-
-    int result = ov_time_seek(&mVorbisFile, position);
-    if (result != 0) {
-        LOGE("ov_time_seek() returned %d\n", result);
-        return result;
-    }
-    sendEvent(MEDIA_SEEK_COMPLETE);
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::pause()
-{
-    LOGV("pause\n");
-    Mutex::Autolock l(mMutex);
-    if (mState != STATE_OPEN) {
-        return ERROR_NOT_OPEN;
-    }
-    mPaused = true;
-    return NO_ERROR;
-}
-
-bool VorbisPlayer::isPlaying()
-{
-    LOGV("isPlaying\n");
-    if (mState == STATE_OPEN) {
-        return mRender;
-    }
-    return false;
-}
-
-status_t VorbisPlayer::getCurrentPosition(int* position)
-{
-    LOGV("getCurrentPosition\n");
-    Mutex::Autolock l(mMutex);
-    if (mState != STATE_OPEN) {
-        LOGE("getCurrentPosition(): file not open");
-        return ERROR_NOT_OPEN;
-    }
-    *position = ov_time_tell(&mVorbisFile);
-    if (*position < 0) {
-        LOGE("getCurrentPosition(): ov_time_tell returned %d", *position);
-        return *position;
-    }
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::getDuration(int* duration)
-{
-    LOGV("getDuration\n");
-    Mutex::Autolock l(mMutex);
-    if (mState != STATE_OPEN) {
-        return ERROR_NOT_OPEN;
-    }
-
-    int ret = ov_time_total(&mVorbisFile, -1);
-    if (ret == OV_EINVAL) {
-        return -1;
-    }
-
-    *duration = ret;
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::release()
-{
-    LOGV("release\n");
-    Mutex::Autolock l(mMutex);
-    reset_nosync();
-
-    // TODO: timeout when thread won't exit
-    // wait for render thread to exit
-    if (mRenderTid > 0) {
-        mExit = true;
-        mCondition.signal();
-        mCondition.wait(mMutex);
-    }
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::reset()
-{
-    LOGV("reset\n");
-    Mutex::Autolock l(mMutex);
-    return reset_nosync();
-}
-
-// always call with lock held
-status_t VorbisPlayer::reset_nosync()
-{
-    // close file
-    if (mFile != NULL) {
-        ov_clear(&mVorbisFile); // this also closes the FILE
-        if (mFile != NULL) {
-            LOGV("OOPS! Vorbis didn't close the file");
-            fclose(mFile);
-            mFile = NULL;
-        }
-    }
-    mState = STATE_ERROR;
-
-    mPlayTime = -1;
-    mDuration = -1;
-    mLoop = false;
-    mAndroidLoop = false;
-    mPaused = false;
-    mRender = false;
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::setLooping(int loop)
-{
-    LOGV("setLooping\n");
-    Mutex::Autolock l(mMutex);
-    mLoop = (loop != 0);
-    return NO_ERROR;
-}
-
-status_t VorbisPlayer::createOutputTrack() {
-    // open audio track
-    vorbis_info *vi = ov_info(&mVorbisFile, -1);
-
-    LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
-            vi->rate, vi->channels);
-    if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
-        LOGE("mAudioSink open failed");
-        return ERROR_OPEN_FAILED;
-    }
-    return NO_ERROR;
-}
-
-int VorbisPlayer::renderThread(void* p) {
-    return ((VorbisPlayer*)p)->render();
-}
-
-#define AUDIOBUFFER_SIZE 4096
-
-int VorbisPlayer::render() {
-    int result = -1;
-    int temp;
-    int current_section = 0;
-    bool audioStarted = false;
-
-    LOGV("render\n");
-
-    // allocate render buffer
-    mAudioBuffer = new char[AUDIOBUFFER_SIZE];
-    if (!mAudioBuffer) {
-        LOGE("mAudioBuffer allocate failed\n");
-        goto threadExit;
-    }
-
-    // let main thread know we're ready
-    {
-        Mutex::Autolock l(mMutex);
-        mRenderTid = myTid();
-        mCondition.signal();
-    }
-
-    while (1) {
-        long numread = 0;
-        {
-            Mutex::Autolock l(mMutex);
-
-            // pausing?
-            if (mPaused) {
-                if (mAudioSink->ready()) mAudioSink->pause();
-                mRender = false;
-                audioStarted = false;
-            }
-
-            // nothing to render, wait for client thread to wake us up
-            if (!mExit && !mRender) {
-                LOGV("render - signal wait\n");
-                mCondition.wait(mMutex);
-                LOGV("render - signal rx'd\n");
-            }
-            if (mExit) break;
-
-            // We could end up here if start() is called, and before we get a
-            // chance to run, the app calls stop() or reset(). Re-check render
-            // flag so we don't try to render in stop or reset state.
-            if (!mRender) continue;
-
-            // render vorbis data into the input buffer
-            numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
-            if (numread == 0) {
-                // end of file, do we need to loop?
-                // ...
-                if (mLoop || mAndroidLoop) {
-                    ov_time_seek(&mVorbisFile, 0);
-                    current_section = 0;
-                    numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
-                } else {
-                    mAudioSink->stop();
-                    audioStarted = false;
-                    mRender = false;
-                    mPaused = true;
-                    int endpos = ov_time_tell(&mVorbisFile);
-
-                    LOGV("send MEDIA_PLAYBACK_COMPLETE");
-                    sendEvent(MEDIA_PLAYBACK_COMPLETE);
-
-                    // wait until we're started again
-                    LOGV("playback complete - wait for signal");
-                    mCondition.wait(mMutex);
-                    LOGV("playback complete - signal rx'd");
-                    if (mExit) break;
-
-                    // if we're still at the end, restart from the beginning
-                    if (mState == STATE_OPEN) {
-                        int curpos = ov_time_tell(&mVorbisFile);
-                        if (curpos == endpos) {
-                            ov_time_seek(&mVorbisFile, 0);
-                        }
-                        current_section = 0;
-                        numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
-                    }
-                }
-            }
-        }
-
-        // codec returns negative number on error
-        if (numread < 0) {
-            LOGE("Error in Vorbis decoder");
-            sendEvent(MEDIA_ERROR);
-            break;
-        }
-
-        // create audio output track if necessary
-        if (!mAudioSink->ready()) {
-            LOGV("render - create output track\n");
-            if (createOutputTrack() != NO_ERROR)
-                break;
-        }
-
-        // Write data to the audio hardware
-        if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) {
-            LOGE("Error in writing:%d",temp);
-            result = temp;
-            break;
-        }
-
-        // start audio output if necessary
-        if (!audioStarted && !mPaused && !mExit) {
-            LOGV("render - starting audio\n");
-            mAudioSink->start();
-            audioStarted = true;
-        }
-    }
-
-threadExit:
-    mAudioSink.clear();
-    if (mAudioBuffer) {
-        delete [] mAudioBuffer;
-        mAudioBuffer = NULL;
-    }
-
-    // tell main thread goodbye
-    Mutex::Autolock l(mMutex);
-    mRenderTid = -1;
-    mCondition.signal();
-    return result;
-}
-
-} // end namespace android
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
deleted file mode 100644
index 4a50835..0000000
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-**
-** Copyright 2008, 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 ANDROID_VORBISPLAYER_H
-#define ANDROID_VORBISPLAYER_H
-
-#include <utils/threads.h>
-
-#include <media/MediaPlayerInterface.h>
-#include <media/AudioTrack.h>
-
-#include "ivorbiscodec.h"
-#include "ivorbisfile.h"
-
-#define ANDROID_LOOP_TAG "ANDROID_LOOP"
-
-namespace android {
-
-class VorbisPlayer : public MediaPlayerInterface {
-public:
-                        VorbisPlayer();
-                        ~VorbisPlayer();
-
-    virtual void        onFirstRef();
-    virtual status_t    initCheck();
-
-    virtual status_t    setDataSource(
-            const char *uri, const KeyedVector<String8, String8> *headers);
-
-    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length);
-    virtual status_t    setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
-    virtual status_t    prepare();
-    virtual status_t    prepareAsync();
-    virtual status_t    start();
-    virtual status_t    stop();
-    virtual status_t    seekTo(int msec);
-    virtual status_t    pause();
-    virtual bool        isPlaying();
-    virtual status_t    getCurrentPosition(int* msec);
-    virtual status_t    getDuration(int* msec);
-    virtual status_t    release();
-    virtual status_t    reset();
-    virtual status_t    setLooping(int loop);
-    virtual player_type playerType() { return VORBIS_PLAYER; }
-    virtual status_t    invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
-
-private:
-            status_t    setdatasource(const char *path, int fd, int64_t offset, int64_t length);
-            status_t    reset_nosync();
-            status_t    createOutputTrack();
-    static  int         renderThread(void*);
-            int         render();
-
-    static  size_t      vp_fread(void *, size_t, size_t, void *);
-    static  int         vp_fseek(void *, ogg_int64_t, int);
-    static  int         vp_fclose(void *);
-    static  long        vp_ftell(void *);
-
-    Mutex               mMutex;
-    Condition           mCondition;
-    FILE*               mFile;
-    int64_t             mOffset;
-    int64_t             mLength;
-    OggVorbis_File      mVorbisFile;
-    char*               mAudioBuffer;
-    int                 mPlayTime;
-    int                 mDuration;
-    status_t            mState;
-    int                 mStreamType;
-    bool                mLoop;
-    bool                mAndroidLoop;
-    volatile bool       mExit;
-    bool                mPaused;
-    volatile bool       mRender;
-    pid_t               mRenderTid;
-};
-
-}; // namespace android
-
-#endif // ANDROID_VORBISPLAYER_H
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 0fea72e..9fc1d27 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -212,7 +212,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         int64_t seekFrame = seekTimeUs / 20000ll;  // 20ms per frame.
         mCurrentTimeUs = seekFrame * 20000ll;
         mOffset = seekFrame * mFrameSize + (mIsWide ? 9 : 6);
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index bf4424b..c71743e 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -22,19 +22,24 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/MetaData.h>
+#include <media/mediarecorder.h>
 
 namespace android {
 
 AMRWriter::AMRWriter(const char *filename)
     : mFile(fopen(filename, "wb")),
       mInitCheck(mFile != NULL ? OK : NO_INIT),
-      mStarted(false) {
+      mStarted(false),
+      mPaused(false),
+      mResumed(false) {
 }
 
 AMRWriter::AMRWriter(int fd)
     : mFile(fdopen(fd, "wb")),
       mInitCheck(mFile != NULL ? OK : NO_INIT),
-      mStarted(false) {
+      mStarted(false),
+      mPaused(false),
+      mResumed(false) {
 }
 
 AMRWriter::~AMRWriter() {
@@ -53,8 +58,6 @@
 }
 
 status_t AMRWriter::addSource(const sp<MediaSource> &source) {
-    Mutex::Autolock autoLock(mLock);
-
     if (mInitCheck != OK) {
         return mInitCheck;
     }
@@ -94,17 +97,24 @@
     return OK;
 }
 
-status_t AMRWriter::start() {
-    Mutex::Autolock autoLock(mLock);
-
+status_t AMRWriter::start(MetaData *params) {
     if (mInitCheck != OK) {
         return mInitCheck;
     }
 
-    if (mStarted || mSource == NULL) {
+    if (mSource == NULL) {
         return UNKNOWN_ERROR;
     }
 
+    if (mStarted && mPaused) {
+        mPaused = false;
+        mResumed = true;
+        return OK;
+    } else if (mStarted) {
+        // Already started, does nothing
+        return OK;
+    }
+
     status_t err = mSource->start();
 
     if (err != OK) {
@@ -126,16 +136,19 @@
     return OK;
 }
 
-void AMRWriter::stop() {
-    {
-        Mutex::Autolock autoLock(mLock);
-
-        if (!mStarted) {
-            return;
-        }
-
-        mDone = true;
+void AMRWriter::pause() {
+    if (!mStarted) {
+        return;
     }
+    mPaused = true;
+}
+
+void AMRWriter::stop() {
+    if (!mStarted) {
+        return;
+    }
+
+    mDone = true;
 
     void *dummy;
     pthread_join(mThread, &dummy);
@@ -145,6 +158,20 @@
     mStarted = false;
 }
 
+bool AMRWriter::exceedsFileSizeLimit() {
+    if (mMaxFileSizeLimitBytes == 0) {
+        return false;
+    }
+    return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes;
+}
+
+bool AMRWriter::exceedsFileDurationLimit() {
+    if (mMaxFileDurationLimitUs == 0) {
+        return false;
+    }
+    return mEstimatedDurationUs >= mMaxFileDurationLimitUs;
+}
+
 // static
 void *AMRWriter::ThreadWrapper(void *me) {
     static_cast<AMRWriter *>(me)->threadFunc();
@@ -153,13 +180,13 @@
 }
 
 void AMRWriter::threadFunc() {
-    for (;;) {
-        Mutex::Autolock autoLock(mLock);
+    mEstimatedDurationUs = 0;
+    mEstimatedSizeBytes = 0;
+    bool stoppedPrematurely = true;
+    int64_t previousPausedDurationUs = 0;
+    int64_t maxTimestampUs = 0;
 
-        if (mDone) {
-            break;
-        }
-
+    while (!mDone) {
         MediaBuffer *buffer;
         status_t err = mSource->read(&buffer);
 
@@ -167,6 +194,42 @@
             break;
         }
 
+        if (mPaused) {
+            buffer->release();
+            buffer = NULL;
+            continue;
+        }
+
+        mEstimatedSizeBytes += buffer->range_length();
+        if (exceedsFileSizeLimit()) {
+            buffer->release();
+            buffer = NULL;
+            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+            break;
+        }
+
+        int64_t timestampUs;
+        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+        if (timestampUs > mEstimatedDurationUs) {
+            mEstimatedDurationUs = timestampUs;
+        }
+        if (mResumed) {
+            previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
+            mResumed = false;
+        }
+        timestampUs -= previousPausedDurationUs;
+        LOGV("time stamp: %lld, previous paused duration: %lld",
+                timestampUs, previousPausedDurationUs);
+        if (timestampUs > maxTimestampUs) {
+            maxTimestampUs = timestampUs;
+        }
+
+        if (exceedsFileDurationLimit()) {
+            buffer->release();
+            buffer = NULL;
+            notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
+            break;
+        }
         ssize_t n = fwrite(
                 (const uint8_t *)buffer->data() + buffer->range_offset(),
                 1,
@@ -180,16 +243,26 @@
             break;
         }
 
+        // XXX: How to tell it is stopped prematurely?
+        if (stoppedPrematurely) {
+            stoppedPrematurely = false;
+        }
+
         buffer->release();
         buffer = NULL;
     }
 
-    Mutex::Autolock autoLock(mLock);
+    if (stoppedPrematurely) {
+        notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+    }
+
+    fflush(mFile);
+    fclose(mFile);
+    mFile = NULL;
     mReachedEOS = true;
 }
 
 bool AMRWriter::reachedEOS() {
-    Mutex::Autolock autoLock(mLock);
     return mReachedEOS;
 }
 
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 81f995b..89bfc1f 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -1,51 +1,46 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:=                 \
-        ESDS.cpp                  \
-        MediaBuffer.cpp           \
-        MediaBufferGroup.cpp      \
-        MediaDefs.cpp             \
-        MediaSource.cpp           \
-        MetaData.cpp              \
-        OMXCodec.cpp              \
-        Utils.cpp                 \
-        OMXClient.cpp
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
 
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_SRC_FILES +=                \
-        AMRExtractor.cpp          \
-        AMRWriter.cpp             \
-        AudioPlayer.cpp           \
-        AudioSource.cpp           \
-        AwesomePlayer.cpp         \
-        CachingDataSource.cpp     \
-        CameraSource.cpp          \
-        DataSource.cpp            \
-        FileSource.cpp            \
-        HTTPDataSource.cpp        \
-        HTTPStream.cpp            \
-        JPEGSource.cpp            \
-        MP3Extractor.cpp          \
-        MPEG4Extractor.cpp        \
-        MPEG4Writer.cpp           \
-        MediaExtractor.cpp        \
-        OggExtractor.cpp          \
-        Prefetcher.cpp            \
-        SampleIterator.cpp        \
-        SampleTable.cpp           \
-        ShoutcastSource.cpp       \
-        StagefrightMediaScanner.cpp \
-        StagefrightMetadataRetriever.cpp \
-        TimeSource.cpp            \
-        TimedEventQueue.cpp       \
-        WAVExtractor.cpp          \
+LOCAL_SRC_FILES:=                         \
+        AMRExtractor.cpp                  \
+        AMRWriter.cpp                     \
+        AudioPlayer.cpp                   \
+        AudioSource.cpp                   \
+        AwesomePlayer.cpp                 \
+        CameraSource.cpp                  \
+        DataSource.cpp                    \
+        ESDS.cpp                          \
+        FileSource.cpp                    \
+        HTTPStream.cpp                    \
+        JPEGSource.cpp                    \
+        MP3Extractor.cpp                  \
+        MPEG4Extractor.cpp                \
+        MPEG4Writer.cpp                   \
+        MediaBuffer.cpp                   \
+        MediaBufferGroup.cpp              \
+        MediaDefs.cpp                     \
+        MediaExtractor.cpp                \
+        MediaSource.cpp                   \
+        MetaData.cpp                      \
+        NuCachedSource2.cpp               \
+        NuHTTPDataSource.cpp              \
+        OMXClient.cpp                     \
+        OMXCodec.cpp                      \
+        OggExtractor.cpp                  \
+        SampleIterator.cpp                \
+        SampleTable.cpp                   \
+        ShoutcastSource.cpp               \
+        StagefrightMediaScanner.cpp       \
+        StagefrightMetadataRetriever.cpp  \
+        ThrottledSource.cpp               \
+        TimeSource.cpp                    \
+        TimedEventQueue.cpp               \
+        Utils.cpp                         \
+        WAVExtractor.cpp                  \
         string.cpp
 
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT
-endif
-
 LOCAL_C_INCLUDES:= \
 	$(JNI_H_INCLUDE) \
         $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
@@ -65,24 +60,30 @@
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_aacdec \
+        libstagefright_aacenc \
         libstagefright_amrnbdec \
         libstagefright_amrnbenc \
         libstagefright_amrwbdec \
+        libstagefright_amrwbenc \
         libstagefright_avcdec \
+        libstagefright_avcenc \
         libstagefright_m4vh263dec \
+        libstagefright_m4vh263enc \
         libstagefright_mp3dec \
-        libstagefright_vorbisdec
+        libstagefright_vorbisdec \
+        libstagefright_matroska \
+        libstagefright_vpxdec \
+        libvpx \
+        libstagefright_mpeg2ts \
+        libstagefright_httplive \
+        libstagefright_rtsp \
+        libstagefright_id3 \
 
 LOCAL_SHARED_LIBRARIES += \
         libstagefright_amrnb_common \
-        libstagefright_avc_common
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_STATIC_LIBRARIES += \
-        libstagefright_id3
-
-LOCAL_SHARED_LIBRARIES += \
+        libstagefright_enc_common \
+        libstagefright_avc_common \
+        libstagefright_foundation \
         libstagefright_color_conversion
 
 ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
@@ -95,8 +96,6 @@
 LOCAL_SHARED_LIBRARIES += libdl
 endif
 
-endif
-
 ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
         LOCAL_LDLIBS += -lpthread
 endif
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index edabaf9..50c0edc 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioSource"
+#include <utils/Log.h>
+
 #include <media/stagefright/AudioSource.h>
 
 #include <media/AudioRecord.h>
@@ -21,16 +25,33 @@
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
+#include <cutils/properties.h>
+#include <sys/time.h>
+#include <time.h>
 
 namespace android {
 
 AudioSource::AudioSource(
         int inputSource, uint32_t sampleRate, uint32_t channels)
-    : mRecord(new AudioRecord(
-                inputSource, sampleRate, AudioSystem::PCM_16_BIT, channels)),
-      mInitCheck(mRecord->initCheck()),
-      mStarted(false),
+    : mStarted(false),
+      mCollectStats(false),
+      mTotalReadTimeUs(0),
+      mTotalReadBytes(0),
+      mTotalReads(0),
       mGroup(NULL) {
+
+    LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
+    uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
+                     AudioRecord::RECORD_NS_ENABLE  |
+                     AudioRecord::RECORD_IIR_ENABLE;
+
+    mRecord = new AudioRecord(
+                inputSource, sampleRate, AudioSystem::PCM_16_BIT,
+                channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
+                4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
+                flags);
+
+    mInitCheck = mRecord->initCheck();
 }
 
 AudioSource::~AudioSource() {
@@ -51,6 +72,19 @@
         return UNKNOWN_ERROR;
     }
 
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.record-stats", value, NULL)
+        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+        mCollectStats = true;
+    }
+
+    mTrackMaxAmplitude = false;
+    mMaxAmplitude = 0;
+    mStartTimeUs = 0;
+    int64_t startTimeUs;
+    if (params && params->findInt64(kKeyTime, &startTimeUs)) {
+        mStartTimeUs = startTimeUs;
+    }
     status_t err = mRecord->start();
 
     if (err == OK) {
@@ -75,6 +109,13 @@
 
     mStarted = false;
 
+    if (mCollectStats) {
+        LOGI("%lld reads: %.2f bps in %lld us",
+                mTotalReads,
+                (mTotalReadBytes * 8000000.0) / mTotalReadTimeUs,
+                mTotalReadTimeUs);
+    }
+
     return OK;
 }
 
@@ -91,32 +132,105 @@
 status_t AudioSource::read(
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
+    ++mTotalReads;
 
     MediaBuffer *buffer;
     CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
 
-    uint32_t numFramesRecorded;
-    mRecord->getPosition(&numFramesRecorded);
+    while (mStarted) {
+        uint32_t numFramesRecorded;
+        mRecord->getPosition(&numFramesRecorded);
+        int64_t latency = mRecord->latency() * 1000;
 
-    buffer->meta_data()->setInt64(
-            kKeyTime,
-            (1000000ll * numFramesRecorded) / mRecord->getSampleRate()
-            - mRecord->latency() * 1000);
+        int64_t readTime = systemTime() / 1000;
 
-    ssize_t n = mRecord->read(buffer->data(), buffer->size());
+        if (numFramesRecorded == 0) {
+            // Initial delay
+            if (mStartTimeUs > 0) {
+                mStartTimeUs = readTime - mStartTimeUs;
+            } else {
+                mStartTimeUs += latency;
+            }
+        }
 
-    if (n < 0) {
-        buffer->release();
-        buffer = NULL;
+        ssize_t n = 0;
+        if (mCollectStats) {
+            n = mRecord->read(buffer->data(), buffer->size());
+            int64_t endTime = systemTime() / 1000;
+            mTotalReadTimeUs += (endTime - readTime);
+            if (n >= 0) {
+                mTotalReadBytes += n;
+            }
+        } else {
+            n = mRecord->read(buffer->data(), buffer->size());
+        }
 
-        return (status_t)n;
+        if (n < 0) {
+            buffer->release();
+            buffer = NULL;
+
+            return (status_t)n;
+        }
+
+        uint32_t sampleRate = mRecord->getSampleRate();
+        int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate +
+                                 mStartTimeUs;
+        int64_t skipFrameUs;
+        if (!options || !options->getSkipFrame(&skipFrameUs)) {
+            skipFrameUs = timestampUs;  // Don't skip frame
+        }
+
+        if (skipFrameUs > timestampUs) {
+            // Safe guard against the abuse of the kSkipFrame_Option.
+            if (skipFrameUs - timestampUs >= 1E6) {
+                LOGE("Frame skipping requested is way too long: %lld us",
+                    skipFrameUs - timestampUs);
+                buffer->release();
+                return UNKNOWN_ERROR;
+            }
+            LOGV("skipFrame: %lld us > timestamp: %lld us, samples %d",
+                skipFrameUs, timestampUs, numFramesRecorded);
+            continue;
+        }
+
+        if (mTrackMaxAmplitude) {
+            trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
+        }
+
+        buffer->meta_data()->setInt64(kKeyTime, timestampUs);
+        LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
+                mStartTimeUs, sampleRate, timestampUs);
+
+        buffer->set_range(0, n);
+
+        *out = buffer;
+        return OK;
     }
 
-    buffer->set_range(0, n);
-
-    *out = buffer;
-
     return OK;
 }
 
+void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
+    for (int i = nSamples; i > 0; --i) {
+        int16_t value = *data++;
+        if (value < 0) {
+            value = -value;
+        }
+        if (mMaxAmplitude < value) {
+            mMaxAmplitude = value;
+        }
+    }
+}
+
+int16_t AudioSource::getMaxAmplitude() {
+    // First call activates the tracking.
+    if (!mTrackMaxAmplitude) {
+        mTrackMaxAmplitude = true;
+    }
+    int16_t value = mMaxAmplitude;
+    mMaxAmplitude = 0;
+    LOGV("max amplitude since last call: %d", value);
+    return value;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 274dad9..236a62b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -20,13 +20,15 @@
 
 #include <dlfcn.h>
 
+#include "include/ARTSPController.h"
 #include "include/AwesomePlayer.h"
-#include "include/Prefetcher.h"
+#include "include/LiveSource.h"
 #include "include/SoftwareRenderer.h"
+#include "include/NuCachedSource2.h"
+#include "include/ThrottledSource.h"
 
 #include <binder/IPCThreadState.h>
 #include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/CachingDataSource.h>
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
 #include <media/stagefright/MediaBuffer.h>
@@ -39,6 +41,8 @@
 
 #include <surfaceflinger/ISurface.h>
 
+#include <media/stagefright/foundation/ALooper.h>
+
 namespace android {
 
 struct AwesomeEvent : public TimedEventQueue::Event {
@@ -261,6 +265,16 @@
 
 status_t AwesomePlayer::setDataSource(
         int fd, int64_t offset, int64_t length) {
+#if 0
+    // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_96.m3u8");
+    // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_1500.m3u8");
+    return setDataSource("httplive://iphone.video.hsn.com/iPhone_high.m3u8");
+    // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/iphonewebcast/webcast090209_all/webcast090209_all.m3u8");
+    // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_062209_iphone/hi/prog_index.m3u8");
+    // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_googmaps/hi/prog_index.m3u8");
+    // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/mtv/ni_spo_25a_rt74137_clip_syn/hi/prog_index.m3u8");
+#endif
+
     Mutex::Autolock autoLock(mLock);
 
     reset_l();
@@ -340,11 +354,7 @@
 
     cancelPlayerEvents();
 
-    if (mPrefetcher != NULL) {
-        CHECK_EQ(mPrefetcher->getStrongCount(), 1);
-    }
-    mPrefetcher.clear();
-
+    mCachedSource.clear();
     mAudioTrack.clear();
     mVideoTrack.clear();
 
@@ -361,9 +371,6 @@
     }
     mAudioSource.clear();
 
-    if (mTimeSource != mAudioPlayer) {
-        delete mTimeSource;
-    }
     mTimeSource = NULL;
 
     delete mAudioPlayer;
@@ -381,6 +388,8 @@
         mVideoBuffer = NULL;
     }
 
+    mRTSPController.clear();
+
     if (mVideoSource != NULL) {
         mVideoSource->stop();
 
@@ -432,29 +441,45 @@
     }
     mBufferingEventPending = false;
 
-    int64_t durationUs;
-    {
-        Mutex::Autolock autoLock(mMiscStateLock);
-        durationUs = mDurationUs;
+    if (mCachedSource == NULL) {
+        return;
     }
 
-    if (durationUs >= 0) {
-        int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
+    size_t lowWatermark = 400000;
+    size_t highWatermark = 1000000;
 
-        LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
+    off_t size;
+    if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
+        int64_t bitrate = size * 8000000ll / mDurationUs;  // in bits/sec
 
-        int64_t positionUs;
-        getPosition(&positionUs);
+        size_t cachedSize = mCachedSource->cachedSize();
+        int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
 
-        cachedDurationUs += positionUs;
+        double percentage = (double)cachedDurationUs / mDurationUs;
 
-        double percentage = (double)cachedDurationUs / durationUs;
         notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
 
-        postBufferingEvent_l();
-    } else {
-        LOGE("Not sending buffering status because duration is unknown.");
+        lowWatermark = 2 * bitrate / 8;  // 2 secs
+        highWatermark = 10 * bitrate / 8;  // 10 secs
     }
+
+    bool eos;
+    size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
+
+    if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) {
+        LOGI("cache is running low (< %d) , pausing.", lowWatermark);
+        mFlags |= CACHE_UNDERRUN;
+        pause_l();
+        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
+    } else if ((mFlags & CACHE_UNDERRUN)
+            && (eos || cachedDataRemaining > highWatermark)) {
+        LOGI("cache has filled up (> %d), resuming.", highWatermark);
+        mFlags &= ~CACHE_UNDERRUN;
+        play_l();
+        notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+    }
+
+    postBufferingEvent_l();
 }
 
 void AwesomePlayer::onStreamDone() {
@@ -466,22 +491,35 @@
     }
     mStreamDoneEventPending = false;
 
-    if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
+    if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
+        LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
+
+        notifyListener_l(
+                MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
+
+        pause_l();
+
+        mFlags |= AT_EOS;
+        return;
+    }
+
+    const bool allDone =
+        (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
+            && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
+
+    if (!allDone) {
+        return;
+    }
+
+    if (mFlags & LOOPING) {
         seekTo_l(0);
 
         if (mVideoSource != NULL) {
             postVideoEvent_l();
         }
     } else {
-        if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
-            LOGV("MEDIA_PLAYBACK_COMPLETE");
-            notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
-        } else {
-            LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
-
-            notifyListener_l(
-                    MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
-        }
+        LOGV("MEDIA_PLAYBACK_COMPLETE");
+        notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
 
         pause_l();
 
@@ -491,6 +529,9 @@
 
 status_t AwesomePlayer::play() {
     Mutex::Autolock autoLock(mLock);
+
+    mFlags &= ~CACHE_UNDERRUN;
+
     return play_l();
 }
 
@@ -532,7 +573,6 @@
                     return err;
                 }
 
-                delete mTimeSource;
                 mTimeSource = mAudioPlayer;
 
                 deferredAudioSeek = true;
@@ -548,7 +588,7 @@
     }
 
     if (mTimeSource == NULL && mAudioPlayer == NULL) {
-        mTimeSource = new SystemTimeSource;
+        mTimeSource = &mSystemTimeSource;
     }
 
     if (mVideoSource != NULL) {
@@ -615,6 +655,9 @@
 
 status_t AwesomePlayer::pause() {
     Mutex::Autolock autoLock(mLock);
+
+    mFlags &= ~CACHE_UNDERRUN;
+
     return pause_l();
 }
 
@@ -635,7 +678,7 @@
 }
 
 bool AwesomePlayer::isPlaying() const {
-    return mFlags & PLAYING;
+    return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
 }
 
 void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
@@ -702,10 +745,15 @@
 }
 
 status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
+    if (mFlags & CACHE_UNDERRUN) {
+        mFlags &= ~CACHE_UNDERRUN;
+        play_l();
+    }
+
     mSeeking = true;
     mSeekNotificationSent = false;
     mSeekTimeUs = timeUs;
-    mFlags &= ~AT_EOS;
+    mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
 
     seekAudioIfNecessary_l();
 
@@ -747,10 +795,6 @@
 void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
     CHECK(source != NULL);
 
-    if (mPrefetcher != NULL) {
-        source = mPrefetcher->addSource(source);
-    }
-
     mAudioTrack = source;
 }
 
@@ -797,10 +841,6 @@
 void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
     CHECK(source != NULL);
 
-    if (mPrefetcher != NULL) {
-        source = mPrefetcher->addSource(source);
-    }
-
     mVideoTrack = source;
 }
 
@@ -852,6 +892,21 @@
             mVideoBuffer->release();
             mVideoBuffer = NULL;
         }
+
+        if (mCachedSource != NULL && mAudioSource != NULL) {
+            // We're going to seek the video source first, followed by
+            // the audio source.
+            // In order to avoid jumps in the DataSource offset caused by
+            // the audio codec prefetching data from the old locations
+            // while the video codec is already reading data from the new
+            // locations, we'll "pause" the audio source, causing it to
+            // stop reading input data until a subsequent seek.
+
+            if (mAudioPlayer != NULL) {
+                mAudioPlayer->pause();
+            }
+            mAudioSource->pause();
+        }
     }
 
     if (!mVideoBuffer) {
@@ -859,7 +914,8 @@
         if (mSeeking) {
             LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
 
-            options.setSeekTo(mSeekTimeUs);
+            options.setSeekTo(
+                    mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
         }
         for (;;) {
             status_t err = mVideoSource->read(&mVideoBuffer, &options);
@@ -878,6 +934,7 @@
                     continue;
                 }
 
+                mFlags |= VIDEO_AT_EOS;
                 postStreamDoneEvent_l(err);
                 return;
             }
@@ -908,6 +965,7 @@
             LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
 
             mAudioPlayer->seekTo(timeUs);
+            mAudioPlayer->resume();
             mWatchForAudioSeekComplete = true;
             mWatchForAudioEOS = true;
         } else if (!mSeekNotificationSent) {
@@ -921,19 +979,21 @@
         mSeekNotificationSent = false;
     }
 
+    TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
+
     if (mFlags & FIRST_FRAME) {
         mFlags &= ~FIRST_FRAME;
 
-        mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
+        mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
     }
 
     int64_t realTimeUs, mediaTimeUs;
-    if (mAudioPlayer != NULL
+    if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
         && mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
         mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
     }
 
-    int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
+    int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
 
     int64_t latenessUs = nowUs - timeUs;
 
@@ -995,10 +1055,6 @@
 }
 
 void AwesomePlayer::postBufferingEvent_l() {
-    if (mPrefetcher == NULL) {
-        return;
-    }
-
     if (mBufferingEventPending) {
         return;
     }
@@ -1038,6 +1094,8 @@
     status_t finalStatus;
     if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
         mWatchForAudioEOS = false;
+        mFlags |= AUDIO_AT_EOS;
+        mFlags |= FIRST_FRAME;
         postStreamDoneEvent_l(finalStatus);
     }
 
@@ -1106,10 +1164,10 @@
     sp<DataSource> dataSource;
 
     if (!strncasecmp("http://", mUri.string(), 7)) {
-        mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
+        mConnectingDataSource = new NuHTTPDataSource;
 
         mLock.unlock();
-        status_t err = mConnectingDataSource->connect();
+        status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
         mLock.lock();
 
         if (err != OK) {
@@ -1119,10 +1177,46 @@
             return err;
         }
 
-        dataSource = new CachingDataSource(
-                mConnectingDataSource, 64 * 1024, 10);
-
+#if 0
+        mCachedSource = new NuCachedSource2(
+                new ThrottledSource(
+                    mConnectingDataSource, 50 * 1024 /* bytes/sec */));
+#else
+        mCachedSource = new NuCachedSource2(mConnectingDataSource);
+#endif
         mConnectingDataSource.clear();
+
+        dataSource = mCachedSource;
+    } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
+        String8 uri("http://");
+        uri.append(mUri.string() + 11);
+
+        dataSource = new LiveSource(uri.string());
+
+        mCachedSource = new NuCachedSource2(dataSource);
+        dataSource = mCachedSource;
+
+        sp<MediaExtractor> extractor =
+            MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+        return setDataSource_l(extractor);
+    } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
+        if (mLooper == NULL) {
+            mLooper = new ALooper;
+            mLooper->start();
+        }
+        mRTSPController = new ARTSPController(mLooper);
+        status_t err = mRTSPController->connect(mUri.string());
+
+        LOGI("ARTSPController::connect returned %d", err);
+
+        if (err != OK) {
+            mRTSPController.clear();
+            return err;
+        }
+
+        sp<MediaExtractor> extractor = mRTSPController.get();
+        return setDataSource_l(extractor);
     } else {
         dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
     }
@@ -1137,10 +1231,6 @@
         return UNKNOWN_ERROR;
     }
 
-    if (dataSource->flags() & DataSource::kWantsPrefetching) {
-        mPrefetcher = new Prefetcher;
-    }
-
     return setDataSource_l(extractor);
 }
 
@@ -1165,8 +1255,6 @@
 }
 
 void AwesomePlayer::onPrepareAsyncEvent() {
-    sp<Prefetcher> prefetcher;
-
     {
         Mutex::Autolock autoLock(mLock);
 
@@ -1202,39 +1290,6 @@
                 return;
             }
         }
-
-        prefetcher = mPrefetcher;
-    }
-
-    if (prefetcher != NULL) {
-        {
-            Mutex::Autolock autoLock(mLock);
-            if (mFlags & PREPARE_CANCELLED) {
-                LOGI("prepare was cancelled before preparing the prefetcher");
-
-                prefetcher.clear();
-                abortPrepare(UNKNOWN_ERROR);
-                return;
-            }
-        }
-
-        LOGI("calling prefetcher->prepare()");
-        status_t result =
-            prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
-
-        prefetcher.clear();
-
-        if (result == OK) {
-            LOGI("prefetcher is done preparing");
-        } else {
-            Mutex::Autolock autoLock(mLock);
-
-            CHECK_EQ(result, -EINTR);
-
-            LOGI("prefetcher->prepare() was cancelled early.");
-            abortPrepare(UNKNOWN_ERROR);
-            return;
-        }
     }
 
     Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/CachingDataSource.cpp b/media/libstagefright/CachingDataSource.cpp
deleted file mode 100644
index 1ca463e..0000000
--- a/media/libstagefright/CachingDataSource.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <media/stagefright/CachingDataSource.h>
-#include <media/stagefright/MediaDebug.h>
-
-namespace android {
-
-CachingDataSource::CachingDataSource(
-        const sp<DataSource> &source, size_t pageSize, int numPages)
-    : mSource(source),
-      mData(malloc(pageSize * numPages)),
-      mPageSize(pageSize),
-      mFirst(NULL),
-      mLast(NULL) {
-    for (int i = 0; i < numPages; ++i) {
-        Page *page = new Page;
-        page->mPrev = mLast;
-        page->mNext = NULL;
-
-        if (mLast == NULL) {
-            mFirst = page;
-        } else {
-            mLast->mNext = page;
-        }
-
-        mLast = page;
-
-        page->mOffset = -1;
-        page->mLength = 0;
-        page->mData = (char *)mData + mPageSize * i;
-    }
-}
-
-CachingDataSource::~CachingDataSource() {
-    Page *page = mFirst;
-    while (page != NULL) {
-        Page *next = page->mNext;
-        delete page;
-        page = next;
-    }
-    mFirst = mLast = NULL;
-
-    free(mData);
-    mData = NULL;
-}
-
-status_t CachingDataSource::initCheck() const {
-    return mSource->initCheck();
-}
-
-status_t CachingDataSource::getSize(off_t *size) {
-    return mSource->getSize(size);
-}
-
-uint32_t CachingDataSource::flags() {
-    return mSource->flags();
-}
-
-ssize_t CachingDataSource::readAt(off_t offset, void *data, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    size_t total = 0;
-    while (size > 0) {
-        Page *page = mFirst;
-        while (page != NULL) {
-            if (page->mOffset >= 0 && offset >= page->mOffset
-                && offset < page->mOffset + (off_t)page->mLength) {
-                break;
-            }
-            page = page->mNext;
-        }
-
-        if (page == NULL) {
-            page = allocate_page();
-            page->mOffset = offset - offset % mPageSize;
-            ssize_t n = mSource->readAt(page->mOffset, page->mData, mPageSize);
-            if (n < 0) {
-                page->mLength = 0;
-            } else {
-                page->mLength = (size_t)n;
-            }
-            mFirst->mPrev = page;
-            page->mNext = mFirst;
-            page->mPrev = NULL;
-            mFirst = page;
-
-            if (n < 0) {
-                return n;
-            }
-
-            if (offset >= page->mOffset + (off_t)page->mLength) {
-                break;
-            }
-        } else {
-            // Move "page" to the front in LRU order.
-            if (page->mNext != NULL) {
-                page->mNext->mPrev = page->mPrev;
-            } else {
-                mLast = page->mPrev;
-            }
-
-            if (page->mPrev != NULL) {
-                page->mPrev->mNext = page->mNext;
-            } else {
-                mFirst = page->mNext;
-            }
-
-            mFirst->mPrev = page;
-            page->mNext = mFirst;
-            page->mPrev = NULL;
-            mFirst = page;
-        }
-
-        size_t copy = page->mLength - (offset - page->mOffset);
-        if (copy > size) {
-            copy = size;
-        }
-        memcpy(data,(const char *)page->mData + (offset - page->mOffset),
-               copy);
-
-        total += copy;
-
-        if (page->mLength < mPageSize) {
-            // This was the final page. There is no more data beyond it.
-            break;
-        }
-
-        offset += copy;
-        size -= copy;
-        data = (char *)data + copy;
-    }
-
-    return total;
-}
-
-CachingDataSource::Page *CachingDataSource::allocate_page() {
-    // The last page is the least recently used, i.e. oldest.
-
-    Page *page = mLast;
-
-    page->mPrev->mNext = NULL;
-    mLast = page->mPrev;
-    page->mPrev = NULL;
-
-    return page;
-}
-
-}  // namespace android
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 075b1e3..9c48daf 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#include <sys/time.h>
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CameraSource"
+#include <utils/Log.h>
 
 #include <OMX_Component.h>
-
-#include <binder/IServiceManager.h>
-#include <cutils/properties.h> // for property_get
+#include <binder/IPCThreadState.h>
 #include <media/stagefright/CameraSource.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
@@ -27,46 +27,11 @@
 #include <media/stagefright/MetaData.h>
 #include <camera/Camera.h>
 #include <camera/CameraParameters.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/Overlay.h>
-#include <surfaceflinger/ISurface.h>
 #include <utils/String8.h>
+#include <cutils/properties.h>
 
 namespace android {
 
-static int64_t getNowUs() {
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-
-    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
-}
-
-struct DummySurface : public BnSurface {
-    DummySurface() {}
-
-    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) {
-        return NULL;
-    }
-
-    virtual status_t registerBuffers(const BufferHeap &buffers) {
-        return OK;
-    }
-
-    virtual void postBuffer(ssize_t offset) {}
-    virtual void unregisterBuffers() {}
-
-    virtual sp<OverlayRef> createOverlay(
-            uint32_t w, uint32_t h, int32_t format, int32_t orientation) {
-        return NULL;
-    }
-
-protected:
-    virtual ~DummySurface() {}
-
-    DummySurface(const DummySurface &);
-    DummySurface &operator=(const DummySurface &);
-};
-
 struct CameraSourceListener : public CameraListener {
     CameraSourceListener(const sp<CameraSource> &source);
 
@@ -100,22 +65,40 @@
 void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) {
     LOGV("postData(%d, ptr:%p, size:%d)",
          msgType, dataPtr->pointer(), dataPtr->size());
-
-    sp<CameraSource> source = mSource.promote();
-    if (source.get() != NULL) {
-        source->dataCallback(msgType, dataPtr);
-    }
 }
 
 void CameraSourceListener::postDataTimestamp(
         nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
-    LOGV("postDataTimestamp(%lld, %d, ptr:%p, size:%d)",
-         timestamp, msgType, dataPtr->pointer(), dataPtr->size());
+
+    sp<CameraSource> source = mSource.promote();
+    if (source.get() != NULL) {
+        source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
+    }
+}
+
+static int32_t getColorFormat(const char* colorFormat) {
+    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
+       return OMX_COLOR_FormatYUV422SemiPlanar;
+    }
+
+    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+        return OMX_COLOR_FormatYUV420SemiPlanar;
+    }
+
+    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
+        return OMX_COLOR_FormatYCbYCr;
+    }
+
+    if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
+       return OMX_COLOR_Format16bitRGB565;
+    }
+
+    CHECK_EQ(0, "Unknown color format");
 }
 
 // static
 CameraSource *CameraSource::Create() {
-    sp<Camera> camera = Camera::connect();
+    sp<Camera> camera = Camera::connect(0);
 
     if (camera.get() == NULL) {
         return NULL;
@@ -125,9 +108,7 @@
 }
 
 // static
-CameraSource *CameraSource::CreateFromICamera(const sp<ICamera> &icamera) {
-    sp<Camera> camera = Camera::create(icamera);
-
+CameraSource *CameraSource::CreateFromCamera(const sp<Camera> &camera) {
     if (camera.get() == NULL) {
         return NULL;
     }
@@ -137,23 +118,50 @@
 
 CameraSource::CameraSource(const sp<Camera> &camera)
     : mCamera(camera),
-      mWidth(0),
-      mHeight(0),
       mFirstFrameTimeUs(0),
-      mNumFrames(0),
+      mLastFrameTimestampUs(0),
+      mNumFramesReceived(0),
+      mNumFramesEncoded(0),
+      mNumFramesDropped(0),
+      mNumGlitches(0),
+      mGlitchDurationThresholdUs(200000),
+      mCollectStats(false),
       mStarted(false) {
-    char value[PROPERTY_VALUE_MAX];
-    if (property_get("ro.hardware", value, NULL) && !strcmp(value, "sholes")) {
-        // The hardware encoder(s) do not support yuv420, but only YCbYCr,
-        // fortunately the camera also supports this, so we needn't transcode.
-        mCamera->setParameters(String8("preview-format=yuv422i-yuyv"));
-    }
 
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
     String8 s = mCamera->getParameters();
+    IPCThreadState::self()->restoreCallingIdentity(token);
+
     printf("params: \"%s\"\n", s.string());
 
+    int32_t width, height, stride, sliceHeight;
     CameraParameters params(s);
-    params.getPreviewSize(&mWidth, &mHeight);
+    params.getPreviewSize(&width, &height);
+
+    // Calculate glitch duraton threshold based on frame rate
+    int32_t frameRate = params.getPreviewFrameRate();
+    int64_t glitchDurationUs = (1000000LL / frameRate);
+    if (glitchDurationUs > mGlitchDurationThresholdUs) {
+        mGlitchDurationThresholdUs = glitchDurationUs;
+    }
+
+    const char *colorFormatStr = params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT);
+    CHECK(colorFormatStr != NULL);
+    int32_t colorFormat = getColorFormat(colorFormatStr);
+
+    // XXX: query camera for the stride and slice height
+    // when the capability becomes available.
+    stride = width;
+    sliceHeight = height;
+
+    mMeta = new MetaData;
+    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+    mMeta->setInt32(kKeyColorFormat, colorFormat);
+    mMeta->setInt32(kKeyWidth, width);
+    mMeta->setInt32(kKeyHeight, height);
+    mMeta->setInt32(kKeyStride, stride);
+    mMeta->setInt32(kKeySliceHeight, sliceHeight);
+
 }
 
 CameraSource::~CameraSource() {
@@ -162,60 +170,105 @@
     }
 }
 
-void CameraSource::setPreviewSurface(const sp<ISurface> &surface) {
-    mPreviewSurface = surface;
-}
-
-status_t CameraSource::start(MetaData *) {
+status_t CameraSource::start(MetaData *meta) {
     CHECK(!mStarted);
 
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.record-stats", value, NULL)
+        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+        mCollectStats = true;
+    }
+
+    mStartTimeUs = 0;
+    int64_t startTimeUs;
+    if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
+        mStartTimeUs = startTimeUs;
+    }
+
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
     mCamera->setListener(new CameraSourceListener(this));
-
-    status_t err =
-        mCamera->setPreviewDisplay(
-                mPreviewSurface != NULL ? mPreviewSurface : new DummySurface);
-    CHECK_EQ(err, OK);
-
-    mCamera->setPreviewCallbackFlags(
-            FRAME_CALLBACK_FLAG_ENABLE_MASK
-            | FRAME_CALLBACK_FLAG_COPY_OUT_MASK);
-
-    err = mCamera->startPreview();
-    CHECK_EQ(err, OK);
+    CHECK_EQ(OK, mCamera->startRecording());
+    IPCThreadState::self()->restoreCallingIdentity(token);
 
     mStarted = true;
-
     return OK;
 }
 
 status_t CameraSource::stop() {
-    CHECK(mStarted);
-
-    mCamera->stopPreview();
-
+    LOGV("stop");
+    Mutex::Autolock autoLock(mLock);
     mStarted = false;
+    mFrameAvailableCondition.signal();
 
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    mCamera->setListener(NULL);
+    mCamera->stopRecording();
+    releaseQueuedFrames();
+    while (!mFramesBeingEncoded.empty()) {
+        LOGI("Waiting for outstanding frames being encoded: %d",
+                mFramesBeingEncoded.size());
+        mFrameCompleteCondition.wait(mLock);
+    }
+    mCamera = NULL;
+    IPCThreadState::self()->restoreCallingIdentity(token);
+
+    if (mCollectStats) {
+        LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
+                mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
+                mLastFrameTimestampUs - mFirstFrameTimeUs);
+    }
+
+    CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
     return OK;
 }
 
-sp<MetaData> CameraSource::getFormat() {
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
-    meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420SemiPlanar);
-    meta->setInt32(kKeyWidth, mWidth);
-    meta->setInt32(kKeyHeight, mHeight);
+void CameraSource::releaseQueuedFrames() {
+    List<sp<IMemory> >::iterator it;
+    while (!mFramesReceived.empty()) {
+        it = mFramesReceived.begin();
+        mCamera->releaseRecordingFrame(*it);
+        mFramesReceived.erase(it);
+        ++mNumFramesDropped;
+    }
+}
 
-    return meta;
+sp<MetaData> CameraSource::getFormat() {
+    return mMeta;
+}
+
+void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
+    int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    mCamera->releaseRecordingFrame(frame);
+    IPCThreadState::self()->restoreCallingIdentity(token);
+}
+
+void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
+    LOGV("signalBufferReturned: %p", buffer->data());
+    for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
+         it != mFramesBeingEncoded.end(); ++it) {
+        if ((*it)->pointer() ==  buffer->data()) {
+
+            releaseOneRecordingFrame((*it));
+            mFramesBeingEncoded.erase(it);
+            ++mNumFramesEncoded;
+            buffer->setObserver(0);
+            buffer->release();
+            mFrameCompleteCondition.signal();
+            return;
+        }
+    }
+    CHECK_EQ(0, "signalBufferReturned: bogus buffer");
 }
 
 status_t CameraSource::read(
         MediaBuffer **buffer, const ReadOptions *options) {
-    CHECK(mStarted);
+    LOGV("read");
 
     *buffer = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         return ERROR_UNSUPPORTED;
     }
 
@@ -224,38 +277,88 @@
 
     {
         Mutex::Autolock autoLock(mLock);
-        while (mFrames.empty()) {
-            mFrameAvailableCondition.wait(mLock);
+        while (mStarted) {
+            while(mFramesReceived.empty()) {
+                mFrameAvailableCondition.wait(mLock);
+            }
+
+            if (!mStarted) {
+                return OK;
+            }
+
+            frame = *mFramesReceived.begin();
+            mFramesReceived.erase(mFramesReceived.begin());
+
+            frameTime = *mFrameTimes.begin();
+            mFrameTimes.erase(mFrameTimes.begin());
+            int64_t skipTimeUs;
+            if (!options || !options->getSkipFrame(&skipTimeUs)) {
+                skipTimeUs = frameTime;
+            }
+            if (skipTimeUs > frameTime) {
+                LOGV("skipTimeUs: %lld us > frameTime: %lld us",
+                    skipTimeUs, frameTime);
+                releaseOneRecordingFrame(frame);
+                ++mNumFramesDropped;
+                // Safeguard against the abuse of the kSkipFrame_Option.
+                if (skipTimeUs - frameTime >= 1E6) {
+                    LOGE("Frame skipping requested is way too long: %lld us",
+                        skipTimeUs - frameTime);
+                    return UNKNOWN_ERROR;
+                }
+            } else {
+                mFramesBeingEncoded.push_back(frame);
+                *buffer = new MediaBuffer(frame->pointer(), frame->size());
+                (*buffer)->setObserver(this);
+                (*buffer)->add_ref();
+                (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
+                return OK;
+            }
         }
-
-        frame = *mFrames.begin();
-        mFrames.erase(mFrames.begin());
-
-        frameTime = *mFrameTimes.begin();
-        mFrameTimes.erase(mFrameTimes.begin());
     }
-
-    *buffer = new MediaBuffer(frame->size());
-    memcpy((*buffer)->data(), frame->pointer(), frame->size());
-    (*buffer)->set_range(0, frame->size());
-
-    (*buffer)->meta_data()->clear();
-    (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
-
     return OK;
 }
 
-void CameraSource::dataCallback(int32_t msgType, const sp<IMemory> &data) {
+void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
+        int32_t msgType, const sp<IMemory> &data) {
+    LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
     Mutex::Autolock autoLock(mLock);
-
-    int64_t nowUs = getNowUs();
-    if (mNumFrames == 0) {
-        mFirstFrameTimeUs = nowUs;
+    if (!mStarted) {
+        releaseOneRecordingFrame(data);
+        ++mNumFramesReceived;
+        ++mNumFramesDropped;
+        return;
     }
-    ++mNumFrames;
 
-    mFrames.push_back(data);
-    mFrameTimes.push_back(nowUs - mFirstFrameTimeUs);
+    if (mNumFramesReceived > 0 &&
+        timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
+        if (mNumGlitches % 10 == 0) {  // Don't spam the log
+            LOGW("Long delay detected in video recording");
+        }
+        ++mNumGlitches;
+    }
+
+    mLastFrameTimestampUs = timestampUs;
+    if (mNumFramesReceived == 0) {
+        mFirstFrameTimeUs = timestampUs;
+        // Initial delay
+        if (mStartTimeUs > 0) {
+            if (timestampUs < mStartTimeUs) {
+                // Frame was captured before recording was started
+                // Drop it without updating the statistical data.
+                releaseOneRecordingFrame(data);
+                return;
+            }
+            mStartTimeUs = timestampUs - mStartTimeUs;
+        }
+    }
+    ++mNumFramesReceived;
+
+    mFramesReceived.push_back(data);
+    int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
+    mFrameTimes.push_back(timeUs);
+    LOGV("initial delay: %lld, current time stamp: %lld",
+        mStartTimeUs, timeUs);
     mFrameAvailableCondition.signal();
 }
 
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index a66f86b..90a596c 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -19,11 +19,14 @@
 #include "include/MPEG4Extractor.h"
 #include "include/WAVExtractor.h"
 #include "include/OggExtractor.h"
+#include "include/MPEG2TSExtractor.h"
+#include "include/NuCachedSource2.h"
+#include "include/NuHTTPDataSource.h"
 
-#include <media/stagefright/CachingDataSource.h>
+#include "matroska/MatroskaExtractor.h"
+
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/FileSource.h>
-#include <media/stagefright/HTTPDataSource.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/String8.h>
 
@@ -94,6 +97,8 @@
     RegisterSniffer(SniffAMR);
     RegisterSniffer(SniffWAV);
     RegisterSniffer(SniffOgg);
+    RegisterSniffer(SniffMatroska);
+    RegisterSniffer(SniffMPEG2TS);
 }
 
 // static
@@ -103,11 +108,11 @@
     if (!strncasecmp("file://", uri, 7)) {
         source = new FileSource(uri + 7);
     } else if (!strncasecmp("http://", uri, 7)) {
-        sp<HTTPDataSource> httpSource = new HTTPDataSource(uri, headers);
-        if (httpSource->connect() != OK) {
+        sp<NuHTTPDataSource> httpSource = new NuHTTPDataSource;
+        if (httpSource->connect(uri, headers) != OK) {
             return NULL;
         }
-        source = new CachingDataSource(httpSource, 64 * 1024, 10);
+        source = new NuCachedSource2(httpSource);
     } else {
         // Assume it's a filename.
         source = new FileSource(uri);
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index b6f1af2..dd2579b 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -45,6 +45,10 @@
 }
 
 ssize_t FileSource::readAt(off_t offset, void *data, size_t size) {
+    if (mFile == NULL) {
+        return NO_INIT;
+    }
+
     Mutex::Autolock autoLock(mLock);
 
     if (mLength >= 0) {
@@ -67,6 +71,10 @@
 }
 
 status_t FileSource::getSize(off_t *size) {
+    if (mFile == NULL) {
+        return NO_INIT;
+    }
+
     if (mLength >= 0) {
         *size = mLength;
 
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
deleted file mode 100644
index f72a6cc..0000000
--- a/media/libstagefright/HTTPDataSource.cpp
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Copyright (C) 2009 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 "HTTPDataSource"
-#include <utils/Log.h>
-
-#include "include/stagefright_string.h"
-#include "include/HTTPStream.h"
-
-#include <stdlib.h>
-
-#include <cutils/properties.h>
-#include <media/stagefright/HTTPDataSource.h>
-#include <media/stagefright/MediaDebug.h>
-
-namespace android {
-
-status_t HTTPDataSource::connectWithRedirectsAndRange(off_t rangeStart) {
-    string host = mStartingHost.string();
-    string path = mStartingPath.string();
-    int port = mStartingPort;
-
-    LOGV("Connecting to host '%s', port %d, path '%s'",
-         host.c_str(), port, path.c_str());
-
-    int numRedirectsRemaining = 5;
-    while (numRedirectsRemaining-- > 0) {
-        {
-            Mutex::Autolock autoLock(mStateLock);
-            if (mState == DISCONNECTED) {
-                return UNKNOWN_ERROR;
-            }
-        }
-
-        status_t err = mHttp->connect(host.c_str(), port);
-
-        if (err != OK) {
-            return err;
-        }
-
-        String8 request;
-        request.append("GET ");
-        request.append(path.c_str());
-        request.append(" HTTP/1.1\r\n");
-        request.append(mHeaders);
-        request.append("Host: ");
-        request.append(host.c_str());
-        request.append("\r\n");
-
-        if (rangeStart > 0) {
-            char range[128];
-            sprintf(range, "Range: bytes=%ld-\r\n", rangeStart);
-
-            request.append(range);
-        }
-
-        request.append("\r\n");
-
-        err = mHttp->send(request.string());
-
-        if (err != OK) {
-            return err;
-        }
-
-        int httpStatus;
-        err = mHttp->receive_header(&httpStatus);
-
-        if (err != OK) {
-            return err;
-        }
-
-        if (httpStatus >= 200 && httpStatus < 300) {
-            applyTimeoutResponse();
-            return OK;
-        }
-
-        if (httpStatus != 301 && httpStatus != 302) {
-            LOGE("HTTP request failed w/ http status %d", httpStatus);
-            return ERROR_IO;
-        }
-
-        string location;
-        CHECK(mHttp->find_header_value("Location", &location));
-
-        CHECK(string(location, 0, 7) == "http://");
-        location.erase(0, 7);
-        string::size_type slashPos = location.find('/');
-        if (slashPos == string::npos) {
-            slashPos = location.size();
-            location += '/';
-        }
-
-        mHttp->disconnect();
-
-        LOGV("Redirecting to %s\n", location.c_str());
-
-        host = string(location, 0, slashPos);
-
-        string::size_type colonPos = host.find(':');
-        if (colonPos != string::npos) {
-            const char *start = host.c_str() + colonPos + 1;
-            char *end;
-            long tmp = strtol(start, &end, 10);
-            CHECK(end > start && (*end == '\0'));
-
-            port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80;
-
-            host.erase(colonPos, host.size() - colonPos);
-        } else {
-            port = 80;
-        }
-
-        path = string(location, slashPos);
-
-        mStartingHost = host.c_str();
-        mStartingPath = path.c_str();
-        mStartingPort = port;
-    }
-
-    return ERROR_IO;
-}
-
-void HTTPDataSource::applyTimeoutResponse() {
-    string timeout;
-    if (mHttp->find_header_value("X-SocketTimeout", &timeout)) {
-        const char *s = timeout.c_str();
-        char *end;
-        long tmp = strtol(s, &end, 10);
-        if (end == s || *end != '\0') {
-            LOGW("Illegal X-SocketTimeout value given.");
-            return;
-        }
-
-        LOGI("overriding default timeout, new timeout is %ld seconds", tmp);
-        mHttp->setReceiveTimeout(tmp);
-    }
-}
-
-HTTPDataSource::HTTPDataSource(
-        const char *uri, const KeyedVector<String8, String8> *headers) {
-    CHECK(!strncasecmp("http://", uri, 7));
-
-    string host;
-    string path;
-    int port;
-
-    char *slash = strchr(uri + 7, '/');
-    if (slash == NULL) {
-        host = uri + 7;
-        path = "/";
-    } else {
-        host = string(uri + 7, slash - (uri + 7));
-        path = slash;
-    }
-
-    char *colon = strchr(host.c_str(), ':');
-    if (colon == NULL) {
-        port = 80;
-    } else {
-        char *end;
-        long tmp = strtol(colon + 1, &end, 10);
-        CHECK(end > colon + 1);
-        CHECK(tmp > 0 && tmp < 65536);
-        port = tmp;
-
-        host = string(host, 0, colon - host.c_str());
-    }
-
-    mStartingHost = host.c_str();
-    mStartingPath = path.c_str();
-    mStartingPort = port;
-
-    init(headers);
-}
-
-HTTPDataSource::HTTPDataSource(
-        const char *_host, int port, const char *_path,
-        const KeyedVector<String8, String8> *headers) {
-    mStartingHost = _host;
-    mStartingPath = _path;
-    mStartingPort = port;
-
-    init(headers);
-}
-
-void HTTPDataSource::init(const KeyedVector<String8, String8> *headers) {
-    mState = DISCONNECTED;
-    mHttp = new HTTPStream;
-
-    initHeaders(headers);
-
-    mBuffer = malloc(kBufferSize);
-
-    mNumRetriesLeft = kMaxNumRetries;
-}
-
-status_t HTTPDataSource::connect() {
-    {
-        Mutex::Autolock autoLock(mStateLock);
-
-        if (mState != DISCONNECTED) {
-            return ERROR_ALREADY_CONNECTED;
-        }
-
-        mState = CONNECTING;
-    }
-
-    mBufferLength = 0;
-    mBufferOffset = 0;
-    mContentLengthValid = false;
-
-    status_t err = connectWithRedirectsAndRange(0);
-
-    if (err != OK) {
-        Mutex::Autolock autoLock(mStateLock);
-
-        if (mState != CONNECTING) {
-            LOGV("connect() cancelled");
-        }
-        mState = DISCONNECTED;
-
-        return err;
-    }
-
-    string value;
-    if (mHttp->find_header_value("Content-Length", &value)) {
-        char *end;
-        mContentLength = strtoull(value.c_str(), &end, 10);
-        mContentLengthValid = true;
-    }
-
-    Mutex::Autolock autoLock(mStateLock);
-
-    if (mState != CONNECTING) {
-        // disconnect was called when we had just successfully connected.
-        LOGV("connect() cancelled (we had just succeeded connecting)");
-
-        mHttp->disconnect();
-        return UNKNOWN_ERROR;
-    }
-
-    mState = CONNECTED;
-
-    return OK;
-}
-
-void HTTPDataSource::disconnect() {
-    Mutex::Autolock autoLock(mStateLock);
-
-    if (mState == CONNECTING || mState == CONNECTED) {
-        mHttp->disconnect();
-        mState = DISCONNECTED;
-    }
-}
-
-status_t HTTPDataSource::initCheck() const {
-    Mutex::Autolock autoLock(mStateLock);
-
-    return (mState == CONNECTED) ? (status_t)OK : ERROR_NOT_CONNECTED;
-}
-
-status_t HTTPDataSource::getSize(off_t *size) {
-    *size = 0;
-
-    {
-        Mutex::Autolock autoLock(mStateLock);
-        if (mState != CONNECTED) {
-            return ERROR_NOT_CONNECTED;
-        }
-    }
-
-    if (!mContentLengthValid) {
-        return ERROR_UNSUPPORTED;
-    }
-
-    *size = mContentLength;
-
-    return OK;
-}
-
-HTTPDataSource::~HTTPDataSource() {
-    disconnect();
-
-    delete mHttp;
-    mHttp = NULL;
-
-    free(mBuffer);
-    mBuffer = NULL;
-}
-
-ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
-    status_t err = connectWithRedirectsAndRange(offset);
-
-    if (err != OK) {
-        return err;
-    }
-
-    string value;
-    if (!mHttp->find_header_value("Content-Length", &value)) {
-        return kBufferSize;
-    }
-
-    char *end;
-    unsigned long contentLength = strtoul(value.c_str(), &end, 10);
-
-    return contentLength;
-}
-
-ssize_t HTTPDataSource::readAt(off_t offset, void *data, size_t size) {
-    LOGV("readAt %ld, size %d", offset, size);
-
-rinse_repeat:
-    {
-        Mutex::Autolock autoLock(mStateLock);
-        if (mState != CONNECTED) {
-            return ERROR_NOT_CONNECTED;
-        }
-    }
-
-    if (offset >= mBufferOffset
-            && offset < (off_t)(mBufferOffset + mBufferLength)) {
-        size_t num_bytes_available = mBufferLength - (offset - mBufferOffset);
-
-        size_t copy = num_bytes_available;
-        if (copy > size) {
-            copy = size;
-        }
-
-        memcpy(data, (const char *)mBuffer + (offset - mBufferOffset), copy);
-
-        if (copy < size) {
-            LOGV("short read (1), returning %d vs. %d requested", copy, size);
-        }
-
-        return copy;
-    }
-
-    ssize_t contentLength = 0;
-    if (offset != (off_t)(mBufferOffset + mBufferLength)) {
-        LOGV("new range offset=%ld (old=%ld)",
-             offset, mBufferOffset + mBufferLength);
-
-        mHttp->disconnect();
-
-        contentLength = sendRangeRequest(offset);
-
-        if (contentLength > kBufferSize) {
-            contentLength = kBufferSize;
-        }
-    } else {
-        contentLength = kBufferSize;
-    }
-
-    mBufferOffset = offset;
-
-    if (mContentLengthValid
-            && mBufferOffset + contentLength >= (off_t)mContentLength) {
-        // If we never triggered a range request but know the content length,
-        // make sure to not read more data than there could be, otherwise
-        // we'd block indefinitely if the server doesn't close the connection.
-
-        contentLength = mContentLength - mBufferOffset;
-    }
-
-    if (contentLength <= 0) {
-        return contentLength;
-    }
-
-    ssize_t num_bytes_received = mHttp->receive(mBuffer, contentLength);
-
-    if (num_bytes_received < 0
-            || (mContentLengthValid && num_bytes_received < contentLength)) {
-        if (mNumRetriesLeft-- > 0) {
-            mHttp->disconnect();
-            mBufferLength = 0;
-            num_bytes_received = connectWithRedirectsAndRange(mBufferOffset);
-            if (num_bytes_received == OK) {
-                LOGI("retrying connection succeeded.");
-                goto rinse_repeat;
-            }
-            LOGE("retrying connection failed");
-        }
-
-        mBufferLength = 0;
-
-        return num_bytes_received;
-    }
-
-    mBufferLength = (size_t)num_bytes_received;
-
-    size_t copy = mBufferLength;
-    if (copy > size) {
-        copy = size;
-    }
-
-    memcpy(data, mBuffer, copy);
-
-    return copy;
-}
-
-void HTTPDataSource::initHeaders(
-        const KeyedVector<String8, String8> *overrides) {
-    mHeaders = String8();
-
-    mHeaders.append("User-Agent: stagefright/1.0 (Linux;Android ");
-
-#if (PROPERTY_VALUE_MAX < 8)
-#error "PROPERTY_VALUE_MAX must be at least 8"
-#endif
-
-    char value[PROPERTY_VALUE_MAX];
-    property_get("ro.build.version.release", value, "Unknown");
-    mHeaders.append(value);
-    mHeaders.append(")\r\n");
-
-    if (overrides == NULL) {
-        return;
-    }
-
-    for (size_t i = 0; i < overrides->size(); ++i) {
-        String8 line;
-        line.append(overrides->keyAt(i));
-        line.append(": ");
-        line.append(overrides->valueAt(i));
-        line.append("\r\n");
-
-        mHeaders.append(line);
-    }
-}
-
-uint32_t HTTPDataSource::flags() {
-    uint32_t f = kWantsPrefetching;
-
-    if (!strcasecmp(mStartingHost.string(), "localhost")
-            || !strcmp(mStartingHost.string(), "127.0.0.1")) {
-        f |= kStreamedFromLocalHost;
-    }
-
-    return f;
-}
-
-}  // namespace android
-
diff --git a/media/libstagefright/JPEGSource.cpp b/media/libstagefright/JPEGSource.cpp
index a4be2dd..ec81097 100644
--- a/media/libstagefright/JPEGSource.cpp
+++ b/media/libstagefright/JPEGSource.cpp
@@ -112,7 +112,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options != NULL && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
         return UNKNOWN_ERROR;
     }
 
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index f9251e1..2248e23 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -586,7 +586,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options != NULL && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
         int32_t bitrate;
         if (!mMeta->findInt32(kKeyBitRate, &bitrate)) {
             // bitrate is in bits/sec.
@@ -634,6 +635,7 @@
     }
 
     size_t frame_size;
+    int bitrate;
     for (;;) {
         ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
         if (n < 4) {
@@ -646,7 +648,7 @@
         uint32_t header = U32_AT((const uint8_t *)buffer->data());
 
         if ((header & kMask) == (mFixedHeader & kMask)
-            && get_mp3_frame_size(header, &frame_size)) {
+            && get_mp3_frame_size(header, &frame_size, NULL, NULL, &bitrate)) {
             break;
         }
 
@@ -683,7 +685,7 @@
     buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
 
     mCurrentPos += frame_size;
-    mCurrentTimeUs += 1152 * 1000000 / 44100;
+    mCurrentTimeUs += frame_size * 8000ll / bitrate;
 
     *out = buffer;
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index a41b2f4..7cea629 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -428,6 +428,14 @@
         }
         chunk_size = ntoh64(chunk_size);
         data_offset += 8;
+
+        if (chunk_size < 16) {
+            // The smallest valid chunk is 16 bytes long in this case.
+            return ERROR_MALFORMED;
+        }
+    } else if (chunk_size < 8) {
+        // The smallest valid chunk is 8 bytes long.
+        return ERROR_MALFORMED;
     }
 
     char chunk[5];
@@ -1460,12 +1468,45 @@
 
     *out = NULL;
 
+    int64_t targetSampleTimeUs = -1;
+
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+        uint32_t findFlags = 0;
+        switch (mode) {
+            case ReadOptions::SEEK_PREVIOUS_SYNC:
+                findFlags = SampleTable::kFlagBefore;
+                break;
+            case ReadOptions::SEEK_NEXT_SYNC:
+                findFlags = SampleTable::kFlagAfter;
+                break;
+            case ReadOptions::SEEK_CLOSEST_SYNC:
+            case ReadOptions::SEEK_CLOSEST:
+                findFlags = SampleTable::kFlagClosest;
+                break;
+            default:
+                CHECK(!"Should not be here.");
+                break;
+        }
+
         uint32_t sampleIndex;
-        status_t err = mSampleTable->findClosestSample(
+        status_t err = mSampleTable->findSampleAtTime(
                 seekTimeUs * mTimescale / 1000000,
-                &sampleIndex, SampleTable::kSyncSample_Flag);
+                &sampleIndex, findFlags);
+
+        if (mode == ReadOptions::SEEK_CLOSEST) {
+            // We found the closest sample already, now we want the sync
+            // sample preceding it (or the sample itself of course), even
+            // if the subsequent sync sample is closer.
+            findFlags = SampleTable::kFlagBefore;
+        }
+
+        uint32_t syncSampleIndex;
+        if (err == OK) {
+            err = mSampleTable->findSyncSampleNear(
+                    sampleIndex, &syncSampleIndex, findFlags);
+        }
 
         if (err != OK) {
             if (err == ERROR_OUT_OF_RANGE) {
@@ -1479,7 +1520,27 @@
             return err;
         }
 
-        mCurrentSampleIndex = sampleIndex;
+        uint32_t sampleTime;
+        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
+                    sampleIndex, NULL, NULL, &sampleTime));
+
+        if (mode == ReadOptions::SEEK_CLOSEST) {
+            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
+        }
+
+#if 0
+        uint32_t syncSampleTime;
+        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
+                    syncSampleIndex, NULL, NULL, &syncSampleTime));
+
+        LOGI("seek to time %lld us => sample at time %lld us, "
+             "sync sample at time %lld us",
+             seekTimeUs,
+             sampleTime * 1000000ll / mTimescale,
+             syncSampleTime * 1000000ll / mTimescale);
+#endif
+
+        mCurrentSampleIndex = syncSampleIndex;
         if (mBuffer != NULL) {
             mBuffer->release();
             mBuffer = NULL;
@@ -1528,6 +1589,12 @@
             mBuffer->meta_data()->clear();
             mBuffer->meta_data()->setInt64(
                     kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
+
+            if (targetSampleTimeUs >= 0) {
+                mBuffer->meta_data()->setInt64(
+                        kKeyTargetTime, targetSampleTimeUs);
+            }
+
             ++mCurrentSampleIndex;
         }
 
@@ -1624,6 +1691,12 @@
         mBuffer->meta_data()->clear();
         mBuffer->meta_data()->setInt64(
                 kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
+
+        if (targetSampleTimeUs >= 0) {
+            mBuffer->meta_data()->setInt64(
+                    kKeyTargetTime, targetSampleTimeUs);
+        }
+
         ++mCurrentSampleIndex;
 
         *out = mBuffer;
@@ -1633,7 +1706,7 @@
     }
 }
 
-bool SniffMPEG4(
+static bool LegacySniffMPEG4(
         const sp<DataSource> &source, String8 *mimeType, float *confidence) {
     uint8_t header[8];
 
@@ -1657,5 +1730,83 @@
     return false;
 }
 
+static bool isCompatibleBrand(uint32_t fourcc) {
+    static const uint32_t kCompatibleBrands[] = {
+        FOURCC('i', 's', 'o', 'm'),
+        FOURCC('i', 's', 'o', '2'),
+        FOURCC('a', 'v', 'c', '1'),
+        FOURCC('3', 'g', 'p', '4'),
+        FOURCC('m', 'p', '4', '1'),
+        FOURCC('m', 'p', '4', '2'),
+    };
+
+    for (size_t i = 0;
+         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
+         ++i) {
+        if (kCompatibleBrands[i] == fourcc) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+// Attempt to actually parse the 'ftyp' atom and determine if a suitable
+// compatible brand is present.
+static bool BetterSniffMPEG4(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+    uint8_t header[12];
+    if (source->readAt(0, header, 12) != 12
+            || memcmp("ftyp", &header[4], 4)) {
+        return false;
+    }
+
+    size_t atomSize = U32_AT(&header[0]);
+    if (atomSize < 16 || (atomSize % 4) != 0) {
+        return false;
+    }
+
+    bool success = false;
+    if (isCompatibleBrand(U32_AT(&header[8]))) {
+        success = true;
+    } else {
+        size_t numCompatibleBrands = (atomSize - 16) / 4;
+        for (size_t i = 0; i < numCompatibleBrands; ++i) {
+            uint8_t tmp[4];
+            if (source->readAt(16 + i * 4, tmp, 4) != 4) {
+                return false;
+            }
+
+            if (isCompatibleBrand(U32_AT(&tmp[0]))) {
+                success = true;
+                break;
+            }
+        }
+    }
+
+    if (!success) {
+        return false;
+    }
+
+    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
+    *confidence = 0.3f;
+
+    return true;
+}
+
+bool SniffMPEG4(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+    if (BetterSniffMPEG4(source, mimeType, confidence)) {
+        return true;
+    }
+
+    if (LegacySniffMPEG4(source, mimeType, confidence)) {
+        LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
+        return true;
+    }
+
+    return false;
+}
+
 }  // namespace android
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 2cf0ddf..baf9f4f 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MPEG4Writer"
+#include <utils/Log.h>
+
 #include <arpa/inet.h>
 
 #include <ctype.h>
@@ -24,62 +28,136 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MediaDebug.h>
 #include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/Utils.h>
+#include <media/mediarecorder.h>
+#include <cutils/properties.h>
+
+#include "include/ESDS.h"
 
 namespace android {
 
 class MPEG4Writer::Track {
 public:
     Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+
     ~Track();
 
-    status_t start();
+    status_t start(MetaData *params);
     void stop();
+    void pause();
     bool reachedEOS();
 
     int64_t getDurationUs() const;
-    void writeTrackHeader(int32_t trackID);
+    int64_t getEstimatedTrackSizeBytes() const;
+    void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
 
 private:
     MPEG4Writer *mOwner;
     sp<MetaData> mMeta;
     sp<MediaSource> mSource;
     volatile bool mDone;
+    volatile bool mPaused;
+    volatile bool mResumed;
     int64_t mMaxTimeStampUs;
+    int64_t mEstimatedTrackSizeBytes;
+    int32_t mTimeScale;
 
     pthread_t mThread;
 
-    struct SampleInfo {
-        size_t size;
-        off_t offset;
-        int64_t timestamp;
+    // mNumSamples is used to track how many samples in mSampleSizes List.
+    // This is to reduce the cost associated with mSampleSizes.size() call,
+    // since it is O(n). Ideally, the fix should be in List class.
+    size_t              mNumSamples;
+    List<size_t>        mSampleSizes;
+    bool                mSamplesHaveSameSize;
+
+    List<MediaBuffer *> mChunkSamples;
+    List<off_t>         mChunkOffsets;
+
+    struct StscTableEntry {
+
+        StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
+            : firstChunk(chunk),
+              samplesPerChunk(samples),
+              sampleDescriptionId(id) {}
+
+        uint32_t firstChunk;
+        uint32_t samplesPerChunk;
+        uint32_t sampleDescriptionId;
     };
-    List<SampleInfo> mSampleInfos;
+    List<StscTableEntry> mStscTableEntries;
+
+    List<int32_t> mStssTableEntries;
+    List<int64_t> mChunkDurations;
+
+    struct SttsTableEntry {
+
+        SttsTableEntry(uint32_t count, uint32_t durationUs)
+            : sampleCount(count), sampleDurationUs(durationUs) {}
+
+        uint32_t sampleCount;
+        uint32_t sampleDurationUs;
+    };
+    List<SttsTableEntry> mSttsTableEntries;
 
     void *mCodecSpecificData;
     size_t mCodecSpecificDataSize;
+    bool mGotAllCodecSpecificData;
+    bool mTrackingProgressStatus;
 
     bool mReachedEOS;
+    int64_t mStartTimestampUs;
+    int64_t mPreviousTrackTimeUs;
+    int64_t mTrackEveryTimeDurationUs;
 
     static void *ThreadWrapper(void *me);
     void threadEntry();
 
+    status_t makeAVCCodecSpecificData(
+            const uint8_t *data, size_t size);
+    void writeOneChunk(bool isAvc);
+
+    // Track authoring progress status
+    void trackProgressStatus(int64_t timeUs, status_t err = OK);
+    void initTrackingProgressStatus(MetaData *params);
+
+    // Utilities for collecting statistical data
+    void logStatisticalData(bool isAudio);
+    void findMinAvgMaxSampleDurationMs(
+            int32_t *min, int32_t *avg, int32_t *max);
+    void findMinMaxChunkDurations(int64_t *min, int64_t *max);
+
+    void getCodecSpecificDataFromInputFormatIfPossible();
+
     Track(const Track &);
     Track &operator=(const Track &);
 };
 
+#define USE_NALLEN_FOUR         1
+
 MPEG4Writer::MPEG4Writer(const char *filename)
     : mFile(fopen(filename, "wb")),
+      mUse32BitOffset(true),
+      mPaused(false),
+      mStarted(false),
       mOffset(0),
-      mMdatOffset(0) {
+      mMdatOffset(0),
+      mEstimatedMoovBoxSize(0),
+      mInterleaveDurationUs(1000000) {
     CHECK(mFile != NULL);
 }
 
 MPEG4Writer::MPEG4Writer(int fd)
     : mFile(fdopen(fd, "wb")),
+      mUse32BitOffset(true),
+      mPaused(false),
+      mStarted(false),
       mOffset(0),
-      mMdatOffset(0) {
+      mMdatOffset(0),
+      mEstimatedMoovBoxSize(0),
+      mInterleaveDurationUs(1000000) {
     CHECK(mFile != NULL);
 }
 
@@ -100,23 +178,10 @@
     return OK;
 }
 
-status_t MPEG4Writer::start() {
-    if (mFile == NULL) {
-        return UNKNOWN_ERROR;
-    }
-
-    beginBox("ftyp");
-      writeFourcc("isom");
-      writeInt32(0);
-      writeFourcc("isom");
-    endBox();
-
-    mMdatOffset = mOffset;
-    write("\x00\x00\x00\x01mdat????????", 16);
-
+status_t MPEG4Writer::startTracks(MetaData *params) {
     for (List<Track *>::iterator it = mTracks.begin();
          it != mTracks.end(); ++it) {
-        status_t err = (*it)->start();
+        status_t err = (*it)->start(params);
 
         if (err != OK) {
             for (List<Track *>::iterator it2 = mTracks.begin();
@@ -127,34 +192,190 @@
             return err;
         }
     }
-
     return OK;
 }
 
+int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
+    // This implementation is highly experimental/heurisitic.
+    //
+    // Statistical analysis shows that metadata usually accounts
+    // for a small portion of the total file size, usually < 0.6%.
+    // Currently, lets set to 0.4% for now.
+
+    // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
+    // where 1MB is the common file size limit for MMS application.
+    // The default MAX _MOOV_BOX_SIZE value is based on about 4
+    // minute video recording with a bit rate about 3 Mbps, because
+    // statistics also show that most of the video captured are going
+    // to be less than 3 minutes.
+
+    // If the estimation is wrong, we will pay the price of wasting
+    // some reserved space. This should not happen so often statistically.
+    static const int32_t factor = mUse32BitOffset? 1: 2;
+    static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024;  // 4 KB
+    static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
+    int64_t size = MIN_MOOV_BOX_SIZE;
+
+    if (mMaxFileSizeLimitBytes != 0) {
+        size = mMaxFileSizeLimitBytes * 4 / 1000;
+    } else if (mMaxFileDurationLimitUs != 0) {
+        if (bitRate <= 0) {
+            // We could not estimate the file size since bitRate is not set.
+            size = MIN_MOOV_BOX_SIZE;
+        } else {
+            size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
+        }
+    }
+    if (size < MIN_MOOV_BOX_SIZE) {
+        size = MIN_MOOV_BOX_SIZE;
+    }
+
+    // Any long duration recording will be probably end up with
+    // non-streamable mp4 file.
+    if (size > MAX_MOOV_BOX_SIZE) {
+        size = MAX_MOOV_BOX_SIZE;
+    }
+
+    LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
+         " moov size %lld bytes",
+         mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
+    return factor * size;
+}
+
+status_t MPEG4Writer::start(MetaData *param) {
+    if (mFile == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    int32_t use64BitOffset;
+    if (param &&
+        param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
+        use64BitOffset) {
+        mUse32BitOffset = false;
+    }
+
+    // System property can overwrite the file offset bits parameter
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.record-64bits", value, NULL)
+        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+        mUse32BitOffset = false;
+    }
+
+    mStartTimestampUs = -1;
+
+    if (mStarted) {
+        if (mPaused) {
+            mPaused = false;
+            return startTracks(param);
+        }
+        return OK;
+    }
+
+    if (!param ||
+        !param->findInt32(kKeyTimeScale, &mTimeScale)) {
+        mTimeScale = 1000;
+    }
+    CHECK(mTimeScale > 0);
+    LOGV("movie time scale: %d", mTimeScale);
+
+    mStreamableFile = true;
+    mWriteMoovBoxToMemory = false;
+    mMoovBoxBuffer = NULL;
+    mMoovBoxBufferOffset = 0;
+
+    beginBox("ftyp");
+      {
+        int32_t fileType;
+        if (param && param->findInt32(kKeyFileType, &fileType) &&
+            fileType != OUTPUT_FORMAT_MPEG_4) {
+            writeFourcc("3gp4");
+        } else {
+            writeFourcc("isom");
+        }
+      }
+      writeInt32(0);
+      writeFourcc("isom");
+      writeFourcc("3gp4");
+    endBox();
+
+    mFreeBoxOffset = mOffset;
+
+    if (mEstimatedMoovBoxSize == 0) {
+        int32_t bitRate = -1;
+        if (param) {
+            param->findInt32(kKeyBitRate, &bitRate);
+        }
+        mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
+    }
+    CHECK(mEstimatedMoovBoxSize >= 8);
+    fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+    writeInt32(mEstimatedMoovBoxSize);
+    write("free", 4);
+
+    mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
+    mOffset = mMdatOffset;
+    fseeko(mFile, mMdatOffset, SEEK_SET);
+    if (mUse32BitOffset) {
+        write("????mdat", 8);
+    } else {
+        write("\x00\x00\x00\x01mdat????????", 16);
+    }
+    status_t err = startTracks(param);
+    if (err != OK) {
+        return err;
+    }
+    mStarted = true;
+    return OK;
+}
+
+void MPEG4Writer::pause() {
+    if (mFile == NULL) {
+        return;
+    }
+    mPaused = true;
+    for (List<Track *>::iterator it = mTracks.begin();
+         it != mTracks.end(); ++it) {
+        (*it)->pause();
+    }
+}
+
 void MPEG4Writer::stop() {
     if (mFile == NULL) {
         return;
     }
 
-    int64_t max_duration = 0;
+    int64_t maxDurationUs = 0;
     for (List<Track *>::iterator it = mTracks.begin();
          it != mTracks.end(); ++it) {
         (*it)->stop();
 
-        int64_t duration = (*it)->getDurationUs();
-        if (duration > max_duration) {
-            max_duration = duration;
+        int64_t durationUs = (*it)->getDurationUs();
+        if (durationUs > maxDurationUs) {
+            maxDurationUs = durationUs;
         }
     }
 
+
     // Fix up the size of the 'mdat' chunk.
-    fseek(mFile, mMdatOffset + 8, SEEK_SET);
-    int64_t size = mOffset - mMdatOffset;
-    size = hton64(size);
-    fwrite(&size, 1, 8, mFile);
-    fseek(mFile, mOffset, SEEK_SET);
+    if (mUse32BitOffset) {
+        fseeko(mFile, mMdatOffset, SEEK_SET);
+        int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
+        fwrite(&size, 1, 4, mFile);
+    } else {
+        fseeko(mFile, mMdatOffset + 8, SEEK_SET);
+        int64_t size = mOffset - mMdatOffset;
+        size = hton64(size);
+        fwrite(&size, 1, 8, mFile);
+    }
+    fseeko(mFile, mOffset, SEEK_SET);
 
     time_t now = time(NULL);
+    const off_t moovOffset = mOffset;
+    mWriteMoovBoxToMemory = true;
+    mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
+    mMoovBoxBufferOffset = 0;
+    CHECK(mMoovBoxBuffer != NULL);
+    int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
 
     beginBox("moov");
 
@@ -162,9 +383,9 @@
         writeInt32(0);             // version=0, flags=0
         writeInt32(now);           // creation time
         writeInt32(now);           // modification time
-        writeInt32(1000);          // timescale
-        writeInt32(max_duration / 1000);
-        writeInt32(0x10000);       // rate
+        writeInt32(mTimeScale);    // mvhd timescale
+        writeInt32(duration);
+        writeInt32(0x10000);       // rate: 1.0
         writeInt16(0x100);         // volume
         writeInt16(0);             // reserved
         writeInt32(0);             // reserved
@@ -190,19 +411,54 @@
       int32_t id = 1;
       for (List<Track *>::iterator it = mTracks.begin();
            it != mTracks.end(); ++it, ++id) {
-          (*it)->writeTrackHeader(id);
+          (*it)->writeTrackHeader(id, mUse32BitOffset);
       }
     endBox();  // moov
 
+    mWriteMoovBoxToMemory = false;
+    if (mStreamableFile) {
+        CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
+
+        // Moov box
+        fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+        mOffset = mFreeBoxOffset;
+        write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
+
+        // Free box
+        fseeko(mFile, mOffset, SEEK_SET);
+        writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
+        write("free", 4);
+
+        // Free temp memory
+        free(mMoovBoxBuffer);
+        mMoovBoxBuffer = NULL;
+        mMoovBoxBufferOffset = 0;
+    } else {
+        LOGI("The mp4 file will not be streamable.");
+    }
+
     CHECK(mBoxes.empty());
 
+    fflush(mFile);
     fclose(mFile);
     mFile = NULL;
+    mStarted = false;
 }
 
-off_t MPEG4Writer::addSample(MediaBuffer *buffer) {
-    Mutex::Autolock autoLock(mLock);
+status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
+    mInterleaveDurationUs = durationUs;
+    return OK;
+}
 
+void MPEG4Writer::lock() {
+    mLock.lock();
+}
+
+void MPEG4Writer::unlock() {
+    mLock.unlock();
+}
+
+off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
     off_t old_offset = mOffset;
 
     fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
@@ -213,31 +469,91 @@
     return old_offset;
 }
 
-off_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) {
-    Mutex::Autolock autoLock(mLock);
+static void StripStartcode(MediaBuffer *buffer) {
+    if (buffer->range_length() < 4) {
+        return;
+    }
 
+    const uint8_t *ptr =
+        (const uint8_t *)buffer->data() + buffer->range_offset();
+
+    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
+        buffer->set_range(
+                buffer->range_offset() + 4, buffer->range_length() - 4);
+    }
+}
+
+off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
     off_t old_offset = mOffset;
 
     size_t length = buffer->range_length();
+
+#if USE_NALLEN_FOUR
+    uint8_t x = length >> 24;
+    fwrite(&x, 1, 1, mFile);
+    x = (length >> 16) & 0xff;
+    fwrite(&x, 1, 1, mFile);
+    x = (length >> 8) & 0xff;
+    fwrite(&x, 1, 1, mFile);
+    x = length & 0xff;
+    fwrite(&x, 1, 1, mFile);
+#else
     CHECK(length < 65536);
 
     uint8_t x = length >> 8;
     fwrite(&x, 1, 1, mFile);
     x = length & 0xff;
     fwrite(&x, 1, 1, mFile);
+#endif
 
     fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
            1, length, mFile);
 
+#if USE_NALLEN_FOUR
+    mOffset += length + 4;
+#else
     mOffset += length + 2;
+#endif
 
     return old_offset;
 }
 
+size_t MPEG4Writer::write(
+        const void *ptr, size_t size, size_t nmemb, FILE *stream) {
+
+    const size_t bytes = size * nmemb;
+    if (mWriteMoovBoxToMemory) {
+        off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
+        if (moovBoxSize > mEstimatedMoovBoxSize) {
+            for (List<off_t>::iterator it = mBoxes.begin();
+                 it != mBoxes.end(); ++it) {
+                (*it) += mOffset;
+            }
+            fseeko(mFile, mOffset, SEEK_SET);
+            fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
+            fwrite(ptr, size, nmemb, stream);
+            mOffset += (bytes + mMoovBoxBufferOffset);
+            free(mMoovBoxBuffer);
+            mMoovBoxBuffer = NULL;
+            mMoovBoxBufferOffset = 0;
+            mWriteMoovBoxToMemory = false;
+            mStreamableFile = false;
+        } else {
+            memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
+            mMoovBoxBufferOffset += bytes;
+        }
+    } else {
+        fwrite(ptr, size, nmemb, stream);
+        mOffset += bytes;
+    }
+    return bytes;
+}
+
 void MPEG4Writer::beginBox(const char *fourcc) {
     CHECK_EQ(strlen(fourcc), 4);
 
-    mBoxes.push_back(mOffset);
+    mBoxes.push_back(mWriteMoovBoxToMemory?
+            mMoovBoxBufferOffset: mOffset);
 
     writeInt32(0);
     writeFourcc(fourcc);
@@ -249,51 +565,77 @@
     off_t offset = *--mBoxes.end();
     mBoxes.erase(--mBoxes.end());
 
-    fseek(mFile, offset, SEEK_SET);
-    writeInt32(mOffset - offset);
-    mOffset -= 4;
-    fseek(mFile, mOffset, SEEK_SET);
+    if (mWriteMoovBoxToMemory) {
+       int32_t x = htonl(mMoovBoxBufferOffset - offset);
+       memcpy(mMoovBoxBuffer + offset, &x, 4);
+    } else {
+        fseeko(mFile, offset, SEEK_SET);
+        writeInt32(mOffset - offset);
+        mOffset -= 4;
+        fseeko(mFile, mOffset, SEEK_SET);
+    }
 }
 
 void MPEG4Writer::writeInt8(int8_t x) {
-    fwrite(&x, 1, 1, mFile);
-    ++mOffset;
+    write(&x, 1, 1, mFile);
 }
 
 void MPEG4Writer::writeInt16(int16_t x) {
     x = htons(x);
-    fwrite(&x, 1, 2, mFile);
-    mOffset += 2;
+    write(&x, 1, 2, mFile);
 }
 
 void MPEG4Writer::writeInt32(int32_t x) {
     x = htonl(x);
-    fwrite(&x, 1, 4, mFile);
-    mOffset += 4;
+    write(&x, 1, 4, mFile);
 }
 
 void MPEG4Writer::writeInt64(int64_t x) {
     x = hton64(x);
-    fwrite(&x, 1, 8, mFile);
-    mOffset += 8;
+    write(&x, 1, 8, mFile);
 }
 
 void MPEG4Writer::writeCString(const char *s) {
     size_t n = strlen(s);
-
-    fwrite(s, 1, n + 1, mFile);
-    mOffset += n + 1;
+    write(s, 1, n + 1, mFile);
 }
 
 void MPEG4Writer::writeFourcc(const char *s) {
     CHECK_EQ(strlen(s), 4);
-    fwrite(s, 1, 4, mFile);
-    mOffset += 4;
+    write(s, 1, 4, mFile);
 }
 
 void MPEG4Writer::write(const void *data, size_t size) {
-    fwrite(data, 1, size, mFile);
-    mOffset += size;
+    write(data, 1, size, mFile);
+}
+
+bool MPEG4Writer::exceedsFileSizeLimit() {
+    // No limit
+    if (mMaxFileSizeLimitBytes == 0) {
+        return false;
+    }
+
+    int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
+    for (List<Track *>::iterator it = mTracks.begin();
+         it != mTracks.end(); ++it) {
+        nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
+    }
+    return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
+}
+
+bool MPEG4Writer::exceedsFileDurationLimit() {
+    // No limit
+    if (mMaxFileDurationLimitUs == 0) {
+        return false;
+    }
+
+    for (List<Track *>::iterator it = mTracks.begin();
+         it != mTracks.end(); ++it) {
+        if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
+            return true;
+        }
+    }
+    return false;
 }
 
 bool MPEG4Writer::reachedEOS() {
@@ -309,6 +651,26 @@
     return allDone;
 }
 
+void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
+    LOGI("setStartTimestampUs: %lld", timeUs);
+    CHECK(timeUs >= 0);
+    Mutex::Autolock autoLock(mLock);
+    if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
+        mStartTimestampUs = timeUs;
+        LOGI("Earliest track starting time: %lld", mStartTimestampUs);
+    }
+}
+
+int64_t MPEG4Writer::getStartTimestampUs() {
+    Mutex::Autolock autoLock(mLock);
+    return mStartTimestampUs;
+}
+
+size_t MPEG4Writer::numTracks() {
+    Mutex::Autolock autolock(mLock);
+    return mTracks.size();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Writer::Track::Track(
@@ -317,10 +679,52 @@
       mMeta(source->getFormat()),
       mSource(source),
       mDone(false),
+      mPaused(false),
+      mResumed(false),
       mMaxTimeStampUs(0),
+      mEstimatedTrackSizeBytes(0),
+      mSamplesHaveSameSize(true),
       mCodecSpecificData(NULL),
       mCodecSpecificDataSize(0),
+      mGotAllCodecSpecificData(false),
       mReachedEOS(false) {
+    getCodecSpecificDataFromInputFormatIfPossible();
+
+    if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
+        mTimeScale = 1000;
+    }
+    CHECK(mTimeScale > 0);
+}
+
+void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
+    const char *mime;
+    CHECK(mMeta->findCString(kKeyMIMEType, &mime));
+
+    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+        uint32_t type;
+        const void *data;
+        size_t size;
+        if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
+            mCodecSpecificData = malloc(size);
+            mCodecSpecificDataSize = size;
+            memcpy(mCodecSpecificData, data, size);
+            mGotAllCodecSpecificData = true;
+        }
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
+            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+        uint32_t type;
+        const void *data;
+        size_t size;
+        if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
+            ESDS esds(data, size);
+            if (esds.getCodecSpecificInfo(&data, &size) == OK) {
+                mCodecSpecificData = malloc(size);
+                mCodecSpecificDataSize = size;
+                memcpy(mCodecSpecificData, data, size);
+                mGotAllCodecSpecificData = true;
+            }
+        }
+    }
 }
 
 MPEG4Writer::Track::~Track() {
@@ -332,9 +736,38 @@
     }
 }
 
-status_t MPEG4Writer::Track::start() {
-    status_t err = mSource->start();
+void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
+    LOGV("initTrackingProgressStatus");
+    mPreviousTrackTimeUs = -1;
+    mTrackingProgressStatus = false;
+    mTrackEveryTimeDurationUs = 0;
+    {
+        int64_t timeUs;
+        if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
+            LOGV("Receive request to track progress status for every %lld us", timeUs);
+            mTrackEveryTimeDurationUs = timeUs;
+            mTrackingProgressStatus = true;
+        }
+    }
+}
 
+status_t MPEG4Writer::Track::start(MetaData *params) {
+    if (!mDone && mPaused) {
+        mPaused = false;
+        mResumed = true;
+        return OK;
+    }
+
+    int64_t startTimeUs;
+    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
+        startTimeUs = 0;
+    }
+
+    initTrackingProgressStatus(params);
+
+    sp<MetaData> meta = new MetaData;
+    meta->setInt64(kKeyTime, startTimeUs);
+    status_t err = mSource->start(meta.get());
     if (err != OK) {
         mDone = mReachedEOS = true;
         return err;
@@ -347,6 +780,7 @@
     mDone = false;
     mMaxTimeStampUs = 0;
     mReachedEOS = false;
+    mEstimatedTrackSizeBytes = 0;
 
     pthread_create(&mThread, &attr, ThreadWrapper, this);
     pthread_attr_destroy(&attr);
@@ -354,6 +788,10 @@
     return OK;
 }
 
+void MPEG4Writer::Track::pause() {
+    mPaused = true;
+}
+
 void MPEG4Writer::Track::stop() {
     if (mDone) {
         return;
@@ -380,73 +818,186 @@
     return NULL;
 }
 
+#include <ctype.h>
+static void hexdump(const void *_data, size_t size) {
+    const uint8_t *data = (const uint8_t *)_data;
+    size_t offset = 0;
+    while (offset < size) {
+        printf("0x%04x  ", offset);
+
+        size_t n = size - offset;
+        if (n > 16) {
+            n = 16;
+        }
+
+        for (size_t i = 0; i < 16; ++i) {
+            if (i == 8) {
+                printf(" ");
+            }
+
+            if (offset + i < size) {
+                printf("%02x ", data[offset + i]);
+            } else {
+                printf("   ");
+            }
+        }
+
+        printf(" ");
+
+        for (size_t i = 0; i < n; ++i) {
+            if (isprint(data[offset + i])) {
+                printf("%c", data[offset + i]);
+            } else {
+                printf(".");
+            }
+        }
+
+        printf("\n");
+
+        offset += 16;
+    }
+}
+
+
+status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
+        const uint8_t *data, size_t size) {
+    // hexdump(data, size);
+
+    if (mCodecSpecificData != NULL) {
+        LOGE("Already have codec specific data");
+        return ERROR_MALFORMED;
+    }
+
+    if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
+        LOGE("Must start with a start code");
+        return ERROR_MALFORMED;
+    }
+
+    size_t picParamOffset = 4;
+    while (picParamOffset + 3 < size
+            && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
+        ++picParamOffset;
+    }
+
+    if (picParamOffset + 3 >= size) {
+        LOGE("Could not find start-code for pictureParameterSet");
+        return ERROR_MALFORMED;
+    }
+
+    size_t seqParamSetLength = picParamOffset - 4;
+    size_t picParamSetLength = size - picParamOffset - 4;
+
+    mCodecSpecificDataSize =
+        6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;
+
+    mCodecSpecificData = malloc(mCodecSpecificDataSize);
+    uint8_t *header = (uint8_t *)mCodecSpecificData;
+    header[0] = 1;
+    header[1] = 0x42;  // profile
+    header[2] = 0x80;
+    header[3] = 0x1e;  // level
+
+#if USE_NALLEN_FOUR
+    header[4] = 0xfc | 3;  // length size == 4 bytes
+#else
+    header[4] = 0xfc | 1;  // length size == 2 bytes
+#endif
+
+    header[5] = 0xe0 | 1;
+    header[6] = seqParamSetLength >> 8;
+    header[7] = seqParamSetLength & 0xff;
+    memcpy(&header[8], &data[4], seqParamSetLength);
+    header += 8 + seqParamSetLength;
+    header[0] = 1;
+    header[1] = picParamSetLength >> 8;
+    header[2] = picParamSetLength & 0xff;
+    memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);
+
+    return OK;
+}
+
+static bool collectStatisticalData() {
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("media.stagefright.record-stats", value, NULL)
+        && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+        return true;
+    }
+    return false;
+}
+
 void MPEG4Writer::Track::threadEntry() {
     sp<MetaData> meta = mSource->getFormat();
     const char *mime;
     meta->findCString(kKeyMIMEType, &mime);
-    bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4);
+    bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
+                    !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
     bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
+    bool is_audio = !strncasecmp(mime, "audio/", 6);
     int32_t count = 0;
+    const int64_t interleaveDurationUs = mOwner->interleaveDuration();
+    int64_t chunkTimestampUs = 0;
+    int32_t nChunks = 0;
+    int32_t nZeroLengthFrames = 0;
+    int64_t lastTimestampUs = 0;  // Previous sample time stamp in ms
+    int64_t lastDurationUs = 0;   // Between the previous two samples in ms
+    int32_t sampleCount = 1;      // Sample count in the current stts table entry
+    uint32_t previousSampleSize = 0;  // Size of the previous sample
+    int64_t previousPausedDurationUs = 0;
+    sp<MetaData> meta_data;
+    bool collectStats = collectStatisticalData();
 
+    mNumSamples = 0;
+    status_t err = OK;
     MediaBuffer *buffer;
-    while (!mDone && mSource->read(&buffer) == OK) {
+    while (!mDone && (err = mSource->read(&buffer)) == OK) {
         if (buffer->range_length() == 0) {
             buffer->release();
             buffer = NULL;
+            ++nZeroLengthFrames;
+            continue;
+        }
 
+        // If the codec specific data has not been received yet, delay pause.
+        // After the codec specific data is received, discard what we received
+        // when the track is to be paused.
+        if (mPaused && !mResumed) {
+            buffer->release();
+            buffer = NULL;
             continue;
         }
 
         ++count;
 
-        if (is_avc && count < 3) {
-            size_t size = buffer->range_length();
+        int32_t isCodecConfig;
+        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
+                && isCodecConfig) {
+            CHECK(!mGotAllCodecSpecificData);
 
-            switch (count) {
-                case 1:
-                {
-                    CHECK_EQ(mCodecSpecificData, NULL);
-                    mCodecSpecificData = malloc(size + 8);
-                    uint8_t *header = (uint8_t *)mCodecSpecificData;
-                    header[0] = 1;
-                    header[1] = 0x42;  // profile
-                    header[2] = 0x80;
-                    header[3] = 0x1e;  // level
-                    header[4] = 0xfc | 3;
-                    header[5] = 0xe0 | 1;
-                    header[6] = size >> 8;
-                    header[7] = size & 0xff;
-                    memcpy(&header[8],
-                            (const uint8_t *)buffer->data() + buffer->range_offset(),
-                            size);
-
-                    mCodecSpecificDataSize = size + 8;
-                    break;
-                }
-
-                case 2:
-                {
-                    size_t offset = mCodecSpecificDataSize;
-                    mCodecSpecificDataSize += size + 3;
-                    mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize);
-                    uint8_t *header = (uint8_t *)mCodecSpecificData;
-                    header[offset] = 1;
-                    header[offset + 1] = size >> 8;
-                    header[offset + 2] = size & 0xff;
-                    memcpy(&header[offset + 3],
-                            (const uint8_t *)buffer->data() + buffer->range_offset(),
-                            size);
-                    break;
-                }
+            if (is_avc) {
+                status_t err = makeAVCCodecSpecificData(
+                        (const uint8_t *)buffer->data()
+                            + buffer->range_offset(),
+                        buffer->range_length());
+                CHECK_EQ(OK, err);
+            } else if (is_mpeg4) {
+                mCodecSpecificDataSize = buffer->range_length();
+                mCodecSpecificData = malloc(mCodecSpecificDataSize);
+                memcpy(mCodecSpecificData,
+                        (const uint8_t *)buffer->data()
+                            + buffer->range_offset(),
+                       buffer->range_length());
             }
 
             buffer->release();
             buffer = NULL;
 
+            mGotAllCodecSpecificData = true;
             continue;
-        }
+        } else if (!mGotAllCodecSpecificData &&
+                count == 1 && is_mpeg4 && mCodecSpecificData == NULL) {
+            // The TI mpeg4 encoder does not properly set the
+            // codec-specific-data flag.
 
-        if (mCodecSpecificData == NULL && is_mpeg4) {
             const uint8_t *data =
                 (const uint8_t *)buffer->data() + buffer->range_offset();
 
@@ -474,56 +1025,417 @@
             memcpy(mCodecSpecificData, data, offset);
 
             buffer->set_range(buffer->range_offset() + offset, size - offset);
+
+            if (size == offset) {
+                buffer->release();
+                buffer = NULL;
+
+                continue;
+            }
+
+            mGotAllCodecSpecificData = true;
+        } else if (!mGotAllCodecSpecificData && is_avc && count < 3) {
+            // The TI video encoder does not flag codec specific data
+            // as such and also splits up SPS and PPS across two buffers.
+
+            const uint8_t *data =
+                (const uint8_t *)buffer->data() + buffer->range_offset();
+
+            size_t size = buffer->range_length();
+
+            CHECK(count == 2 || mCodecSpecificData == NULL);
+
+            size_t offset = mCodecSpecificDataSize;
+            mCodecSpecificDataSize += size + 4;
+            mCodecSpecificData =
+                realloc(mCodecSpecificData, mCodecSpecificDataSize);
+
+            memcpy((uint8_t *)mCodecSpecificData + offset,
+                   "\x00\x00\x00\x01", 4);
+
+            memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
+
+            buffer->release();
+            buffer = NULL;
+
+            if (count == 2) {
+                void *tmp = mCodecSpecificData;
+                size = mCodecSpecificDataSize;
+                mCodecSpecificData = NULL;
+                mCodecSpecificDataSize = 0;
+
+                status_t err = makeAVCCodecSpecificData(
+                        (const uint8_t *)tmp, size);
+                free(tmp);
+                tmp = NULL;
+                CHECK_EQ(OK, err);
+
+                mGotAllCodecSpecificData = true;
+            }
+
+            continue;
         }
 
-        off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer)
-                              : mOwner->addSample(buffer);
+        if (!mGotAllCodecSpecificData) {
+            mGotAllCodecSpecificData = true;
+        }
 
-        SampleInfo info;
-        info.size = is_avc ? buffer->range_length() + 2 : buffer->range_length();
-        info.offset = offset;
+        // Make a deep copy of the MediaBuffer and Metadata and release
+        // the original as soon as we can
+        MediaBuffer *copy = new MediaBuffer(buffer->range_length());
+        memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
+                buffer->range_length());
+        copy->set_range(0, buffer->range_length());
+        meta_data = new MetaData(*buffer->meta_data().get());
+        buffer->release();
+        buffer = NULL;
+
+        if (is_avc) StripStartcode(copy);
+
+        size_t sampleSize;
+        sampleSize = is_avc
+#if USE_NALLEN_FOUR
+                ? copy->range_length() + 4
+#else
+                ? copy->range_length() + 2
+#endif
+                : copy->range_length();
+
+        // Max file size or duration handling
+        mEstimatedTrackSizeBytes += sampleSize;
+        if (mOwner->exceedsFileSizeLimit()) {
+            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+            break;
+        }
+        if (mOwner->exceedsFileDurationLimit()) {
+            mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
+            break;
+        }
+
+
+        int32_t isSync = false;
+        meta_data->findInt32(kKeyIsSyncFrame, &isSync);
 
         int64_t timestampUs;
-        CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+        CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
 
+////////////////////////////////////////////////////////////////////////////////
+        if (mSampleSizes.empty()) {
+            mStartTimestampUs = timestampUs;
+            mOwner->setStartTimestampUs(mStartTimestampUs);
+        }
+
+        if (mResumed) {
+            previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - lastDurationUs);
+            mResumed = false;
+        }
+
+        timestampUs -= previousPausedDurationUs;
+        LOGV("time stamp: %lld and previous paused duration %lld",
+                timestampUs, previousPausedDurationUs);
         if (timestampUs > mMaxTimeStampUs) {
             mMaxTimeStampUs = timestampUs;
         }
 
-        // Our timestamp is in ms.
-        info.timestamp = (timestampUs + 500) / 1000;
+        mSampleSizes.push_back(sampleSize);
+        ++mNumSamples;
+        if (mNumSamples > 2) {
+            if (lastDurationUs != timestampUs - lastTimestampUs) {
+                SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
+                mSttsTableEntries.push_back(sttsEntry);
+                sampleCount = 1;
+            } else {
+                ++sampleCount;
+            }
+        }
+        if (mSamplesHaveSameSize) {
+            if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
+                mSamplesHaveSameSize = false;
+            }
+            previousSampleSize = sampleSize;
+        }
+        lastDurationUs = timestampUs - lastTimestampUs;
+        lastTimestampUs = timestampUs;
 
-        mSampleInfos.push_back(info);
+        if (isSync != 0) {
+            mStssTableEntries.push_back(mNumSamples);
+        }
 
-        buffer->release();
-        buffer = NULL;
+        if (mTrackingProgressStatus) {
+            if (mPreviousTrackTimeUs <= 0) {
+                mPreviousTrackTimeUs = mStartTimestampUs;
+            }
+            trackProgressStatus(timestampUs);
+        }
+        if (mOwner->numTracks() == 1) {
+            off_t offset = is_avc? mOwner->addLengthPrefixedSample_l(copy)
+                                 : mOwner->addSample_l(copy);
+            if (mChunkOffsets.empty()) {
+                mChunkOffsets.push_back(offset);
+            }
+            copy->release();
+            copy = NULL;
+            continue;
+        }
+
+        mChunkSamples.push_back(copy);
+        if (interleaveDurationUs == 0) {
+            StscTableEntry stscEntry(++nChunks, 1, 1);
+            mStscTableEntries.push_back(stscEntry);
+            writeOneChunk(is_avc);
+        } else {
+            if (chunkTimestampUs == 0) {
+                chunkTimestampUs = timestampUs;
+            } else {
+                if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
+                    ++nChunks;
+                    if (collectStats) {
+                        mChunkDurations.push_back(timestampUs - chunkTimestampUs);
+                    }
+                    if (nChunks == 1 ||  // First chunk
+                        (--(mStscTableEntries.end()))->samplesPerChunk !=
+                         mChunkSamples.size()) {
+                        StscTableEntry stscEntry(nChunks,
+                                mChunkSamples.size(), 1);
+                        mStscTableEntries.push_back(stscEntry);
+                    }
+                    writeOneChunk(is_avc);
+                    chunkTimestampUs = timestampUs;
+                }
+            }
+        }
+
     }
 
+    if (mSampleSizes.empty()) {
+        err = UNKNOWN_ERROR;
+    }
+    mOwner->trackProgressStatus(this, -1, err);
+
+    // Last chunk
+    if (mOwner->numTracks() == 1) {
+        StscTableEntry stscEntry(1, mNumSamples, 1);
+        mStscTableEntries.push_back(stscEntry);
+    } else if (!mChunkSamples.empty()) {
+        ++nChunks;
+        StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
+        mStscTableEntries.push_back(stscEntry);
+        writeOneChunk(is_avc);
+    }
+
+    // We don't really know how long the last frame lasts, since
+    // there is no frame time after it, just repeat the previous
+    // frame's duration.
+    if (mNumSamples == 1) {
+        lastDurationUs = 0;  // A single sample's duration
+    } else {
+        ++sampleCount;  // Count for the last sample
+    }
+    SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
+    mSttsTableEntries.push_back(sttsEntry);
     mReachedEOS = true;
+    LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s",
+            count, nZeroLengthFrames, mNumSamples, is_audio? "audio": "video");
+
+    logStatisticalData(is_audio);
+}
+
+void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
+    LOGV("trackProgressStatus: %lld us", timeUs);
+    if (mTrackEveryTimeDurationUs > 0 &&
+        timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
+        LOGV("Fire time tracking progress status at %lld us", timeUs);
+        mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
+        mPreviousTrackTimeUs = timeUs;
+    }
+}
+
+void MPEG4Writer::trackProgressStatus(
+        const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
+    Mutex::Autolock lock(mLock);
+    int32_t nTracks = mTracks.size();
+    CHECK(nTracks >= 1);
+    CHECK(nTracks < 64);  // Arbitrary number
+
+    int32_t trackNum = 0;
+#if 0
+    // In the worst case, we can put the trackNum
+    // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS
+    // to report the progress.
+    for (List<Track *>::iterator it = mTracks.begin();
+         it != mTracks.end(); ++it, ++trackNum) {
+        if (track == (*it)) {
+            break;
+        }
+    }
+#endif
+    CHECK(trackNum < nTracks);
+    trackNum <<= 16;
+
+    // Error notification
+    // Do not consider ERROR_END_OF_STREAM an error
+    if (err != OK && err != ERROR_END_OF_STREAM) {
+        notify(MEDIA_RECORDER_EVENT_ERROR,
+               trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
+               err);
+        return;
+    }
+
+    if (timeUs == -1) {
+        // Send completion notification
+        notify(MEDIA_RECORDER_EVENT_INFO,
+               trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
+               err);
+        return;
+    } else {
+        // Send progress status
+        notify(MEDIA_RECORDER_EVENT_INFO,
+               trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
+               timeUs / 1000);
+    }
+}
+
+void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
+        int32_t *min, int32_t *avg, int32_t *max) {
+    CHECK(!mSampleSizes.empty());
+    int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000 / mNumSamples;
+    int32_t minSampleDurationMs = 0x7FFFFFFF;
+    int32_t maxSampleDurationMs = 0;
+    for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
+        it != mSttsTableEntries.end(); ++it) {
+        int32_t sampleDurationMs =
+            (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
+        if (sampleDurationMs > maxSampleDurationMs) {
+            maxSampleDurationMs = sampleDurationMs;
+        } else if (sampleDurationMs < minSampleDurationMs) {
+            minSampleDurationMs = sampleDurationMs;
+        }
+        LOGI("sample duration: %d ms", sampleDurationMs);
+    }
+    CHECK(minSampleDurationMs != 0);
+    CHECK(avgSampleDurationMs != 0);
+    CHECK(maxSampleDurationMs != 0);
+    *min = minSampleDurationMs;
+    *avg = avgSampleDurationMs;
+    *max = maxSampleDurationMs;
+}
+
+// Don't count the last duration
+void MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
+    int64_t duration = mOwner->interleaveDuration();
+    int64_t minChunkDuration = duration;
+    int64_t maxChunkDuration = duration;
+    if (mChunkDurations.size() > 1) {
+        for (List<int64_t>::iterator it = mChunkDurations.begin();
+            it != --mChunkDurations.end(); ++it) {
+            if (minChunkDuration > (*it)) {
+                minChunkDuration = (*it);
+            } else if (maxChunkDuration < (*it)) {
+                maxChunkDuration = (*it);
+            }
+        }
+    }
+    *min = minChunkDuration;
+    *max = maxChunkDuration;
+}
+
+void MPEG4Writer::Track::logStatisticalData(bool isAudio) {
+    if (mMaxTimeStampUs <= 0 || mSampleSizes.empty()) {
+        LOGI("nothing is recorded");
+        return;
+    }
+
+    bool collectStats = collectStatisticalData();
+
+    if (collectStats) {
+        LOGI("%s track - duration %lld us, total %d frames",
+                isAudio? "audio": "video", mMaxTimeStampUs,
+                mNumSamples);
+        int32_t min, avg, max;
+        findMinAvgMaxSampleDurationMs(&min, &avg, &max);
+        LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
+        if (!isAudio) {
+            float avgFps = 1000.0 / avg;
+            float minFps = 1000.0 / max;
+            float maxFps = 1000.0 / min;
+            LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
+                minFps, avgFps, maxFps);
+        }
+
+        int64_t totalBytes = 0;
+        for (List<size_t>::iterator it = mSampleSizes.begin();
+            it != mSampleSizes.end(); ++it) {
+            totalBytes += (*it);
+        }
+        float bitRate = (totalBytes * 8000000.0) / mMaxTimeStampUs;
+        LOGI("avg bit rate (bps): %.2f", bitRate);
+
+        int64_t duration = mOwner->interleaveDuration();
+        if (duration != 0) {  // If interleaving is enabled
+            int64_t minChunk, maxChunk;
+            findMinMaxChunkDurations(&minChunk, &maxChunk);
+            LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
+                minChunk, duration, maxChunk);
+        }
+    }
+}
+
+void MPEG4Writer::Track::writeOneChunk(bool isAvc) {
+    mOwner->lock();
+    for (List<MediaBuffer *>::iterator it = mChunkSamples.begin();
+         it != mChunkSamples.end(); ++it) {
+        off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it)
+                            : mOwner->addSample_l(*it);
+        if (it == mChunkSamples.begin()) {
+            mChunkOffsets.push_back(offset);
+        }
+    }
+    mOwner->unlock();
+    while (!mChunkSamples.empty()) {
+        List<MediaBuffer *>::iterator it = mChunkSamples.begin();
+        (*it)->release();
+        (*it) = NULL;
+        mChunkSamples.erase(it);
+    }
+    mChunkSamples.clear();
 }
 
 int64_t MPEG4Writer::Track::getDurationUs() const {
     return mMaxTimeStampUs;
 }
 
-void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
+int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
+    return mEstimatedTrackSizeBytes;
+}
+
+void MPEG4Writer::Track::writeTrackHeader(
+        int32_t trackID, bool use32BitOffset) {
     const char *mime;
     bool success = mMeta->findCString(kKeyMIMEType, &mime);
     CHECK(success);
 
     bool is_audio = !strncasecmp(mime, "audio/", 6);
+    LOGV("%s track time scale: %d",
+        is_audio? "Audio": "Video", mTimeScale);
+
 
     time_t now = time(NULL);
+    int32_t mvhdTimeScale = mOwner->getTimeScale();
+    int64_t trakDurationUs = getDurationUs();
 
     mOwner->beginBox("trak");
 
       mOwner->beginBox("tkhd");
-        mOwner->writeInt32(0);             // version=0, flags=0
+        // Flags = 7 to indicate that the track is enabled, and
+        // part of the presentation
+        mOwner->writeInt32(0x07);          // version=0, flags=7
         mOwner->writeInt32(now);           // creation time
         mOwner->writeInt32(now);           // modification time
         mOwner->writeInt32(trackID);
         mOwner->writeInt32(0);             // reserved
-        mOwner->writeInt32(getDurationUs() / 1000);
+        int32_t tkhdDuration =
+            (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+        mOwner->writeInt32(tkhdDuration);  // in mvhd timescale
         mOwner->writeInt32(0);             // reserved
         mOwner->writeInt32(0);             // reserved
         mOwner->writeInt16(0);             // layer
@@ -550,45 +1462,64 @@
             success = success && mMeta->findInt32(kKeyHeight, &height);
             CHECK(success);
 
-            mOwner->writeInt32(width);
-            mOwner->writeInt32(height);
+            mOwner->writeInt32(width << 16);   // 32-bit fixed-point value
+            mOwner->writeInt32(height << 16);  // 32-bit fixed-point value
         }
       mOwner->endBox();  // tkhd
 
+      int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
+      if (mStartTimestampUs != moovStartTimeUs) {
+        mOwner->beginBox("edts");
+          mOwner->beginBox("elst");
+            mOwner->writeInt32(0);           // version=0, flags=0: 32-bit time
+            mOwner->writeInt32(2);           // never ends with an empty list
+
+            // First elst entry: specify the starting time offset
+            int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
+            int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
+            mOwner->writeInt32(seg);         // in mvhd timecale
+            mOwner->writeInt32(-1);          // starting time offset
+            mOwner->writeInt32(1 << 16);     // rate = 1.0
+
+            // Second elst entry: specify the track duration
+            seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+            mOwner->writeInt32(seg);         // in mvhd timescale
+            mOwner->writeInt32(0);
+            mOwner->writeInt32(1 << 16);
+          mOwner->endBox();
+        mOwner->endBox();
+      }
+
       mOwner->beginBox("mdia");
 
         mOwner->beginBox("mdhd");
           mOwner->writeInt32(0);             // version=0, flags=0
           mOwner->writeInt32(now);           // creation time
           mOwner->writeInt32(now);           // modification time
-          mOwner->writeInt32(1000);          // timescale
-          mOwner->writeInt32(getDurationUs() / 1000);
-          mOwner->writeInt16(0);             // language code XXX
+          mOwner->writeInt32(mTimeScale);    // media timescale
+          int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
+          mOwner->writeInt32(mdhdDuration);  // use media timescale
+          // Language follows the three letter standard ISO-639-2/T
+          // 'e', 'n', 'g' for "English", for instance.
+          // Each character is packed as the difference between its ASCII value and 0x60.
+          // For "English", these are 00101, 01110, 00111.
+          // XXX: Where is the padding bit located: 0x15C7?
+          mOwner->writeInt16(0);             // language code
           mOwner->writeInt16(0);             // predefined
         mOwner->endBox();
 
         mOwner->beginBox("hdlr");
           mOwner->writeInt32(0);             // version=0, flags=0
-          mOwner->writeInt32(0);             // predefined
-          mOwner->writeFourcc(is_audio ? "soun" : "vide");
+          mOwner->writeInt32(0);             // component type: should be mhlr
+          mOwner->writeFourcc(is_audio ? "soun" : "vide");  // component subtype
           mOwner->writeInt32(0);             // reserved
           mOwner->writeInt32(0);             // reserved
           mOwner->writeInt32(0);             // reserved
-          mOwner->writeCString("");          // name
+          // Removing "r" for the name string just makes the string 4 byte aligned
+          mOwner->writeCString(is_audio ? "SoundHandle": "VideoHandle");  // name
         mOwner->endBox();
 
         mOwner->beginBox("minf");
-
-          mOwner->beginBox("dinf");
-            mOwner->beginBox("dref");
-              mOwner->writeInt32(0);  // version=0, flags=0
-              mOwner->writeInt32(1);
-              mOwner->beginBox("url ");
-                mOwner->writeInt32(1);  // version=0, flags=1
-              mOwner->endBox();  // url
-            mOwner->endBox();  // dref
-          mOwner->endBox();  // dinf
-
           if (is_audio) {
               mOwner->beginBox("smhd");
               mOwner->writeInt32(0);           // version=0, flags=0
@@ -597,14 +1528,25 @@
               mOwner->endBox();
           } else {
               mOwner->beginBox("vmhd");
-              mOwner->writeInt32(0x00000001);  // version=0, flags=1
+              mOwner->writeInt32(0x01);        // version=0, flags=1
               mOwner->writeInt16(0);           // graphics mode
               mOwner->writeInt16(0);           // opcolor
               mOwner->writeInt16(0);
               mOwner->writeInt16(0);
               mOwner->endBox();
           }
-        mOwner->endBox();  // minf
+
+          mOwner->beginBox("dinf");
+            mOwner->beginBox("dref");
+              mOwner->writeInt32(0);  // version=0, flags=0
+              mOwner->writeInt32(1);  // entry count (either url or urn)
+              // The table index here refers to the sample description index
+              // in the sample table entries.
+              mOwner->beginBox("url ");
+                mOwner->writeInt32(1);  // version=0, flags=1 (self-contained)
+              mOwner->endBox();  // url
+            mOwner->endBox();  // dref
+          mOwner->endBox();  // dinf
 
         mOwner->beginBox("stbl");
 
@@ -617,6 +1559,8 @@
                     fourcc = "samr";
                 } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
                     fourcc = "sawb";
+                } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
+                    fourcc = "mp4a";
                 } else {
                     LOGE("Unknown mime type '%s'.", mime);
                     CHECK(!"should not be here, unknown mime type.");
@@ -625,10 +1569,12 @@
                 mOwner->beginBox(fourcc);          // audio format
                   mOwner->writeInt32(0);           // reserved
                   mOwner->writeInt16(0);           // reserved
-                  mOwner->writeInt16(0);           // data ref index
+                  mOwner->writeInt16(0x1);         // data ref index
                   mOwner->writeInt32(0);           // reserved
                   mOwner->writeInt32(0);           // reserved
-                  mOwner->writeInt16(2);           // channel count
+                  int32_t nChannels;
+                  CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
+                  mOwner->writeInt16(nChannels);   // channel count
                   mOwner->writeInt16(16);          // sample size
                   mOwner->writeInt16(0);           // predefined
                   mOwner->writeInt16(0);           // reserved
@@ -638,6 +1584,38 @@
                   CHECK(success);
 
                   mOwner->writeInt32(samplerate << 16);
+                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
+                    mOwner->beginBox("esds");
+
+                        mOwner->writeInt32(0);     // version=0, flags=0
+                        mOwner->writeInt8(0x03);   // ES_DescrTag
+                        mOwner->writeInt8(23 + mCodecSpecificDataSize);
+                        mOwner->writeInt16(0x0000);// ES_ID
+                        mOwner->writeInt8(0x00);
+
+                        mOwner->writeInt8(0x04);   // DecoderConfigDescrTag
+                        mOwner->writeInt8(15 + mCodecSpecificDataSize);
+                        mOwner->writeInt8(0x40);   // objectTypeIndication ISO/IEC 14492-2
+                        mOwner->writeInt8(0x15);   // streamType AudioStream
+
+                        mOwner->writeInt16(0x03);  // XXX
+                        mOwner->writeInt8(0x00);   // buffer size 24-bit
+                        mOwner->writeInt32(96000); // max bit rate
+                        mOwner->writeInt32(96000); // avg bit rate
+
+                        mOwner->writeInt8(0x05);   // DecoderSpecificInfoTag
+                        mOwner->writeInt8(mCodecSpecificDataSize);
+                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
+
+                        static const uint8_t kData2[] = {
+                            0x06,  // SLConfigDescriptorTag
+                            0x01,
+                            0x02
+                        };
+                        mOwner->write(kData2, sizeof(kData2));
+
+                    mOwner->endBox();  // esds
+                  }
                 mOwner->endBox();
             } else {
                 if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
@@ -653,7 +1631,7 @@
 
                   mOwner->writeInt32(0);           // reserved
                   mOwner->writeInt16(0);           // reserved
-                  mOwner->writeInt16(0);           // data ref index
+                  mOwner->writeInt16(1);           // data ref index
                   mOwner->writeInt16(0);           // predefined
                   mOwner->writeInt16(0);           // reserved
                   mOwner->writeInt32(0);           // predefined
@@ -698,7 +1676,7 @@
                             0x00, 0x03, 0xe8, 0x00
                         };
                         mOwner->write(kData, sizeof(kData));
-                        
+
                         mOwner->writeInt8(0x05);  // DecoderSpecificInfoTag
 
                         mOwner->writeInt8(mCodecSpecificDataSize);
@@ -727,59 +1705,79 @@
                       mOwner->endBox();  // avcC
                   }
 
+                  mOwner->beginBox("pasp");
+                    // This is useful if the pixel is not square
+                    mOwner->writeInt32(1 << 16);  // hspacing
+                    mOwner->writeInt32(1 << 16);  // vspacing
+                  mOwner->endBox();  // pasp
                 mOwner->endBox();  // mp4v, s263 or avc1
             }
           mOwner->endBox();  // stsd
 
           mOwner->beginBox("stts");
             mOwner->writeInt32(0);  // version=0, flags=0
-            mOwner->writeInt32(mSampleInfos.size() - 1);
-
-            List<SampleInfo>::iterator it = mSampleInfos.begin();
-            int64_t last = (*it).timestamp;
-            ++it;
-            while (it != mSampleInfos.end()) {
-                mOwner->writeInt32(1);
-                mOwner->writeInt32((*it).timestamp - last);
-
-                last = (*it).timestamp;
-
-                ++it;
+            mOwner->writeInt32(mSttsTableEntries.size());
+            for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
+                 it != mSttsTableEntries.end(); ++it) {
+                mOwner->writeInt32(it->sampleCount);
+                int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
+                mOwner->writeInt32(dur);
             }
           mOwner->endBox();  // stts
 
+          if (!is_audio) {
+            mOwner->beginBox("stss");
+              mOwner->writeInt32(0);  // version=0, flags=0
+              mOwner->writeInt32(mStssTableEntries.size());  // number of sync frames
+              for (List<int32_t>::iterator it = mStssTableEntries.begin();
+                   it != mStssTableEntries.end(); ++it) {
+                  mOwner->writeInt32(*it);
+              }
+            mOwner->endBox();  // stss
+          }
+
           mOwner->beginBox("stsz");
             mOwner->writeInt32(0);  // version=0, flags=0
-            mOwner->writeInt32(0);  // default sample size
-            mOwner->writeInt32(mSampleInfos.size());
-            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
-                 it != mSampleInfos.end(); ++it) {
-                mOwner->writeInt32((*it).size);
+            if (mSamplesHaveSameSize) {
+                List<size_t>::iterator it = mSampleSizes.begin();
+                mOwner->writeInt32(*it);  // default sample size
+            } else {
+                mOwner->writeInt32(0);
+            }
+            mOwner->writeInt32(mNumSamples);
+            if (!mSamplesHaveSameSize) {
+                for (List<size_t>::iterator it = mSampleSizes.begin();
+                     it != mSampleSizes.end(); ++it) {
+                    mOwner->writeInt32(*it);
+                }
             }
           mOwner->endBox();  // stsz
 
           mOwner->beginBox("stsc");
             mOwner->writeInt32(0);  // version=0, flags=0
-            mOwner->writeInt32(mSampleInfos.size());
-            int32_t n = 1;
-            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
-                 it != mSampleInfos.end(); ++it, ++n) {
-                mOwner->writeInt32(n);
-                mOwner->writeInt32(1);
-                mOwner->writeInt32(1);
+            mOwner->writeInt32(mStscTableEntries.size());
+            for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
+                 it != mStscTableEntries.end(); ++it) {
+                mOwner->writeInt32(it->firstChunk);
+                mOwner->writeInt32(it->samplesPerChunk);
+                mOwner->writeInt32(it->sampleDescriptionId);
             }
           mOwner->endBox();  // stsc
-
-          mOwner->beginBox("co64");
+          mOwner->beginBox(use32BitOffset? "stco": "co64");
             mOwner->writeInt32(0);  // version=0, flags=0
-            mOwner->writeInt32(mSampleInfos.size());
-            for (List<SampleInfo>::iterator it = mSampleInfos.begin();
-                 it != mSampleInfos.end(); ++it, ++n) {
-                mOwner->writeInt64((*it).offset);
+            mOwner->writeInt32(mChunkOffsets.size());
+            for (List<off_t>::iterator it = mChunkOffsets.begin();
+                 it != mChunkOffsets.end(); ++it) {
+                if (use32BitOffset) {
+                    mOwner->writeInt32(static_cast<int32_t>(*it));
+                } else {
+                    mOwner->writeInt64((*it));
+                }
             }
-          mOwner->endBox();  // co64
+          mOwner->endBox();  // stco or co64
 
         mOwner->endBox();  // stbl
+       mOwner->endBox();  // minf
       mOwner->endBox();  // mdia
     mOwner->endBox();  // trak
 }
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 4b3813b..39d264c 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -20,6 +20,7 @@
 
 const char *MEDIA_MIMETYPE_IMAGE_JPEG = "image/jpeg";
 
+const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8";
 const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
 const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
 const char *MEDIA_MIMETYPE_VIDEO_H263 = "video/3gpp";
@@ -36,5 +37,7 @@
 const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mpeg4";
 const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/wav";
 const char *MEDIA_MIMETYPE_CONTAINER_OGG = "application/ogg";
+const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA = "video/x-matroska";
+const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS = "video/mp2ts";
 
 }  // namespace android
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 513f49c..56e6136 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -23,6 +23,9 @@
 #include "include/MPEG4Extractor.h"
 #include "include/WAVExtractor.h"
 #include "include/OggExtractor.h"
+#include "include/MPEG2TSExtractor.h"
+
+#include "matroska/MatroskaExtractor.h"
 
 #include <media/stagefright/DataSource.h>
 #include <media/stagefright/MediaDefs.h>
@@ -69,6 +72,10 @@
         return new WAVExtractor(source);
     } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) {
         return new OggExtractor(source);
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) {
+        return new MatroskaExtractor(source);
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
+        return new MPEG2TSExtractor(source);
     }
 
     return NULL;
diff --git a/media/libstagefright/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
index ec89b74..b4ef338 100644
--- a/media/libstagefright/MediaSource.cpp
+++ b/media/libstagefright/MediaSource.cpp
@@ -32,23 +32,43 @@
     mOptions = 0;
     mSeekTimeUs = 0;
     mLatenessUs = 0;
+    mSkipFrameUntilTimeUs = 0;
 }
 
-void MediaSource::ReadOptions::setSeekTo(int64_t time_us) {
+void MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
     mOptions |= kSeekTo_Option;
     mSeekTimeUs = time_us;
+    mSeekMode = mode;
 }
 
 void MediaSource::ReadOptions::clearSeekTo() {
     mOptions &= ~kSeekTo_Option;
     mSeekTimeUs = 0;
+    mSeekMode = SEEK_CLOSEST_SYNC;
 }
 
-bool MediaSource::ReadOptions::getSeekTo(int64_t *time_us) const {
+bool MediaSource::ReadOptions::getSeekTo(
+        int64_t *time_us, SeekMode *mode) const {
     *time_us = mSeekTimeUs;
+    *mode = mSeekMode;
     return (mOptions & kSeekTo_Option) != 0;
 }
 
+void MediaSource::ReadOptions::clearSkipFrame() {
+    mOptions &= ~kSkipFrame_Option;
+    mSkipFrameUntilTimeUs = 0;
+}
+
+void MediaSource::ReadOptions::setSkipFrame(int64_t timeUs) {
+    mOptions |= kSkipFrame_Option;
+    mSkipFrameUntilTimeUs = timeUs;
+}
+
+bool MediaSource::ReadOptions::getSkipFrame(int64_t *timeUs) const {
+    *timeUs = mSkipFrameUntilTimeUs;
+    return (mOptions & kSkipFrame_Option) != 0;
+}
+
 void MediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
     mLatenessUs = lateness_us;
 }
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
new file mode 100644
index 0000000..c02b7f3
--- /dev/null
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2010 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_TAG "NuCachedSource2"
+#include <utils/Log.h>
+
+#include "include/NuCachedSource2.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+struct PageCache {
+    PageCache(size_t pageSize);
+    ~PageCache();
+
+    struct Page {
+        void *mData;
+        size_t mSize;
+    };
+
+    Page *acquirePage();
+    void releasePage(Page *page);
+
+    void appendPage(Page *page);
+    size_t releaseFromStart(size_t maxBytes);
+
+    size_t totalSize() const {
+        return mTotalSize;
+    }
+
+    void copy(size_t from, void *data, size_t size);
+
+private:
+    size_t mPageSize;
+    size_t mTotalSize;
+
+    List<Page *> mActivePages;
+    List<Page *> mFreePages;
+
+    void freePages(List<Page *> *list);
+
+    DISALLOW_EVIL_CONSTRUCTORS(PageCache);
+};
+
+PageCache::PageCache(size_t pageSize)
+    : mPageSize(pageSize),
+      mTotalSize(0) {
+}
+
+PageCache::~PageCache() {
+    freePages(&mActivePages);
+    freePages(&mFreePages);
+}
+
+void PageCache::freePages(List<Page *> *list) {
+    List<Page *>::iterator it = list->begin();
+    while (it != list->end()) {
+        Page *page = *it;
+
+        free(page->mData);
+        delete page;
+        page = NULL;
+
+        ++it;
+    }
+}
+
+PageCache::Page *PageCache::acquirePage() {
+    if (!mFreePages.empty()) {
+        List<Page *>::iterator it = mFreePages.begin();
+        Page *page = *it;
+        mFreePages.erase(it);
+
+        return page;
+    }
+
+    Page *page = new Page;
+    page->mData = malloc(mPageSize);
+    page->mSize = 0;
+
+    return page;
+}
+
+void PageCache::releasePage(Page *page) {
+    page->mSize = 0;
+    mFreePages.push_back(page);
+}
+
+void PageCache::appendPage(Page *page) {
+    mTotalSize += page->mSize;
+    mActivePages.push_back(page);
+}
+
+size_t PageCache::releaseFromStart(size_t maxBytes) {
+    size_t bytesReleased = 0;
+
+    while (maxBytes > 0 && !mActivePages.empty()) {
+        List<Page *>::iterator it = mActivePages.begin();
+
+        Page *page = *it;
+
+        if (maxBytes < page->mSize) {
+            break;
+        }
+
+        mActivePages.erase(it);
+
+        maxBytes -= page->mSize;
+        bytesReleased += page->mSize;
+
+        releasePage(page);
+    }
+
+    mTotalSize -= bytesReleased;
+    return bytesReleased;
+}
+
+void PageCache::copy(size_t from, void *data, size_t size) {
+    LOG(VERBOSE) << "copy from " << from << " size " << size;
+
+    CHECK_LE(from + size, mTotalSize);
+
+    size_t offset = 0;
+    List<Page *>::iterator it = mActivePages.begin();
+    while (from >= offset + (*it)->mSize) {
+        offset += (*it)->mSize;
+        ++it;
+    }
+
+    size_t delta = from - offset;
+    size_t avail = (*it)->mSize - delta;
+
+    if (avail >= size) {
+        memcpy(data, (const uint8_t *)(*it)->mData + delta, size);
+        return;
+    }
+
+    memcpy(data, (const uint8_t *)(*it)->mData + delta, avail);
+    ++it;
+    data = (uint8_t *)data + avail;
+    size -= avail;
+
+    while (size > 0) {
+        size_t copy = (*it)->mSize;
+        if (copy > size) {
+            copy = size;
+        }
+        memcpy(data, (*it)->mData, copy);
+        data = (uint8_t *)data + copy;
+        size -= copy;
+        ++it;
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
+    : mSource(source),
+      mReflector(new AHandlerReflector<NuCachedSource2>(this)),
+      mLooper(new ALooper),
+      mCache(new PageCache(kPageSize)),
+      mCacheOffset(0),
+      mFinalStatus(OK),
+      mLastAccessPos(0),
+      mFetching(true),
+      mLastFetchTimeUs(-1) {
+    mLooper->registerHandler(mReflector);
+    mLooper->start();
+
+    Mutex::Autolock autoLock(mLock);
+    (new AMessage(kWhatFetchMore, mReflector->id()))->post();
+}
+
+NuCachedSource2::~NuCachedSource2() {
+    mLooper->stop();
+    mLooper->unregisterHandler(mReflector->id());
+
+    delete mCache;
+    mCache = NULL;
+}
+
+status_t NuCachedSource2::initCheck() const {
+    return mSource->initCheck();
+}
+
+status_t NuCachedSource2::getSize(off_t *size) {
+    return mSource->getSize(size);
+}
+
+uint32_t NuCachedSource2::flags() {
+    return mSource->flags();
+}
+
+void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatFetchMore:
+        {
+            onFetch();
+            break;
+        }
+
+        case kWhatRead:
+        {
+            onRead(msg);
+            break;
+        }
+
+        default:
+            TRESPASS();
+    }
+}
+
+void NuCachedSource2::fetchInternal() {
+    LOG(VERBOSE) << "fetchInternal";
+
+    CHECK_EQ(mFinalStatus, (status_t)OK);
+
+    PageCache::Page *page = mCache->acquirePage();
+
+    ssize_t n = mSource->readAt(
+            mCacheOffset + mCache->totalSize(), page->mData, kPageSize);
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (n < 0) {
+        LOG(ERROR) << "source returned error " << n;
+        mFinalStatus = n;
+        mCache->releasePage(page);
+    } else if (n == 0) {
+        LOG(INFO) << "ERROR_END_OF_STREAM";
+        mFinalStatus = ERROR_END_OF_STREAM;
+        mCache->releasePage(page);
+    } else {
+        page->mSize = n;
+        mCache->appendPage(page);
+    }
+}
+
+void NuCachedSource2::onFetch() {
+    LOG(VERBOSE) << "onFetch";
+
+    if (mFinalStatus != OK) {
+        LOG(VERBOSE) << "EOS reached, done prefetching for now";
+        mFetching = false;
+    }
+
+    bool keepAlive =
+        !mFetching
+            && mFinalStatus == OK
+            && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs;
+
+    if (mFetching || keepAlive) {
+        if (keepAlive) {
+            LOG(INFO) << "Keep alive";
+        }
+
+        fetchInternal();
+
+        mLastFetchTimeUs = ALooper::GetNowUs();
+
+        if (mFetching && mCache->totalSize() >= kHighWaterThreshold) {
+            LOG(INFO) << "Cache full, done prefetching for now";
+            mFetching = false;
+        }
+    } else {
+        Mutex::Autolock autoLock(mLock);
+        restartPrefetcherIfNecessary_l();
+    }
+
+    (new AMessage(kWhatFetchMore, mReflector->id()))->post(
+            mFetching ? 0 : 100000ll);
+}
+
+void NuCachedSource2::onRead(const sp<AMessage> &msg) {
+    LOG(VERBOSE) << "onRead";
+
+    int64_t offset;
+    CHECK(msg->findInt64("offset", &offset));
+
+    void *data;
+    CHECK(msg->findPointer("data", &data));
+
+    size_t size;
+    CHECK(msg->findSize("size", &size));
+
+    ssize_t result = readInternal(offset, data, size);
+
+    if (result == -EAGAIN) {
+        msg->post(50000);
+        return;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+
+    CHECK(mAsyncResult == NULL);
+
+    mAsyncResult = new AMessage;
+    mAsyncResult->setInt32("result", result);
+
+    mCondition.signal();
+}
+
+void NuCachedSource2::restartPrefetcherIfNecessary_l() {
+    static const size_t kGrayArea = 256 * 1024;
+
+    if (mFetching || mFinalStatus != OK) {
+        return;
+    }
+
+    if (mCacheOffset + mCache->totalSize() - mLastAccessPos
+            >= kLowWaterThreshold) {
+        return;
+    }
+
+    size_t maxBytes = mLastAccessPos - mCacheOffset;
+    if (maxBytes < kGrayArea) {
+        return;
+    }
+
+    maxBytes -= kGrayArea;
+
+    size_t actualBytes = mCache->releaseFromStart(maxBytes);
+    mCacheOffset += actualBytes;
+
+    LOG(INFO) << "restarting prefetcher, totalSize = " << mCache->totalSize();
+    mFetching = true;
+}
+
+ssize_t NuCachedSource2::readAt(off_t offset, void *data, size_t size) {
+    Mutex::Autolock autoSerializer(mSerializer);
+
+    LOG(VERBOSE) << "readAt offset " << offset << " size " << size;
+
+    Mutex::Autolock autoLock(mLock);
+
+    // If the request can be completely satisfied from the cache, do so.
+
+    if (offset >= mCacheOffset
+            && offset + size <= mCacheOffset + mCache->totalSize()) {
+        size_t delta = offset - mCacheOffset;
+        mCache->copy(delta, data, size);
+
+        mLastAccessPos = offset + size;
+
+        return size;
+    }
+
+    sp<AMessage> msg = new AMessage(kWhatRead, mReflector->id());
+    msg->setInt64("offset", offset);
+    msg->setPointer("data", data);
+    msg->setSize("size", size);
+
+    CHECK(mAsyncResult == NULL);
+    msg->post();
+
+    while (mAsyncResult == NULL) {
+        mCondition.wait(mLock);
+    }
+
+    int32_t result;
+    CHECK(mAsyncResult->findInt32("result", &result));
+
+    mAsyncResult.clear();
+
+    if (result > 0) {
+        mLastAccessPos = offset + result;
+    }
+
+    return (ssize_t)result;
+}
+
+size_t NuCachedSource2::cachedSize() {
+    Mutex::Autolock autoLock(mLock);
+    return mCacheOffset + mCache->totalSize();
+}
+
+size_t NuCachedSource2::approxDataRemaining(bool *eos) {
+    Mutex::Autolock autoLock(mLock);
+    return approxDataRemaining_l(eos);
+}
+
+size_t NuCachedSource2::approxDataRemaining_l(bool *eos) {
+    *eos = (mFinalStatus != OK);
+    off_t lastBytePosCached = mCacheOffset + mCache->totalSize();
+    if (mLastAccessPos < lastBytePosCached) {
+        return lastBytePosCached - mLastAccessPos;
+    }
+    return 0;
+}
+
+ssize_t NuCachedSource2::readInternal(off_t offset, void *data, size_t size) {
+    LOG(VERBOSE) << "readInternal offset " << offset << " size " << size;
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (offset < mCacheOffset
+            || offset >= (off_t)(mCacheOffset + mCache->totalSize())) {
+        static const off_t kPadding = 32768;
+
+        // In the presence of multiple decoded streams, once of them will
+        // trigger this seek request, the other one will request data "nearby"
+        // soon, adjust the seek position so that that subsequent request
+        // does not trigger another seek.
+        off_t seekOffset = (offset > kPadding) ? offset - kPadding : 0;
+
+        seekInternal_l(seekOffset);
+    }
+
+    size_t delta = offset - mCacheOffset;
+
+    if (mFinalStatus != OK) {
+        if (delta >= mCache->totalSize()) {
+            return mFinalStatus;
+        }
+
+        size_t avail = mCache->totalSize() - delta;
+        mCache->copy(delta, data, avail);
+
+        return avail;
+    }
+
+    if (offset + size <= mCacheOffset + mCache->totalSize()) {
+        mCache->copy(delta, data, size);
+
+        return size;
+    }
+
+    LOG(VERBOSE) << "deferring read";
+
+    return -EAGAIN;
+}
+
+status_t NuCachedSource2::seekInternal_l(off_t offset) {
+    mLastAccessPos = offset;
+
+    if (offset >= mCacheOffset
+            && offset <= (off_t)(mCacheOffset + mCache->totalSize())) {
+        return OK;
+    }
+
+    LOG(INFO) << "new range: offset= " << offset;
+
+    mCacheOffset = offset;
+
+    size_t totalSize = mCache->totalSize();
+    CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);
+
+    mFinalStatus = OK;
+    mFetching = true;
+
+    return OK;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
new file mode 100644
index 0000000..ab9285d
--- /dev/null
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -0,0 +1,338 @@
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NuHTTPDataSource"
+#include <utils/Log.h>
+
+#include "include/NuHTTPDataSource.h"
+
+#include <cutils/properties.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+static bool ParseSingleUnsignedLong(
+        const char *from, unsigned long *x) {
+    char *end;
+    *x = strtoul(from, &end, 10);
+
+    if (end == from || *end != '\0') {
+        return false;
+    }
+
+    return true;
+}
+
+static bool ParseURL(
+        const char *url, String8 *host, unsigned *port, String8 *path) {
+    host->setTo("");
+    *port = 0;
+    path->setTo("");
+
+    if (strncasecmp("http://", url, 7)) {
+        return false;
+    }
+
+    const char *slashPos = strchr(&url[7], '/');
+
+    if (slashPos == NULL) {
+        host->setTo(&url[7]);
+        path->setTo("/");
+    } else {
+        host->setTo(&url[7], slashPos - &url[7]);
+        path->setTo(slashPos);
+    }
+
+    char *colonPos = strchr(host->string(), ':');
+
+    if (colonPos != NULL) {
+        unsigned long x;
+        if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
+            return false;
+        }
+
+        *port = x;
+
+        size_t colonOffset = colonPos - host->string();
+        String8 tmp(host->string(), colonOffset);
+        *host = tmp;
+    } else {
+        *port = 80;
+    }
+
+    return true;
+}
+
+NuHTTPDataSource::NuHTTPDataSource()
+    : mState(DISCONNECTED),
+      mPort(0),
+      mOffset(0),
+      mContentLength(0),
+      mContentLengthValid(false) {
+}
+
+NuHTTPDataSource::~NuHTTPDataSource() {
+}
+
+status_t NuHTTPDataSource::connect(
+        const char *uri,
+        const KeyedVector<String8, String8> *overrides,
+        off_t offset) {
+    String8 headers;
+    MakeFullHeaders(overrides, &headers);
+
+    return connect(uri, headers, offset);
+}
+
+status_t NuHTTPDataSource::connect(
+        const char *uri,
+        const String8 &headers,
+        off_t offset) {
+    String8 host, path;
+    unsigned port;
+    if (!ParseURL(uri, &host, &port, &path)) {
+        return ERROR_MALFORMED;
+    }
+
+    return connect(host, port, path, headers, offset);
+}
+
+status_t NuHTTPDataSource::connect(
+        const char *host, unsigned port, const char *path,
+        const String8 &headers,
+        off_t offset) {
+    LOGI("connect to %s:%u%s @%ld", host, port, path, offset);
+
+    bool needsToReconnect = true;
+
+    if (mState == CONNECTED && host == mHost && port == mPort
+            && offset == mOffset) {
+        if (mContentLengthValid && mOffset == mContentLength) {
+            LOGI("Didn't have to reconnect, old one's still good.");
+            needsToReconnect = false;
+        }
+    }
+
+    mHost = host;
+    mPort = port;
+    mPath = path;
+    mHeaders = headers;
+
+    status_t err = OK;
+
+    mState = CONNECTING;
+
+    if (needsToReconnect) {
+        mHTTP.disconnect();
+        err = mHTTP.connect(host, port);
+    }
+
+    if (err != OK) {
+        mState = DISCONNECTED;
+    } else if (mState != CONNECTING) {
+        err = UNKNOWN_ERROR;
+    } else {
+        mState = CONNECTED;
+
+        mOffset = offset;
+        mContentLength = 0;
+        mContentLengthValid = false;
+
+        String8 request("GET ");
+        request.append(mPath);
+        request.append(" HTTP/1.1\r\n");
+        request.append("Host: ");
+        request.append(mHost);
+        request.append("\r\n");
+
+        if (offset != 0) {
+            char rangeHeader[128];
+            sprintf(rangeHeader, "Range: bytes=%ld-\r\n", offset);
+            request.append(rangeHeader);
+        }
+
+        request.append(mHeaders);
+        request.append("\r\n");
+
+        int httpStatus;
+        if ((err = mHTTP.send(request.string(), request.size())) != OK
+                || (err = mHTTP.receive_header(&httpStatus)) != OK) {
+            mHTTP.disconnect();
+            mState = DISCONNECTED;
+            return err;
+        }
+
+        if (httpStatus == 302) {
+            string value;
+            CHECK(mHTTP.find_header_value("Location", &value));
+
+            mState = DISCONNECTED;
+
+            mHTTP.disconnect();
+
+            return connect(value.c_str(), headers, offset);
+        }
+
+        if (httpStatus < 200 || httpStatus >= 300) {
+            mState = DISCONNECTED;
+            mHTTP.disconnect();
+
+            return ERROR_IO;
+        }
+
+        applyTimeoutResponse();
+
+        if (offset == 0) {
+            string value;
+            unsigned long x;
+            if (mHTTP.find_header_value(string("Content-Length"), &value)
+                    && ParseSingleUnsignedLong(value.c_str(), &x)) {
+                mContentLength = (off_t)x;
+                mContentLengthValid = true;
+            }
+        } else {
+            string value;
+            unsigned long x;
+            if (mHTTP.find_header_value(string("Content-Range"), &value)) {
+                const char *slashPos = strchr(value.c_str(), '/');
+                if (slashPos != NULL
+                        && ParseSingleUnsignedLong(slashPos + 1, &x)) {
+                    mContentLength = x;
+                    mContentLengthValid = true;
+                }
+            }
+        }
+    }
+
+    return err;
+}
+
+void NuHTTPDataSource::disconnect() {
+    if (mState == CONNECTING || mState == CONNECTED) {
+        mHTTP.disconnect();
+    }
+    mState = DISCONNECTED;
+}
+
+status_t NuHTTPDataSource::initCheck() const {
+    return mState == CONNECTED ? OK : NO_INIT;
+}
+
+ssize_t NuHTTPDataSource::readAt(off_t offset, void *data, size_t size) {
+    LOGV("readAt offset %ld, size %d", offset, size);
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (offset != mOffset) {
+        String8 host = mHost;
+        String8 path = mPath;
+        String8 headers = mHeaders;
+        status_t err = connect(host, mPort, path, headers, offset);
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
+    if (mContentLengthValid) {
+        size_t avail =
+            (offset >= mContentLength) ? 0 : mContentLength - offset;
+
+        if (size > avail) {
+            size = avail;
+        }
+    }
+
+    size_t numBytesRead = 0;
+    while (numBytesRead < size) {
+        ssize_t n =
+            mHTTP.receive((uint8_t *)data + numBytesRead, size - numBytesRead);
+
+        if (n < 0) {
+            return n;
+        }
+
+        numBytesRead += (size_t)n;
+
+        if (n == 0) {
+            if (mContentLengthValid) {
+                // We know the content length and made sure not to read beyond
+                // it and yet the server closed the connection on us.
+                return ERROR_IO;
+            }
+
+            break;
+        }
+    }
+
+    mOffset += numBytesRead;
+
+    return numBytesRead;
+}
+
+status_t NuHTTPDataSource::getSize(off_t *size) {
+    *size = 0;
+
+    if (mState != CONNECTED) {
+        return ERROR_IO;
+    }
+
+    if (mContentLengthValid) {
+        *size = mContentLength;
+        return OK;
+    }
+
+    return ERROR_UNSUPPORTED;
+}
+
+uint32_t NuHTTPDataSource::flags() {
+    return kWantsPrefetching;
+}
+
+// static
+void NuHTTPDataSource::MakeFullHeaders(
+        const KeyedVector<String8, String8> *overrides, String8 *headers) {
+    headers->setTo("");
+
+    headers->append("User-Agent: stagefright/1.1 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.build.version.release", value, "Unknown");
+    headers->append(value);
+    headers->append(")\r\n");
+
+    if (overrides == NULL) {
+        return;
+    }
+
+    for (size_t i = 0; i < overrides->size(); ++i) {
+        String8 line;
+        line.append(overrides->keyAt(i));
+        line.append(": ");
+        line.append(overrides->valueAt(i));
+        line.append("\r\n");
+
+        headers->append(line);
+    }
+}
+
+void NuHTTPDataSource::applyTimeoutResponse() {
+    string timeout;
+    if (mHTTP.find_header_value("X-SocketTimeout", &timeout)) {
+        const char *s = timeout.c_str();
+        char *end;
+        long tmp = strtol(s, &end, 10);
+        if (end == s || *end != '\0') {
+            LOGW("Illegal X-SocketTimeout value given.");
+            return;
+        }
+
+        LOGI("overriding default timeout, new timeout is %ld seconds", tmp);
+        mHTTP.setReceiveTimeout(tmp);
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 69da7ef..3fba2d9 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -19,13 +19,18 @@
 #include <utils/Log.h>
 
 #include "include/AACDecoder.h"
+#include "include/AACEncoder.h"
 #include "include/AMRNBDecoder.h"
 #include "include/AMRNBEncoder.h"
 #include "include/AMRWBDecoder.h"
+#include "include/AMRWBEncoder.h"
 #include "include/AVCDecoder.h"
+#include "include/AVCEncoder.h"
 #include "include/M4vH263Decoder.h"
+#include "include/M4vH263Encoder.h"
 #include "include/MP3Decoder.h"
 #include "include/VorbisDecoder.h"
+#include "include/VPXDecoder.h"
 
 #include "include/ESDS.h"
 
@@ -60,6 +65,11 @@
     return new name(source); \
 }
 
+#define FACTORY_CREATE_ENCODER(name) \
+static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
+    return new name(source, meta); \
+}
+
 #define FACTORY_REF(name) { #name, Make##name },
 
 FACTORY_CREATE(MP3Decoder)
@@ -69,7 +79,37 @@
 FACTORY_CREATE(AVCDecoder)
 FACTORY_CREATE(M4vH263Decoder)
 FACTORY_CREATE(VorbisDecoder)
-FACTORY_CREATE(AMRNBEncoder)
+FACTORY_CREATE(VPXDecoder)
+FACTORY_CREATE_ENCODER(AMRNBEncoder)
+FACTORY_CREATE_ENCODER(AMRWBEncoder)
+FACTORY_CREATE_ENCODER(AACEncoder)
+FACTORY_CREATE_ENCODER(AVCEncoder)
+FACTORY_CREATE_ENCODER(M4vH263Encoder)
+
+static sp<MediaSource> InstantiateSoftwareEncoder(
+        const char *name, const sp<MediaSource> &source,
+        const sp<MetaData> &meta) {
+    struct FactoryInfo {
+        const char *name;
+        sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
+    };
+
+    static const FactoryInfo kFactoryInfo[] = {
+        FACTORY_REF(AMRNBEncoder)
+        FACTORY_REF(AMRWBEncoder)
+        FACTORY_REF(AACEncoder)
+        FACTORY_REF(AVCEncoder)
+        FACTORY_REF(M4vH263Encoder)
+    };
+    for (size_t i = 0;
+         i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
+        if (!strcmp(name, kFactoryInfo[i].name)) {
+            return (*kFactoryInfo[i].CreateFunc)(source, meta);
+        }
+    }
+
+    return NULL;
+}
 
 static sp<MediaSource> InstantiateSoftwareCodec(
         const char *name, const sp<MediaSource> &source) {
@@ -86,7 +126,7 @@
         FACTORY_REF(AVCDecoder)
         FACTORY_REF(M4vH263Decoder)
         FACTORY_REF(VorbisDecoder)
-        FACTORY_REF(AMRNBEncoder)
+        FACTORY_REF(VPXDecoder)
     };
     for (size_t i = 0;
          i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
@@ -115,34 +155,47 @@
     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
     { MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
 //    { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacdec" },
+    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
 //    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4dec" },
+    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
 //    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263dec" },
+    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
 //    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" },
     { MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
+    { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
 };
 
 static const CodecInfo kEncoderInfo[] = {
     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" },
     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
+    { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
     { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
-    { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
+    { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
+//    { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
+    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
-    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" },
+    { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" },
+//    { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" },
+    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
-    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
+    { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" },
+//    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
+    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
+    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
-    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
+    { MEDIA_MIMETYPE_VIDEO_AVC, "AVCEncoder" },
+//    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
 };
 
 #undef OPTIONAL
@@ -296,10 +349,17 @@
         quirks |= kRequiresAllocateBufferOnInputPorts;
         quirks |= kRequiresAllocateBufferOnOutputPorts;
     }
+    if (!strncmp(componentName, "OMX.qcom.7x30.video.encoder.", 28)) {
+    }
     if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
         quirks |= kRequiresAllocateBufferOnOutputPorts;
         quirks |= kDefersOutputBufferAllocation;
     }
+    if (!strncmp(componentName, "OMX.qcom.7x30.video.decoder.", 28)) {
+        quirks |= kRequiresAllocateBufferOnInputPorts;
+        quirks |= kRequiresAllocateBufferOnOutputPorts;
+        quirks |= kDefersOutputBufferAllocation;
+    }
 
     if (!strncmp(componentName, "OMX.TI.", 7)) {
         // Apparently I must not use OMX_UseBuffer on either input or
@@ -309,6 +369,9 @@
 
         quirks |= kRequiresAllocateBufferOnInputPorts;
         quirks |= kRequiresAllocateBufferOnOutputPorts;
+        if (!strncmp(componentName, "OMX.TI.Video.encoder", 20)) {
+            quirks |= kAvoidMemcopyInputRecordingFrames;
+        }
     }
 
     if (!strcmp(componentName, "OMX.TI.Video.Decoder")) {
@@ -384,8 +447,8 @@
     for (size_t i = 0; i < matchingCodecs.size(); ++i) {
         componentName = matchingCodecs[i].string();
 
-#if BUILD_WITH_FULL_STAGEFRIGHT
-        sp<MediaSource> softwareCodec =
+        sp<MediaSource> softwareCodec = createEncoder?
+            InstantiateSoftwareEncoder(componentName, source, meta):
             InstantiateSoftwareCodec(componentName, source);
 
         if (softwareCodec != NULL) {
@@ -393,7 +456,6 @@
 
             return softwareCodec;
         }
-#endif
 
         LOGV("Attempting to allocate OMX node '%s'", componentName);
 
@@ -496,11 +558,12 @@
             size -= length;
         }
 
-        LOGV("AVC profile = %d (%s), level = %d",
-             (int)profile, AVCProfileToString(profile), (int)level / 10);
+        CODEC_LOGV(
+                "AVC profile = %d (%s), level = %d",
+                (int)profile, AVCProfileToString(profile), level);
 
         if (!strcmp(mComponentName, "OMX.TI.Video.Decoder")
-            && (profile != kAVCProfileBaseline || level > 39)) {
+            && (profile != kAVCProfileBaseline || level > 30)) {
             // This stream exceeds the decoder's capabilities. The decoder
             // does not handle this gracefully and would clobber the heap
             // and wreak havoc instead...
@@ -510,28 +573,33 @@
         }
     }
 
+    int32_t bitRate = 0;
+    if (mIsEncoder) {
+        CHECK(meta->findInt32(kKeyBitRate, &bitRate));
+    }
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
-        setAMRFormat(false /* isWAMR */);
+        setAMRFormat(false /* isWAMR */, bitRate);
     }
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
-        setAMRFormat(true /* isWAMR */);
+        setAMRFormat(true /* isWAMR */, bitRate);
     }
     if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
         int32_t numChannels, sampleRate;
         CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
         CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
 
-        setAACFormat(numChannels, sampleRate);
+        setAACFormat(numChannels, sampleRate, bitRate);
     }
+
     if (!strncasecmp(mMIME, "video/", 6)) {
-        int32_t width, height;
-        bool success = meta->findInt32(kKeyWidth, &width);
-        success = success && meta->findInt32(kKeyHeight, &height);
-        CHECK(success);
 
         if (mIsEncoder) {
-            setVideoInputFormat(mMIME, width, height);
+            setVideoInputFormat(mMIME, meta);
         } else {
+            int32_t width, height;
+            bool success = meta->findInt32(kKeyWidth, &width);
+            success = success && meta->findInt32(kKeyHeight, &height);
+            CHECK(success);
             status_t err = setVideoOutputFormat(
                     mMIME, width, height);
 
@@ -570,7 +638,8 @@
     }
 
     if (!strcmp(mComponentName, "OMX.TI.AMR.encode")
-        || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")) {
+        || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")
+        || !strcmp(mComponentName, "OMX.TI.AAC.encode")) {
         setMinBufferSize(kPortIndexOutput, 8192);  // XXX
     }
 
@@ -683,6 +752,7 @@
         case OMX_COLOR_FormatCbYCrY:
             return width * height * 2;
 
+        case OMX_COLOR_FormatYUV420Planar:
         case OMX_COLOR_FormatYUV420SemiPlanar:
             return (width * height * 3) / 2;
 
@@ -693,8 +763,17 @@
 }
 
 void OMXCodec::setVideoInputFormat(
-        const char *mime, OMX_U32 width, OMX_U32 height) {
-    CODEC_LOGV("setVideoInputFormat width=%ld, height=%ld", width, height);
+        const char *mime, const sp<MetaData>& meta) {
+
+    int32_t width, height, frameRate, bitRate, stride, sliceHeight;
+    bool success = meta->findInt32(kKeyWidth, &width);
+    success = success && meta->findInt32(kKeyHeight, &height);
+    success = success && meta->findInt32(kKeySampleRate, &frameRate);
+    success = success && meta->findInt32(kKeyBitRate, &bitRate);
+    success = success && meta->findInt32(kKeyStride, &stride);
+    success = success && meta->findInt32(kKeySliceHeight, &sliceHeight);
+    CHECK(success);
+    CHECK(stride != 0);
 
     OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
     if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
@@ -713,38 +792,15 @@
         colorFormat = OMX_COLOR_FormatYCbYCr;
     }
 
+    status_t err;
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+    //////////////////////// Input port /////////////////////////
     CHECK_EQ(setVideoPortFormatType(
             kPortIndexInput, OMX_VIDEO_CodingUnused,
             colorFormat), OK);
 
-    CHECK_EQ(setVideoPortFormatType(
-            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
-            OK);
-
-    OMX_PARAM_PORTDEFINITIONTYPE def;
-    InitOMXParams(&def);
-    def.nPortIndex = kPortIndexOutput;
-
-    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
-
-    status_t err = mOMX->getParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-
-    CHECK_EQ(err, OK);
-    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
-
-    video_def->nFrameWidth = width;
-    video_def->nFrameHeight = height;
-
-    video_def->eCompressionFormat = compressionFormat;
-    video_def->eColorFormat = OMX_COLOR_FormatUnused;
-
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-    CHECK_EQ(err, OK);
-
-    ////////////////////////////////////////////////////////////////////////////
-
     InitOMXParams(&def);
     def.nPortIndex = kPortIndexInput;
 
@@ -752,35 +808,62 @@
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
-    def.nBufferSize = getFrameSize(colorFormat, width, height);
-    CODEC_LOGV("Setting nBufferSize = %ld", def.nBufferSize);
+    def.nBufferSize = getFrameSize(colorFormat,
+            stride > 0? stride: -stride, sliceHeight);
 
     CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
 
     video_def->nFrameWidth = width;
     video_def->nFrameHeight = height;
+    video_def->nStride = stride;
+    video_def->nSliceHeight = sliceHeight;
+    video_def->xFramerate = (frameRate << 16);  // Q16 format
     video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
     video_def->eColorFormat = colorFormat;
 
-    video_def->xFramerate = 24 << 16;  // XXX crucial!
-
     err = mOMX->setParameter(
             mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
+    //////////////////////// Output port /////////////////////////
+    CHECK_EQ(setVideoPortFormatType(
+            kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
+            OK);
+    InitOMXParams(&def);
+    def.nPortIndex = kPortIndexOutput;
+
+    err = mOMX->getParameter(
+            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+    CHECK_EQ(err, OK);
+    CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
+
+    video_def->nFrameWidth = width;
+    video_def->nFrameHeight = height;
+    video_def->xFramerate = 0;      // No need for output port
+    video_def->nBitrate = bitRate;  // Q16 format
+    video_def->eCompressionFormat = compressionFormat;
+    video_def->eColorFormat = OMX_COLOR_FormatUnused;
+
+    err = mOMX->setParameter(
+            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    CHECK_EQ(err, OK);
+
+    /////////////////// Codec-specific ////////////////////////
     switch (compressionFormat) {
         case OMX_VIDEO_CodingMPEG4:
         {
-            CHECK_EQ(setupMPEG4EncoderParameters(), OK);
+            CHECK_EQ(setupMPEG4EncoderParameters(meta), OK);
             break;
         }
 
         case OMX_VIDEO_CodingH263:
+            CHECK_EQ(setupH263EncoderParameters(meta), OK);
             break;
 
         case OMX_VIDEO_CodingAVC:
         {
-            CHECK_EQ(setupAVCEncoderParameters(), OK);
+            CHECK_EQ(setupAVCEncoderParameters(meta), OK);
             break;
         }
 
@@ -790,7 +873,159 @@
     }
 }
 
-status_t OMXCodec::setupMPEG4EncoderParameters() {
+static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
+    if (iFramesInterval < 0) {
+        return 0xFFFFFFFF;
+    } else if (iFramesInterval == 0) {
+        return 0;
+    }
+    OMX_U32 ret = frameRate * iFramesInterval;
+    CHECK(ret > 1);
+    return ret;
+}
+
+status_t OMXCodec::setupErrorCorrectionParameters() {
+    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
+    InitOMXParams(&errorCorrectionType);
+    errorCorrectionType.nPortIndex = kPortIndexOutput;
+
+    status_t err = mOMX->getParameter(
+            mNode, OMX_IndexParamVideoErrorCorrection,
+            &errorCorrectionType, sizeof(errorCorrectionType));
+    CHECK_EQ(err, OK);
+
+    errorCorrectionType.bEnableHEC = OMX_FALSE;
+    errorCorrectionType.bEnableResync = OMX_TRUE;
+    errorCorrectionType.nResynchMarkerSpacing = 256;
+    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
+    errorCorrectionType.bEnableRVLC = OMX_FALSE;
+
+    err = mOMX->setParameter(
+            mNode, OMX_IndexParamVideoErrorCorrection,
+            &errorCorrectionType, sizeof(errorCorrectionType));
+    CHECK_EQ(err, OK);
+    return OK;
+}
+
+status_t OMXCodec::setupBitRate(int32_t bitRate) {
+    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
+    InitOMXParams(&bitrateType);
+    bitrateType.nPortIndex = kPortIndexOutput;
+
+    status_t err = mOMX->getParameter(
+            mNode, OMX_IndexParamVideoBitrate,
+            &bitrateType, sizeof(bitrateType));
+    CHECK_EQ(err, OK);
+
+    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
+    bitrateType.nTargetBitrate = bitRate;
+
+    err = mOMX->setParameter(
+            mNode, OMX_IndexParamVideoBitrate,
+            &bitrateType, sizeof(bitrateType));
+    CHECK_EQ(err, OK);
+    return OK;
+}
+
+status_t OMXCodec::getVideoProfileLevel(
+        const sp<MetaData>& meta,
+        const CodecProfileLevel& defaultProfileLevel,
+        CodecProfileLevel &profileLevel) {
+    CODEC_LOGV("Default profile: %ld, level %ld",
+            defaultProfileLevel.mProfile, defaultProfileLevel.mLevel);
+
+    // Are the default profile and level overwriten?
+    int32_t profile, level;
+    if (!meta->findInt32(kKeyVideoProfile, &profile)) {
+        profile = defaultProfileLevel.mProfile;
+    }
+    if (!meta->findInt32(kKeyVideoLevel, &level)) {
+        level = defaultProfileLevel.mLevel;
+    }
+    CODEC_LOGV("Target profile: %d, level: %d", profile, level);
+
+    // Are the target profile and level supported by the encoder?
+    OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+    InitOMXParams(&param);
+    param.nPortIndex = kPortIndexOutput;
+    for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
+        status_t err = mOMX->getParameter(
+                mNode, OMX_IndexParamVideoProfileLevelQuerySupported,
+                &param, sizeof(param));
+
+        if (err != OK) return err;
+
+        int32_t supportedProfile = static_cast<int32_t>(param.eProfile);
+        int32_t supportedLevel = static_cast<int32_t>(param.eLevel);
+        CODEC_LOGV("Supported profile: %d, level %d",
+            supportedProfile, supportedLevel);
+
+        if (profile == supportedProfile &&
+            level == supportedLevel) {
+            profileLevel.mProfile = profile;
+            profileLevel.mLevel = level;
+            return OK;
+        }
+    }
+
+    CODEC_LOGE("Target profile (%d) and level (%d) is not supported",
+            profile, level);
+    return BAD_VALUE;
+}
+
+status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
+    int32_t iFramesInterval, frameRate, bitRate;
+    bool success = meta->findInt32(kKeyBitRate, &bitRate);
+    success = success && meta->findInt32(kKeySampleRate, &frameRate);
+    success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
+    CHECK(success);
+    OMX_VIDEO_PARAM_H263TYPE h263type;
+    InitOMXParams(&h263type);
+    h263type.nPortIndex = kPortIndexOutput;
+
+    status_t err = mOMX->getParameter(
+            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+    CHECK_EQ(err, OK);
+
+    h263type.nAllowedPictureTypes =
+        OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
+
+    h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+    if (h263type.nPFrames == 0) {
+        h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+    }
+    h263type.nBFrames = 0;
+
+    // Check profile and level parameters
+    CodecProfileLevel defaultProfileLevel, profileLevel;
+    defaultProfileLevel.mProfile = OMX_VIDEO_H263ProfileBaseline;
+    defaultProfileLevel.mLevel = OMX_VIDEO_H263Level45;
+    err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
+    if (err != OK) return err;
+    h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile);
+    h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(profileLevel.mLevel);
+
+    h263type.bPLUSPTYPEAllowed = OMX_FALSE;
+    h263type.bForceRoundingTypeToZero = OMX_FALSE;
+    h263type.nPictureHeaderRepetition = 0;
+    h263type.nGOBHeaderInterval = 0;
+
+    err = mOMX->setParameter(
+            mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+    CHECK_EQ(err, OK);
+
+    CHECK_EQ(setupBitRate(bitRate), OK);
+    CHECK_EQ(setupErrorCorrectionParameters(), OK);
+
+    return OK;
+}
+
+status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
+    int32_t iFramesInterval, frameRate, bitRate;
+    bool success = meta->findInt32(kKeyBitRate, &bitRate);
+    success = success && meta->findInt32(kKeySampleRate, &frameRate);
+    success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
+    CHECK(success);
     OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
     InitOMXParams(&mpeg4type);
     mpeg4type.nPortIndex = kPortIndexOutput;
@@ -806,9 +1041,11 @@
     mpeg4type.nAllowedPictureTypes =
         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
 
-    mpeg4type.nPFrames = 23;
+    mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+    if (mpeg4type.nPFrames == 0) {
+        mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+    }
     mpeg4type.nBFrames = 0;
-
     mpeg4type.nIDCVLCThreshold = 0;
     mpeg4type.bACPred = OMX_TRUE;
     mpeg4type.nMaxPacketSize = 256;
@@ -816,58 +1053,32 @@
     mpeg4type.nHeaderExtension = 0;
     mpeg4type.bReversibleVLC = OMX_FALSE;
 
-    mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileCore;
-    mpeg4type.eLevel = OMX_VIDEO_MPEG4Level2;
+    // Check profile and level parameters
+    CodecProfileLevel defaultProfileLevel, profileLevel;
+    defaultProfileLevel.mProfile = OMX_VIDEO_MPEG4ProfileSimple;
+    defaultProfileLevel.mLevel = OMX_VIDEO_MPEG4Level2;
+    err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
+    if (err != OK) return err;
+    mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
+    mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel);
 
     err = mOMX->setParameter(
             mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
     CHECK_EQ(err, OK);
 
-    // ----------------
-
-    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
-    InitOMXParams(&bitrateType);
-    bitrateType.nPortIndex = kPortIndexOutput;
-
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoBitrate,
-            &bitrateType, sizeof(bitrateType));
-    CHECK_EQ(err, OK);
-
-    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
-    bitrateType.nTargetBitrate = 1000000;
-
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamVideoBitrate,
-            &bitrateType, sizeof(bitrateType));
-    CHECK_EQ(err, OK);
-
-    // ----------------
-
-    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
-    InitOMXParams(&errorCorrectionType);
-    errorCorrectionType.nPortIndex = kPortIndexOutput;
-
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoErrorCorrection,
-            &errorCorrectionType, sizeof(errorCorrectionType));
-    CHECK_EQ(err, OK);
-
-    errorCorrectionType.bEnableHEC = OMX_FALSE;
-    errorCorrectionType.bEnableResync = OMX_TRUE;
-    errorCorrectionType.nResynchMarkerSpacing = 256;
-    errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
-    errorCorrectionType.bEnableRVLC = OMX_FALSE;
-
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamVideoErrorCorrection,
-            &errorCorrectionType, sizeof(errorCorrectionType));
-    CHECK_EQ(err, OK);
+    CHECK_EQ(setupBitRate(bitRate), OK);
+    CHECK_EQ(setupErrorCorrectionParameters(), OK);
 
     return OK;
 }
 
-status_t OMXCodec::setupAVCEncoderParameters() {
+status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
+    int32_t iFramesInterval, frameRate, bitRate;
+    bool success = meta->findInt32(kKeyBitRate, &bitRate);
+    success = success && meta->findInt32(kKeySampleRate, &frameRate);
+    success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
+    CHECK(success);
+
     OMX_VIDEO_PARAM_AVCTYPE h264type;
     InitOMXParams(&h264type);
     h264type.nPortIndex = kPortIndexOutput;
@@ -880,47 +1091,51 @@
         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
 
     h264type.nSliceHeaderSpacing = 0;
-    h264type.nBFrames = 0;
-    h264type.bUseHadamard = OMX_TRUE;
-    h264type.nRefFrames = 1;
-    h264type.nRefIdx10ActiveMinus1 = 0;
-    h264type.nRefIdx11ActiveMinus1 = 0;
+    h264type.nBFrames = 0;   // No B frames support yet
+    h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+    if (h264type.nPFrames == 0) {
+        h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+    }
+
+    // Check profile and level parameters
+    CodecProfileLevel defaultProfileLevel, profileLevel;
+    defaultProfileLevel.mProfile = h264type.eProfile;
+    defaultProfileLevel.mLevel = h264type.eLevel;
+    err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
+    if (err != OK) return err;
+    h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
+    h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
+
+    if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
+        h264type.bUseHadamard = OMX_TRUE;
+        h264type.nRefFrames = 1;
+        h264type.nRefIdx10ActiveMinus1 = 0;
+        h264type.nRefIdx11ActiveMinus1 = 0;
+        h264type.bEntropyCodingCABAC = OMX_FALSE;
+        h264type.bWeightedPPrediction = OMX_FALSE;
+        h264type.bconstIpred = OMX_FALSE;
+        h264type.bDirect8x8Inference = OMX_FALSE;
+        h264type.bDirectSpatialTemporal = OMX_FALSE;
+        h264type.nCabacInitIdc = 0;
+    }
+
+    if (h264type.nBFrames != 0) {
+        h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
+    }
+
     h264type.bEnableUEP = OMX_FALSE;
     h264type.bEnableFMO = OMX_FALSE;
     h264type.bEnableASO = OMX_FALSE;
     h264type.bEnableRS = OMX_FALSE;
-    h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
-    h264type.eLevel = OMX_VIDEO_AVCLevel1b;
     h264type.bFrameMBsOnly = OMX_TRUE;
     h264type.bMBAFF = OMX_FALSE;
-    h264type.bEntropyCodingCABAC = OMX_FALSE;
-    h264type.bWeightedPPrediction = OMX_FALSE;
-    h264type.bconstIpred = OMX_FALSE;
-    h264type.bDirect8x8Inference = OMX_FALSE;
-    h264type.bDirectSpatialTemporal = OMX_FALSE;
-    h264type.nCabacInitIdc = 0;
     h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
 
     err = mOMX->setParameter(
             mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
     CHECK_EQ(err, OK);
 
-    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
-    InitOMXParams(&bitrateType);
-    bitrateType.nPortIndex = kPortIndexOutput;
-
-    err = mOMX->getParameter(
-            mNode, OMX_IndexParamVideoBitrate,
-            &bitrateType, sizeof(bitrateType));
-    CHECK_EQ(err, OK);
-
-    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
-    bitrateType.nTargetBitrate = 1000000;
-
-    err = mOMX->setParameter(
-            mNode, OMX_IndexParamVideoBitrate,
-            &bitrateType, sizeof(bitrateType));
-    CHECK_EQ(err, OK);
+    CHECK_EQ(setupBitRate(bitRate), OK);
 
     return OK;
 }
@@ -1057,7 +1272,11 @@
       mNoMoreOutputData(false),
       mOutputPortSettingsHaveChanged(false),
       mSeekTimeUs(-1),
-      mLeftOverBuffer(NULL) {
+      mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
+      mTargetTimeUs(-1),
+      mSkipTimeUs(-1),
+      mLeftOverBuffer(NULL),
+      mPaused(false) {
     mPortStatus[kPortIndexInput] = ENABLED;
     mPortStatus[kPortIndexOutput] = ENABLED;
 
@@ -1424,13 +1643,33 @@
                         kKeyBufferID,
                         msg.u.extended_buffer_data.buffer);
 
-                mFilledBuffers.push_back(i);
-                mBufferFilled.signal();
-
                 if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
                     CODEC_LOGV("No more output data.");
                     mNoMoreOutputData = true;
                 }
+
+                if (mTargetTimeUs >= 0) {
+                    CHECK(msg.u.extended_buffer_data.timestamp <= mTargetTimeUs);
+
+                    if (msg.u.extended_buffer_data.timestamp < mTargetTimeUs) {
+                        CODEC_LOGV(
+                                "skipping output buffer at timestamp %lld us",
+                                msg.u.extended_buffer_data.timestamp);
+
+                        fillOutputBuffer(info);
+                        break;
+                    }
+
+                    CODEC_LOGV(
+                            "returning output buffer at target timestamp "
+                            "%lld us",
+                            msg.u.extended_buffer_data.timestamp);
+
+                    mTargetTimeUs = -1;
+                }
+
+                mFilledBuffers.push_back(i);
+                mBufferFilled.signal();
             }
 
             break;
@@ -1647,6 +1886,9 @@
                     CODEC_LOGV("Finished flushing both ports, now continuing from"
                          " seek-time.");
 
+                    // We implicitly resume pulling on our upstream source.
+                    mPaused = false;
+
                     drainInputBuffers();
                     fillOutputBuffers();
                 }
@@ -1946,6 +2188,10 @@
         return;
     }
 
+    if (mPaused) {
+        return;
+    }
+
     status_t err;
 
     bool signalEOS = false;
@@ -1955,26 +2201,40 @@
     int32_t n = 0;
     for (;;) {
         MediaBuffer *srcBuffer;
+        MediaSource::ReadOptions options;
+        if (mSkipTimeUs >= 0) {
+            options.setSkipFrame(mSkipTimeUs);
+        }
         if (mSeekTimeUs >= 0) {
             if (mLeftOverBuffer) {
                 mLeftOverBuffer->release();
                 mLeftOverBuffer = NULL;
             }
-
-            MediaSource::ReadOptions options;
-            options.setSeekTo(mSeekTimeUs);
+            options.setSeekTo(mSeekTimeUs, mSeekMode);
 
             mSeekTimeUs = -1;
+            mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
             mBufferFilled.signal();
 
             err = mSource->read(&srcBuffer, &options);
+
+            if (err == OK) {
+                int64_t targetTimeUs;
+                if (srcBuffer->meta_data()->findInt64(
+                            kKeyTargetTime, &targetTimeUs)
+                        && targetTimeUs >= 0) {
+                    mTargetTimeUs = targetTimeUs;
+                } else {
+                    mTargetTimeUs = -1;
+                }
+            }
         } else if (mLeftOverBuffer) {
             srcBuffer = mLeftOverBuffer;
             mLeftOverBuffer = NULL;
 
             err = OK;
         } else {
-            err = mSource->read(&srcBuffer);
+            err = mSource->read(&srcBuffer, &options);
         }
 
         if (err != OK) {
@@ -2004,13 +2264,19 @@
             break;
         }
 
-        memcpy((uint8_t *)info->mData + offset,
-               (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
-               srcBuffer->range_length());
+        if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
+            CHECK(mOMXLivesLocally && offset == 0);
+            OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
+            header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
+        } else {
+            memcpy((uint8_t *)info->mData + offset,
+                    (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
+                    srcBuffer->range_length());
+        }
 
         int64_t lastBufferTimeUs;
         CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
-        CHECK(timestampUs >= 0);
+        CHECK(lastBufferTimeUs >= 0);
 
         if (offset == 0) {
             timestampUs = lastBufferTimeUs;
@@ -2128,11 +2394,24 @@
 
 void OMXCodec::setRawAudioFormat(
         OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
+
+    // port definition
+    OMX_PARAM_PORTDEFINITIONTYPE def;
+    InitOMXParams(&def);
+    def.nPortIndex = portIndex;
+    status_t err = mOMX->getParameter(
+            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+    CHECK_EQ(err, OK);
+    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+    CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
+            &def, sizeof(def)), OK);
+
+    // pcm param
     OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
     InitOMXParams(&pcmParams);
     pcmParams.nPortIndex = portIndex;
 
-    status_t err = mOMX->getParameter(
+    err = mOMX->getParameter(
             mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
 
     CHECK_EQ(err, OK);
@@ -2159,7 +2438,51 @@
     CHECK_EQ(err, OK);
 }
 
-void OMXCodec::setAMRFormat(bool isWAMR) {
+static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
+    if (isAMRWB) {
+        if (bps <= 6600) {
+            return OMX_AUDIO_AMRBandModeWB0;
+        } else if (bps <= 8850) {
+            return OMX_AUDIO_AMRBandModeWB1;
+        } else if (bps <= 12650) {
+            return OMX_AUDIO_AMRBandModeWB2;
+        } else if (bps <= 14250) {
+            return OMX_AUDIO_AMRBandModeWB3;
+        } else if (bps <= 15850) {
+            return OMX_AUDIO_AMRBandModeWB4;
+        } else if (bps <= 18250) {
+            return OMX_AUDIO_AMRBandModeWB5;
+        } else if (bps <= 19850) {
+            return OMX_AUDIO_AMRBandModeWB6;
+        } else if (bps <= 23050) {
+            return OMX_AUDIO_AMRBandModeWB7;
+        }
+
+        // 23850 bps
+        return OMX_AUDIO_AMRBandModeWB8;
+    } else {  // AMRNB
+        if (bps <= 4750) {
+            return OMX_AUDIO_AMRBandModeNB0;
+        } else if (bps <= 5150) {
+            return OMX_AUDIO_AMRBandModeNB1;
+        } else if (bps <= 5900) {
+            return OMX_AUDIO_AMRBandModeNB2;
+        } else if (bps <= 6700) {
+            return OMX_AUDIO_AMRBandModeNB3;
+        } else if (bps <= 7400) {
+            return OMX_AUDIO_AMRBandModeNB4;
+        } else if (bps <= 7950) {
+            return OMX_AUDIO_AMRBandModeNB5;
+        } else if (bps <= 10200) {
+            return OMX_AUDIO_AMRBandModeNB6;
+        }
+
+        // 12200 bps
+        return OMX_AUDIO_AMRBandModeNB7;
+    }
+}
+
+void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
     OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
 
     OMX_AUDIO_PARAM_AMRTYPE def;
@@ -2172,9 +2495,8 @@
     CHECK_EQ(err, OK);
 
     def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
-    def.eAMRBandMode =
-        isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0;
 
+    def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
     err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
     CHECK_EQ(err, OK);
 
@@ -2191,9 +2513,61 @@
     }
 }
 
-void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
+void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
+    CHECK(numChannels == 1 || numChannels == 2);
     if (mIsEncoder) {
+        //////////////// input port ////////////////////
         setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+
+        //////////////// output port ////////////////////
+        // format
+        OMX_AUDIO_PARAM_PORTFORMATTYPE format;
+        format.nPortIndex = kPortIndexOutput;
+        format.nIndex = 0;
+        status_t err = OMX_ErrorNone;
+        while (OMX_ErrorNone == err) {
+            CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat,
+                    &format, sizeof(format)), OK);
+            if (format.eEncoding == OMX_AUDIO_CodingAAC) {
+                break;
+            }
+            format.nIndex++;
+        }
+        CHECK_EQ(OK, err);
+        CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
+                &format, sizeof(format)), OK);
+
+        // port definition
+        OMX_PARAM_PORTDEFINITIONTYPE def;
+        InitOMXParams(&def);
+        def.nPortIndex = kPortIndexOutput;
+        CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
+                &def, sizeof(def)), OK);
+        def.format.audio.bFlagErrorConcealment = OMX_TRUE;
+        def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+        CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
+                &def, sizeof(def)), OK);
+
+        // profile
+        OMX_AUDIO_PARAM_AACPROFILETYPE profile;
+        InitOMXParams(&profile);
+        profile.nPortIndex = kPortIndexOutput;
+        CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
+                &profile, sizeof(profile)), OK);
+        profile.nChannels = numChannels;
+        profile.eChannelMode = (numChannels == 1?
+                OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
+        profile.nSampleRate = sampleRate;
+        profile.nBitRate = bitRate;
+        profile.nAudioBandWidth = 0;
+        profile.nFrameLength = 0;
+        profile.nAACtools = OMX_AUDIO_AACToolAll;
+        profile.nAACERtools = OMX_AUDIO_AACERNone;
+        profile.eAACProfile = OMX_AUDIO_AACObjectLC;
+        profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
+        CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
+                &profile, sizeof(profile)), OK);
+
     } else {
         OMX_AUDIO_PARAM_AACPROFILETYPE profile;
         InitOMXParams(&profile);
@@ -2328,7 +2702,7 @@
     mCodecSpecificDataIndex = 0;
 }
 
-status_t OMXCodec::start(MetaData *) {
+status_t OMXCodec::start(MetaData *meta) {
     Mutex::Autolock autoLock(mLock);
 
     if (mState != LOADED) {
@@ -2339,6 +2713,14 @@
     if (mQuirks & kWantsNALFragments) {
         params->setInt32(kKeyWantsNALFragments, true);
     }
+    if (meta) {
+        int64_t startTimeUs = 0;
+        int64_t timeUs;
+        if (meta->findInt64(kKeyTime, &timeUs)) {
+            startTimeUs = timeUs;
+        }
+        params->setInt64(kKeyTime, startTimeUs);
+    }
     status_t err = mSource->start(params.get());
 
     if (err != OK) {
@@ -2351,7 +2733,10 @@
     mNoMoreOutputData = false;
     mOutputPortSettingsHaveChanged = false;
     mSeekTimeUs = -1;
+    mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
+    mTargetTimeUs = -1;
     mFilledBuffers.clear();
+    mPaused = false;
 
     return init();
 }
@@ -2444,9 +2829,16 @@
 
     bool seeking = false;
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode seekMode;
+    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
         seeking = true;
     }
+    int64_t skipTimeUs;
+    if (options && options->getSkipFrame(&skipTimeUs)) {
+        mSkipTimeUs = skipTimeUs;
+    } else {
+        mSkipTimeUs = -1;
+    }
 
     if (mInitialBufferSubmit) {
         mInitialBufferSubmit = false;
@@ -2454,10 +2846,12 @@
         if (seeking) {
             CHECK(seekTimeUs >= 0);
             mSeekTimeUs = seekTimeUs;
+            mSeekMode = seekMode;
 
             // There's no reason to trigger the code below, there's
             // nothing to flush yet.
             seeking = false;
+            mPaused = false;
         }
 
         drainInputBuffers();
@@ -2476,6 +2870,7 @@
 
         CHECK(seekTimeUs >= 0);
         mSeekTimeUs = seekTimeUs;
+        mSeekMode = seekMode;
 
         mFilledBuffers.clear();
 
@@ -2870,6 +3265,12 @@
 void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
     mOutputFormat = new MetaData;
     mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
+    if (mIsEncoder) {
+        int32_t timeScale;
+        if (inputFormat->findInt32(kKeyTimeScale, &timeScale)) {
+            mOutputFormat->setInt32(kKeyTimeScale, timeScale);
+        }
+    }
 
     OMX_PARAM_PORTDEFINITIONTYPE def;
     InitOMXParams(&def);
@@ -2962,6 +3363,13 @@
             } else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
                 mOutputFormat->setCString(
                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+                int32_t numChannels, sampleRate, bitRate;
+                inputFormat->findInt32(kKeyChannelCount, &numChannels);
+                inputFormat->findInt32(kKeySampleRate, &sampleRate);
+                inputFormat->findInt32(kKeyBitRate, &bitRate);
+                mOutputFormat->setInt32(kKeyChannelCount, numChannels);
+                mOutputFormat->setInt32(kKeySampleRate, sampleRate);
+                mOutputFormat->setInt32(kKeyBitRate, bitRate);
             } else {
                 CHECK(!"Should not be here. Unknown audio encoding.");
             }
@@ -3011,6 +3419,14 @@
     }
 }
 
+status_t OMXCodec::pause() {
+    Mutex::Autolock autoLock(mLock);
+
+    mPaused = true;
+
+    return OK;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 status_t QueryCodecs(
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index d0d1b14..c267a23 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -76,7 +76,9 @@
     status_t seekToOffset(off_t offset);
     status_t readNextPacket(MediaBuffer **buffer);
 
-    void init();
+    status_t init();
+
+    sp<MetaData> getFileMetaData() { return mFileMeta; }
 
 private:
     struct Page {
@@ -100,13 +102,17 @@
     vorbis_comment mVc;
 
     sp<MetaData> mMeta;
+    sp<MetaData> mFileMeta;
 
     ssize_t readPage(off_t offset, Page *page);
     status_t findNextPage(off_t startOffset, off_t *pageOffset);
 
-    void verifyHeader(
+    status_t verifyHeader(
             MediaBuffer *buffer, uint8_t type);
 
+    void parseFileMetaData();
+    void extractAlbumArt(const void *data, size_t size);
+
     MyVorbisExtractor(const MyVorbisExtractor &);
     MyVorbisExtractor &operator=(const MyVorbisExtractor &);
 };
@@ -149,7 +155,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll;
         LOGI("seeking to offset %ld", pos);
 
@@ -188,9 +195,14 @@
       mNextLaceIndex(0),
       mFirstDataOffset(-1) {
     mCurrentPage.mNumSegments = 0;
+
+    vorbis_info_init(&mVi);
+    vorbis_comment_init(&mVc);
 }
 
 MyVorbisExtractor::~MyVorbisExtractor() {
+    vorbis_comment_clear(&mVc);
+    vorbis_info_clear(&mVi);
 }
 
 sp<MetaData> MyVorbisExtractor::getFormat() const {
@@ -297,6 +309,7 @@
         totalSize += page->mLace[i];
     }
 
+#if 0
     String8 tmp;
     for (size_t i = 0; i < page->mNumSegments; ++i) {
         char x[32];
@@ -306,6 +319,7 @@
     }
 
     LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
+#endif
 
     return sizeof(header) + page->mNumSegments + totalSize;
 }
@@ -421,47 +435,60 @@
     }
 }
 
-void MyVorbisExtractor::init() {
-    vorbis_info_init(&mVi);
-
-    vorbis_comment mVc;
-
+status_t MyVorbisExtractor::init() {
     mMeta = new MetaData;
     mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
 
     MediaBuffer *packet;
-    CHECK_EQ(readNextPacket(&packet), OK);
+    status_t err;
+    if ((err = readNextPacket(&packet)) != OK) {
+        return err;
+    }
     LOGV("read packet of size %d\n", packet->range_length());
-    verifyHeader(packet, 1);
+    err = verifyHeader(packet, 1);
     packet->release();
     packet = NULL;
+    if (err != OK) {
+        return err;
+    }
 
-    CHECK_EQ(readNextPacket(&packet), OK);
+    if ((err = readNextPacket(&packet)) != OK) {
+        return err;
+    }
     LOGV("read packet of size %d\n", packet->range_length());
-    verifyHeader(packet, 3);
+    err = verifyHeader(packet, 3);
     packet->release();
     packet = NULL;
+    if (err != OK) {
+        return err;
+    }
 
-    CHECK_EQ(readNextPacket(&packet), OK);
+    if ((err = readNextPacket(&packet)) != OK) {
+        return err;
+    }
     LOGV("read packet of size %d\n", packet->range_length());
-    verifyHeader(packet, 5);
+    err = verifyHeader(packet, 5);
     packet->release();
     packet = NULL;
+    if (err != OK) {
+        return err;
+    }
 
     mFirstDataOffset = mOffset + mCurrentPageSize;
+
+    return OK;
 }
 
-void MyVorbisExtractor::verifyHeader(
+status_t MyVorbisExtractor::verifyHeader(
         MediaBuffer *buffer, uint8_t type) {
     const uint8_t *data =
         (const uint8_t *)buffer->data() + buffer->range_offset();
 
     size_t size = buffer->range_length();
 
-    CHECK(size >= 7);
-
-    CHECK_EQ(data[0], type);
-    CHECK(!memcmp(&data[1], "vorbis", 6));
+    if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
+        return ERROR_MALFORMED;
+    }
 
     ogg_buffer buf;
     buf.data = (uint8_t *)data;
@@ -508,18 +535,26 @@
 
         case 3:
         {
-            CHECK_EQ(0, _vorbis_unpack_comment(&mVc, &bits));
+            if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
+                return ERROR_MALFORMED;
+            }
+
+            parseFileMetaData();
             break;
         }
 
         case 5:
         {
-            CHECK_EQ(0, _vorbis_unpack_books(&mVi, &bits));
+            if (0 != _vorbis_unpack_books(&mVi, &bits)) {
+                return ERROR_MALFORMED;
+            }
 
             mMeta->setData(kKeyVorbisBooks, 0, data, size);
             break;
         }
     }
+
+    return OK;
 }
 
 uint64_t MyVorbisExtractor::approxBitrate() {
@@ -530,6 +565,192 @@
     return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
 }
 
+void MyVorbisExtractor::parseFileMetaData() {
+    mFileMeta = new MetaData;
+    mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
+
+    struct {
+        const char *const mTag;
+        uint32_t mKey;
+    } kMap[] = {
+        { "TITLE", kKeyTitle },
+        { "ARTIST", kKeyArtist },
+        { "ALBUM", kKeyAlbum },
+        { "COMPOSER", kKeyComposer },
+        { "GENRE", kKeyGenre },
+        { "AUTHOR", kKeyAuthor },
+        { "TRACKNUMBER", kKeyCDTrackNumber },
+        { "DISCNUMBER", kKeyDiscNumber },
+        { "DATE", kKeyDate },
+        { "LYRICIST", kKeyWriter },
+        { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
+    };
+
+    for (int i = 0; i < mVc.comments; ++i) {
+        const char *comment = mVc.user_comments[i];
+
+        for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
+            size_t tagLen = strlen(kMap[j].mTag);
+            if (!strncasecmp(kMap[j].mTag, comment, tagLen)
+                    && comment[tagLen] == '=') {
+                if (kMap[j].mKey == kKeyAlbumArt) {
+                    extractAlbumArt(
+                            &comment[tagLen + 1],
+                            mVc.comment_lengths[i] - tagLen - 1);
+                } else {
+                    mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
+                }
+            }
+        }
+
+    }
+
+#if 0
+    for (int i = 0; i < mVc.comments; ++i) {
+        LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
+    }
+#endif
+}
+
+// The returned buffer should be free()d.
+static uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
+    *outSize = 0;
+
+    if ((size % 4) != 0) {
+        return NULL;
+    }
+
+    size_t n = size;
+    size_t padding = 0;
+    if (n >= 1 && s[n - 1] == '=') {
+        padding = 1;
+
+        if (n >= 2 && s[n - 2] == '=') {
+            padding = 2;
+        }
+    }
+
+    size_t outLen = 3 * size / 4 - padding;
+
+    *outSize = outLen;
+
+    void *buffer = malloc(outLen);
+
+    uint8_t *out = (uint8_t *)buffer;
+    size_t j = 0;
+    uint32_t accum = 0;
+    for (size_t i = 0; i < n; ++i) {
+        char c = s[i];
+        unsigned value;
+        if (c >= 'A' && c <= 'Z') {
+            value = c - 'A';
+        } else if (c >= 'a' && c <= 'z') {
+            value = 26 + c - 'a';
+        } else if (c >= '0' && c <= '9') {
+            value = 52 + c - '0';
+        } else if (c == '+') {
+            value = 62;
+        } else if (c == '/') {
+            value = 63;
+        } else if (c != '=') {
+            return NULL;
+        } else {
+            if (i < n - padding) {
+                return NULL;
+            }
+
+            value = 0;
+        }
+
+        accum = (accum << 6) | value;
+
+        if (((i + 1) % 4) == 0) {
+            out[j++] = (accum >> 16);
+
+            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
+            if (j < outLen) { out[j++] = accum & 0xff; }
+
+            accum = 0;
+        }
+    }
+
+    return (uint8_t *)buffer;
+}
+
+void MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) {
+    LOGV("extractAlbumArt from '%s'", (const char *)data);
+
+    size_t flacSize;
+    uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
+
+    if (flac == NULL) {
+        LOGE("malformed base64 encoded data.");
+        return;
+    }
+
+    LOGV("got flac of size %d", flacSize);
+
+    uint32_t picType;
+    uint32_t typeLen;
+    uint32_t descLen;
+    uint32_t dataLen;
+    char type[128];
+
+    if (flacSize < 8) {
+        goto exit;
+    }
+
+    picType = U32_AT(flac);
+
+    if (picType != 3) {
+        // This is not a front cover.
+        goto exit;
+    }
+
+    typeLen = U32_AT(&flac[4]);
+    if (typeLen + 1 > sizeof(type)) {
+        goto exit;
+    }
+
+    if (flacSize < 8 + typeLen) {
+        goto exit;
+    }
+
+    memcpy(type, &flac[8], typeLen);
+    type[typeLen] = '\0';
+
+    LOGV("picType = %d, type = '%s'", picType, type);
+
+    if (!strcmp(type, "-->")) {
+        // This is not inline cover art, but an external url instead.
+        goto exit;
+    }
+
+    descLen = U32_AT(&flac[8 + typeLen]);
+
+    if (flacSize < 32 + typeLen + descLen) {
+        goto exit;
+    }
+
+    dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
+
+    if (flacSize < 32 + typeLen + descLen + dataLen) {
+        goto exit;
+    }
+
+    LOGV("got image data, %d trailing bytes",
+         flacSize - 32 - typeLen - descLen - dataLen);
+
+    mFileMeta->setData(
+            kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
+
+    mFileMeta->setCString(kKeyAlbumArtMIME, type);
+
+exit:
+    free(flac);
+    flac = NULL;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 OggExtractor::OggExtractor(const sp<DataSource> &source)
@@ -537,10 +758,11 @@
       mInitCheck(NO_INIT),
       mImpl(NULL) {
     mImpl = new MyVorbisExtractor(mDataSource);
-    CHECK_EQ(mImpl->seekToOffset(0), OK);
-    mImpl->init();
+    mInitCheck = mImpl->seekToOffset(0);
 
-    mInitCheck = OK;
+    if (mInitCheck == OK) {
+        mInitCheck = mImpl->init();
+    }
 }
 
 OggExtractor::~OggExtractor() {
@@ -570,15 +792,7 @@
 }
 
 sp<MetaData> OggExtractor::getMetaData() {
-    sp<MetaData> meta = new MetaData;
-
-    if (mInitCheck != OK) {
-        return meta;
-    }
-
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
-
-    return meta;
+    return mImpl->getFileMetaData();
 }
 
 bool SniffOgg(
diff --git a/media/libstagefright/Prefetcher.cpp b/media/libstagefright/Prefetcher.cpp
deleted file mode 100644
index 650a9f9..0000000
--- a/media/libstagefright/Prefetcher.cpp
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Copyright (C) 2010 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_TAG "Prefetcher"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include "include/Prefetcher.h"
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-#include <utils/List.h>
-
-namespace android {
-
-struct PrefetchedSource : public MediaSource {
-    PrefetchedSource(
-            size_t index,
-            const sp<MediaSource> &source);
-
-    virtual status_t start(MetaData *params);
-    virtual status_t stop();
-
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options);
-
-    virtual sp<MetaData> getFormat();
-
-protected:
-    virtual ~PrefetchedSource();
-
-private:
-    friend struct Prefetcher;
-
-    Mutex mLock;
-    Condition mCondition;
-
-    sp<MediaSource> mSource;
-    size_t mIndex;
-    bool mStarted;
-    bool mReachedEOS;
-    status_t mFinalStatus;
-    int64_t mSeekTimeUs;
-    int64_t mCacheDurationUs;
-    size_t mCacheSizeBytes;
-    bool mPrefetcherStopped;
-    bool mCurrentlyPrefetching;
-
-    List<MediaBuffer *> mCachedBuffers;
-
-    // Returns true iff source is currently caching.
-    bool getCacheDurationUs(int64_t *durationUs, size_t *totalSize = NULL);
-
-    void updateCacheDuration_l();
-    void clearCache_l();
-
-    void cacheMore();
-    void onPrefetcherStopped();
-
-    PrefetchedSource(const PrefetchedSource &);
-    PrefetchedSource &operator=(const PrefetchedSource &);
-};
-
-Prefetcher::Prefetcher()
-    : mDone(false),
-      mThreadExited(false) {
-    startThread();
-}
-
-Prefetcher::~Prefetcher() {
-    stopThread();
-}
-
-sp<MediaSource> Prefetcher::addSource(const sp<MediaSource> &source) {
-    Mutex::Autolock autoLock(mLock);
-
-    sp<PrefetchedSource> psource =
-        new PrefetchedSource(mSources.size(), source);
-
-    mSources.add(psource);
-
-    return psource;
-}
-
-void Prefetcher::startThread() {
-    mThreadExited = false;
-    mDone = false;
-
-    int res = androidCreateThreadEtc(
-            ThreadWrapper, this, "Prefetcher",
-            ANDROID_PRIORITY_DEFAULT, 0, &mThread);
-
-    CHECK_EQ(res, 1);
-}
-
-void Prefetcher::stopThread() {
-    Mutex::Autolock autoLock(mLock);
-
-    while (!mThreadExited) {
-        mDone = true;
-        mCondition.signal();
-        mCondition.wait(mLock);
-    }
-}
-
-// static
-int Prefetcher::ThreadWrapper(void *me) {
-    static_cast<Prefetcher *>(me)->threadFunc();
-
-    return 0;
-}
-
-// Cache at most 1 min for each source.
-static int64_t kMaxCacheDurationUs = 60 * 1000000ll;
-
-// At the same time cache at most 5MB per source.
-static size_t kMaxCacheSizeBytes = 5 * 1024 * 1024;
-
-// If the amount of cached data drops below this,
-// fill the cache up to the max duration again.
-static int64_t kLowWaterDurationUs = 5000000ll;
-
-void Prefetcher::threadFunc() {
-    bool fillingCache = false;
-
-    for (;;) {
-        sp<PrefetchedSource> minSource;
-        int64_t minCacheDurationUs = -1;
-
-        {
-            Mutex::Autolock autoLock(mLock);
-            if (mDone) {
-                break;
-            }
-
-            mCondition.waitRelative(
-                    mLock, fillingCache ? 1ll : 1000000000ll);
-
-
-            ssize_t minIndex = -1;
-            for (size_t i = 0; i < mSources.size(); ++i) {
-                sp<PrefetchedSource> source = mSources[i].promote();
-
-                if (source == NULL) {
-                    continue;
-                }
-
-                int64_t cacheDurationUs;
-                size_t cacheSizeBytes;
-                if (!source->getCacheDurationUs(&cacheDurationUs, &cacheSizeBytes)) {
-                    continue;
-                }
-
-                if (cacheSizeBytes > kMaxCacheSizeBytes) {
-                    LOGI("max cache size reached");
-                    continue;
-                }
-
-                if (mSources.size() > 1 && cacheDurationUs >= kMaxCacheDurationUs) {
-                    LOGI("max duration reached, size = %d bytes", cacheSizeBytes);
-                    continue;
-                }
-
-                if (minIndex < 0 || cacheDurationUs < minCacheDurationUs) {
-                    minCacheDurationUs = cacheDurationUs;
-                    minIndex = i;
-                    minSource = source;
-                }
-            }
-
-            if (minIndex < 0) {
-                if (fillingCache) {
-                    LOGV("[%p] done filling the cache, above high water mark.",
-                         this);
-                    fillingCache = false;
-                }
-                continue;
-            }
-        }
-
-        if (!fillingCache && minCacheDurationUs < kLowWaterDurationUs) {
-            LOGI("[%p] cache below low water mark, filling cache.", this);
-            fillingCache = true;
-        }
-
-        if (fillingCache) {
-            // Make sure not to hold the lock while calling into the source.
-            // The lock guards the list of sources, not the individual sources
-            // themselves.
-            minSource->cacheMore();
-        }
-    }
-
-    Mutex::Autolock autoLock(mLock);
-    for (size_t i = 0; i < mSources.size(); ++i) {
-        sp<PrefetchedSource> source = mSources[i].promote();
-
-        if (source == NULL) {
-            continue;
-        }
-
-        source->onPrefetcherStopped();
-    }
-
-    mThreadExited = true;
-    mCondition.signal();
-}
-
-int64_t Prefetcher::getCachedDurationUs(bool *noMoreData) {
-    Mutex::Autolock autoLock(mLock);
-
-    int64_t minCacheDurationUs = -1;
-    ssize_t minIndex = -1;
-    bool anySourceActive = false;
-    for (size_t i = 0; i < mSources.size(); ++i) {
-        int64_t cacheDurationUs;
-        sp<PrefetchedSource> source = mSources[i].promote();
-        if (source == NULL) {
-            continue;
-        }
-
-        if (source->getCacheDurationUs(&cacheDurationUs)) {
-            anySourceActive = true;
-        }
-
-        if (minIndex < 0 || cacheDurationUs < minCacheDurationUs) {
-            minCacheDurationUs = cacheDurationUs;
-            minIndex = i;
-        }
-    }
-
-    if (noMoreData) {
-        *noMoreData = !anySourceActive;
-    }
-
-    return minCacheDurationUs < 0 ? 0 : minCacheDurationUs;
-}
-
-status_t Prefetcher::prepare(
-        bool (*continueFunc)(void *cookie), void *cookie) {
-    // Fill the cache.
-
-    int64_t duration;
-    bool noMoreData;
-    do {
-        usleep(100000);
-
-        if (continueFunc && !(*continueFunc)(cookie)) {
-            return -EINTR;
-        }
-
-        duration = getCachedDurationUs(&noMoreData);
-    } while (!noMoreData && duration < 2000000ll);
-
-    return OK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-PrefetchedSource::PrefetchedSource(
-        size_t index,
-        const sp<MediaSource> &source)
-    : mSource(source),
-      mIndex(index),
-      mStarted(false),
-      mReachedEOS(false),
-      mSeekTimeUs(0),
-      mCacheDurationUs(0),
-      mCacheSizeBytes(0),
-      mPrefetcherStopped(false),
-      mCurrentlyPrefetching(false) {
-}
-
-PrefetchedSource::~PrefetchedSource() {
-    if (mStarted) {
-        stop();
-    }
-}
-
-status_t PrefetchedSource::start(MetaData *params) {
-    CHECK(!mStarted);
-
-    Mutex::Autolock autoLock(mLock);
-
-    status_t err = mSource->start(params);
-
-    if (err != OK) {
-        return err;
-    }
-
-    mStarted = true;
-
-    return OK;
-}
-
-status_t PrefetchedSource::stop() {
-    CHECK(mStarted);
-
-    Mutex::Autolock autoLock(mLock);
-
-    while (mCurrentlyPrefetching) {
-        mCondition.wait(mLock);
-    }
-
-    clearCache_l();
-
-    status_t err = mSource->stop();
-
-    mStarted = false;
-
-    return err;
-}
-
-status_t PrefetchedSource::read(
-        MediaBuffer **out, const ReadOptions *options) {
-    *out = NULL;
-
-    Mutex::Autolock autoLock(mLock);
-
-    CHECK(mStarted);
-
-    int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
-        CHECK(seekTimeUs >= 0);
-
-        clearCache_l();
-
-        mReachedEOS = false;
-        mSeekTimeUs = seekTimeUs;
-    }
-
-    while (!mPrefetcherStopped && !mReachedEOS && mCachedBuffers.empty()) {
-        mCondition.wait(mLock);
-    }
-
-    if (mCachedBuffers.empty()) {
-        return mReachedEOS ? mFinalStatus : ERROR_END_OF_STREAM;
-    }
-
-    *out = *mCachedBuffers.begin();
-    mCachedBuffers.erase(mCachedBuffers.begin());
-    updateCacheDuration_l();
-    mCacheSizeBytes -= (*out)->size();
-
-    return OK;
-}
-
-sp<MetaData> PrefetchedSource::getFormat() {
-    return mSource->getFormat();
-}
-
-bool PrefetchedSource::getCacheDurationUs(
-        int64_t *durationUs, size_t *totalSize) {
-    Mutex::Autolock autoLock(mLock);
-
-    *durationUs = mCacheDurationUs;
-    if (totalSize != NULL) {
-        *totalSize = mCacheSizeBytes;
-    }
-
-    if (!mStarted || mReachedEOS) {
-        return false;
-    }
-
-    return true;
-}
-
-void PrefetchedSource::cacheMore() {
-    MediaSource::ReadOptions options;
-
-    Mutex::Autolock autoLock(mLock);
-
-    if (!mStarted) {
-        return;
-    }
-
-    mCurrentlyPrefetching = true;
-
-    if (mSeekTimeUs >= 0) {
-        options.setSeekTo(mSeekTimeUs);
-        mSeekTimeUs = -1;
-    }
-
-    // Ensure our object does not go away while we're not holding
-    // the lock.
-    sp<PrefetchedSource> me = this;
-
-    mLock.unlock();
-    MediaBuffer *buffer;
-    status_t err = mSource->read(&buffer, &options);
-    mLock.lock();
-
-    if (err != OK) {
-        mCurrentlyPrefetching = false;
-        mReachedEOS = true;
-        mFinalStatus = err;
-        mCondition.signal();
-
-        return;
-    }
-
-    CHECK(buffer != NULL);
-
-    MediaBuffer *copy = new MediaBuffer(buffer->range_length());
-    memcpy(copy->data(),
-           (const uint8_t *)buffer->data() + buffer->range_offset(),
-           buffer->range_length());
-
-    sp<MetaData> from = buffer->meta_data();
-    sp<MetaData> to = copy->meta_data();
-
-    int64_t timeUs;
-    if (from->findInt64(kKeyTime, &timeUs)) {
-        to->setInt64(kKeyTime, timeUs);
-    }
-
-    buffer->release();
-    buffer = NULL;
-
-    mCachedBuffers.push_back(copy);
-    updateCacheDuration_l();
-    mCacheSizeBytes += copy->size();
-
-    mCurrentlyPrefetching = false;
-    mCondition.signal();
-}
-
-void PrefetchedSource::updateCacheDuration_l() {
-    if (mCachedBuffers.size() < 2) {
-        mCacheDurationUs = 0;
-    } else {
-        int64_t firstTimeUs, lastTimeUs;
-        CHECK((*mCachedBuffers.begin())->meta_data()->findInt64(
-                    kKeyTime, &firstTimeUs));
-        CHECK((*--mCachedBuffers.end())->meta_data()->findInt64(
-                    kKeyTime, &lastTimeUs));
-
-        mCacheDurationUs = lastTimeUs - firstTimeUs;
-    }
-}
-
-void PrefetchedSource::clearCache_l() {
-    List<MediaBuffer *>::iterator it = mCachedBuffers.begin();
-    while (it != mCachedBuffers.end()) {
-        (*it)->release();
-
-        it = mCachedBuffers.erase(it);
-    }
-
-    updateCacheDuration_l();
-    mCacheSizeBytes = 0;
-}
-
-void PrefetchedSource::onPrefetcherStopped() {
-    Mutex::Autolock autoLock(mLock);
-    mPrefetcherStopped = true;
-    mCondition.signal();
-}
-
-}  // namespace android
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 89a522e..2e62f9f 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -314,8 +314,10 @@
     return time1 > time2 ? time1 - time2 : time2 - time1;
 }
 
-status_t SampleTable::findClosestSample(
+status_t SampleTable::findSampleAtTime(
         uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
+    *sample_index = 0;
+
     Mutex::Autolock autoLock(mLock);
 
     uint32_t cur_sample = 0;
@@ -330,16 +332,37 @@
             uint32_t time1 = time + j * delta;
             uint32_t time2 = time1 + delta;
 
+            uint32_t sampleTime;
             if (i+1 == mTimeToSampleCount
                     || (abs_difference(req_time, time1)
                         < abs_difference(req_time, time2))) {
                 *sample_index = cur_sample + j;
+                sampleTime = time1;
             } else {
                 *sample_index = cur_sample + j + 1;
+                sampleTime = time2;
             }
 
-            if (flags & kSyncSample_Flag) {
-                return findClosestSyncSample_l(*sample_index, sample_index);
+            switch (flags) {
+                case kFlagBefore:
+                {
+                    if (sampleTime > req_time && *sample_index > 0) {
+                        --*sample_index;
+                    }
+                    break;
+                }
+
+                case kFlagAfter:
+                {
+                    if (sampleTime < req_time
+                            && *sample_index + 1 < mNumSampleSizes) {
+                        ++*sample_index;
+                    }
+                    break;
+                }
+
+                default:
+                    break;
             }
 
             return OK;
@@ -352,8 +375,10 @@
     return ERROR_OUT_OF_RANGE;
 }
 
-status_t SampleTable::findClosestSyncSample_l(
-        uint32_t start_sample_index, uint32_t *sample_index) {
+status_t SampleTable::findSyncSampleNear(
+        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
+    Mutex::Autolock autoLock(mLock);
+
     *sample_index = 0;
 
     if (mSyncSampleOffset < 0) {
@@ -362,29 +387,124 @@
         return OK;
     }
 
-    uint32_t x;
-    uint32_t left = 0;
-    uint32_t right = mNumSyncSamples;
-    while (left < right) {
-        uint32_t mid = (left + right) / 2;
+    if (mNumSyncSamples == 0) {
+        *sample_index = 0;
+        return OK;
+    }
 
+    uint32_t left = 0;
+    while (left < mNumSyncSamples) {
+        uint32_t x;
         if (mDataSource->readAt(
-                    mSyncSampleOffset + 8 + mid * 4, &x, 4) != 4) {
+                    mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
             return ERROR_IO;
         }
 
         x = ntohl(x);
+        --x;
 
-        if (x < (start_sample_index + 1)) {
-            left = mid + 1;
-        } else if (x > (start_sample_index + 1)) {
-            right = mid;
-        } else {
+        if (x >= start_sample_index) {
             break;
         }
+
+        ++left;
+    }
+
+    --left;
+    uint32_t x;
+    if (mDataSource->readAt(
+                mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
+        return ERROR_IO;
+    }
+
+    x = ntohl(x);
+    --x;
+
+    if (left + 1 < mNumSyncSamples) {
+        uint32_t y;
+        if (mDataSource->readAt(
+                    mSyncSampleOffset + 8 + (left + 1) * 4, &y, 4) != 4) {
+            return ERROR_IO;
+        }
+
+        y = ntohl(y);
+        --y;
+
+        // our sample lies between sync samples x and y.
+
+        status_t err = mSampleIterator->seekTo(start_sample_index);
+        if (err != OK) {
+            return err;
+        }
+
+        uint32_t sample_time = mSampleIterator->getSampleTime();
+
+        err = mSampleIterator->seekTo(x);
+        if (err != OK) {
+            return err;
+        }
+        uint32_t x_time = mSampleIterator->getSampleTime();
+
+        err = mSampleIterator->seekTo(y);
+        if (err != OK) {
+            return err;
+        }
+
+        uint32_t y_time = mSampleIterator->getSampleTime();
+
+        if (abs_difference(x_time, sample_time)
+                > abs_difference(y_time, sample_time)) {
+            // Pick the sync sample closest (timewise) to the start-sample.
+            x = y;
+            ++left;
+        }
     }
 
-    *sample_index = x - 1;
+    switch (flags) {
+        case kFlagBefore:
+        {
+            if (x > start_sample_index) {
+                CHECK(left > 0);
+
+                if (mDataSource->readAt(
+                            mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
+                    return ERROR_IO;
+                }
+
+                x = ntohl(x);
+                --x;
+
+                CHECK(x <= start_sample_index);
+            }
+            break;
+        }
+
+        case kFlagAfter:
+        {
+            if (x < start_sample_index) {
+                if (left + 1 >= mNumSyncSamples) {
+                    return ERROR_OUT_OF_RANGE;
+                }
+
+                if (mDataSource->readAt(
+                            mSyncSampleOffset + 8 + (left + 1) * 4, &x, 4) != 4) {
+                    return ERROR_IO;
+                }
+
+                x = ntohl(x);
+                --x;
+
+                CHECK(x >= start_sample_index);
+            }
+
+            break;
+        }
+
+        default:
+            break;
+    }
+
+    *sample_index = x;
 
     return OK;
 }
diff --git a/media/libstagefright/ShoutcastSource.cpp b/media/libstagefright/ShoutcastSource.cpp
index ec25430..23b7681 100644
--- a/media/libstagefright/ShoutcastSource.cpp
+++ b/media/libstagefright/ShoutcastSource.cpp
@@ -93,7 +93,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         return ERROR_UNSUPPORTED;
     }
 
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 03287dd..1629e9f 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -26,10 +26,6 @@
 // Sonivox includes
 #include <libsonivox/eas.h>
 
-// Ogg Vorbis includes
-#include <Tremolo/ivorbiscodec.h>
-#include <Tremolo/ivorbisfile.h>
-
 namespace android {
 
 StagefrightMediaScanner::StagefrightMediaScanner()
@@ -42,7 +38,8 @@
     static const char *kValidExtensions[] = {
         ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
         ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
-        ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota"
+        ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
+        ".mkv", ".mka", ".webm", ".ts"
     };
     static const size_t kNumValidExtensions =
         sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
@@ -102,48 +99,6 @@
     return OK;
 }
 
-static status_t HandleOGG(
-        const char *filename, MediaScannerClient *client) {
-    int duration;
-
-    FILE *file = fopen(filename,"r");
-    if (!file)
-        return UNKNOWN_ERROR;
-
-    OggVorbis_File vf;
-    if (ov_open(file, &vf, NULL, 0) < 0) {
-        return UNKNOWN_ERROR;
-    }
-
-    char **ptr=ov_comment(&vf,-1)->user_comments;
-    while(*ptr){
-        char *val = strstr(*ptr, "=");
-        if (val) {
-            int keylen = val++ - *ptr;
-            char key[keylen + 1];
-            strncpy(key, *ptr, keylen);
-            key[keylen] = 0;
-            if (!client->addStringTag(key, val)) goto failure;
-        }
-        ++ptr;
-    }
-
-    // Duration
-    duration = ov_time_total(&vf, -1);
-    if (duration > 0) {
-        char buffer[20];
-        sprintf(buffer, "%d", duration);
-        if (!client->addStringTag("duration", buffer)) goto failure;
-    }
-
-    ov_clear(&vf); // this also closes the FILE
-    return OK;
-
-failure:
-    ov_clear(&vf); // this also closes the FILE
-    return UNKNOWN_ERROR;
-}
-
 status_t StagefrightMediaScanner::processFile(
         const char *path, const char *mimeType,
         MediaScannerClient &client) {
@@ -175,10 +130,6 @@
         return HandleMIDI(path, &client);
     }
 
-    if (!strcasecmp(extension, ".ogg")) {
-        return HandleOGG(path, &client);
-    }
-
     if (mRetriever->setDataSource(path) == OK
             && mRetriever->setMode(
                 METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) {
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 258be74..9d89c20 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -378,6 +378,24 @@
     // The duration value is a string representing the duration in ms.
     sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
     mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
+
+    if (numTracks == 1) {
+        const char *fileMIME;
+        CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
+
+        if (!strcasecmp(fileMIME, "video/x-matroska")) {
+            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
+            const char *trackMIME;
+            CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
+
+            if (!strncasecmp("audio/", trackMIME, 6)) {
+                // The matroska file only contains a single audio track,
+                // rewrite its mime type.
+                mMetaData.add(
+                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
+            }
+        }
+    }
 }
 
 
diff --git a/media/libstagefright/ThrottledSource.cpp b/media/libstagefright/ThrottledSource.cpp
new file mode 100644
index 0000000..4711f7c
--- /dev/null
+++ b/media/libstagefright/ThrottledSource.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "include/ThrottledSource.h"
+
+#include <media/stagefright/MediaDebug.h>
+
+namespace android {
+
+static int64_t getNowUs() {
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+
+    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
+}
+
+ThrottledSource::ThrottledSource(
+        const sp<DataSource> &source,
+        int32_t bandwidthLimitBytesPerSecond)
+    : mSource(source),
+      mBandwidthLimitBytesPerSecond(bandwidthLimitBytesPerSecond),
+      mStartTimeUs(-1),
+      mTotalTransferred(0) {
+    CHECK(mBandwidthLimitBytesPerSecond > 0);
+}
+
+status_t ThrottledSource::initCheck() const {
+    return mSource->initCheck();
+}
+
+ssize_t ThrottledSource::readAt(off_t offset, void *data, size_t size) {
+    Mutex::Autolock autoLock(mLock);
+
+    ssize_t n = mSource->readAt(offset, data, size);
+
+    if (n <= 0) {
+        return n;
+    }
+
+    mTotalTransferred += n;
+
+    int64_t nowUs = getNowUs();
+
+    if (mStartTimeUs < 0) {
+        mStartTimeUs = nowUs;
+    }
+
+    // How long would it have taken to transfer everything we ever
+    // transferred given the limited bandwidth.
+    int64_t durationUs =
+        mTotalTransferred * 1000000ll / mBandwidthLimitBytesPerSecond;
+
+    int64_t whenUs = mStartTimeUs + durationUs;
+
+    if (whenUs > nowUs) {
+        usleep(whenUs - nowUs);
+    }
+
+    return n;
+}
+
+status_t ThrottledSource::getSize(off_t *size) {
+    return mSource->getSize(size);
+}
+
+uint32_t ThrottledSource::flags() {
+    return mSource->flags();
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 7365dfa..7c2b07e 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -282,7 +282,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options != NULL && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
         int64_t pos = (seekTimeUs * mSampleRate) / 1000000 * mNumChannels * 2;
         if (pos > mSize) {
             pos = mSize;
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index 8ae1135..c5b51c0 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -159,7 +159,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         CHECK(seekTimeUs >= 0);
 
         mNumSamplesOutput = 0;
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
new file mode 100644
index 0000000..052c354
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2010 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 "AACEncoder"
+#include <utils/Log.h>
+
+#include "AACEncoder.h"
+#include "voAAC.h"
+#include "cmnMemory.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+AACEncoder::AACEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
+    : mSource(source),
+      mMeta(meta),
+      mStarted(false),
+      mBufferGroup(NULL),
+      mInputBuffer(NULL),
+      mEncoderHandle(NULL),
+      mApiHandle(NULL),
+      mMemOperator(NULL) {
+}
+
+status_t AACEncoder::initCheck() {
+    CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
+    CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
+    CHECK(mMeta->findInt32(kKeyChannelCount, &mChannels));
+    CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
+
+    mApiHandle = new VO_AUDIO_CODECAPI;
+    CHECK(mApiHandle);
+
+    if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
+        LOGE("Failed to get api handle");
+        return UNKNOWN_ERROR;
+    }
+
+    mMemOperator = new VO_MEM_OPERATOR;
+    CHECK(mMemOperator != NULL);
+    mMemOperator->Alloc = cmnMemAlloc;
+    mMemOperator->Copy = cmnMemCopy;
+    mMemOperator->Free = cmnMemFree;
+    mMemOperator->Set = cmnMemSet;
+    mMemOperator->Check = cmnMemCheck;
+
+    VO_CODEC_INIT_USERDATA userData;
+    memset(&userData, 0, sizeof(userData));
+    userData.memflag = VO_IMF_USERMEMOPERATOR;
+    userData.memData = (VO_PTR) mMemOperator;
+    if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) {
+        LOGE("Failed to init AAC encoder");
+        return UNKNOWN_ERROR;
+    }
+    if (OK != setAudioSpecificConfigData()) {
+        LOGE("Failed to configure AAC encoder");
+        return UNKNOWN_ERROR;
+    }
+
+    // Configure AAC encoder$
+    AACENC_PARAM params;
+    memset(&params, 0, sizeof(params));
+    params.sampleRate = mSampleRate;
+    params.bitRate = mBitRate;
+    params.nChannels = mChannels;
+    params.adtsUsed = 0;  // For MP4 file, don't use adts format$
+    if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AAC_ENCPARAM,  &params)) {
+        LOGE("Failed to set AAC encoder parameters");
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+static status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) {
+    static const int32_t kSampleRateTable[] = {
+        96000, 88200, 64000, 48000, 44100, 32000,
+        24000, 22050, 16000, 12000, 11025, 8000
+    };
+    const int32_t tableSize = sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
+    for (int32_t i = 0; i < tableSize; ++i) {
+        if (sampleRate == kSampleRateTable[i]) {
+            index = i;
+            return OK;
+        }
+    }
+
+    LOGE("Sampling rate %d bps is not supported", sampleRate);
+    return UNKNOWN_ERROR;
+}
+
+status_t AACEncoder::setAudioSpecificConfigData() {
+    LOGV("setAudioSpecificConfigData: %d hz, %d bps, and %d channels",
+         mSampleRate, mBitRate, mChannels);
+
+    int32_t index;
+    CHECK_EQ(OK, getSampleRateTableIndex(mSampleRate, index));
+    if (mChannels > 2 || mChannels <= 0) {
+        LOGE("Unsupported number of channels(%d)", mChannels);
+        return UNKNOWN_ERROR;
+    }
+
+    // OMX_AUDIO_AACObjectLC
+    mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
+    mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mChannels << 3);
+    return OK;
+}
+
+AACEncoder::~AACEncoder() {
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t AACEncoder::start(MetaData *params) {
+    if (mStarted) {
+        LOGW("Call start() when encoder already started");
+        return OK;
+    }
+
+    mBufferGroup = new MediaBufferGroup;
+    mBufferGroup->add_buffer(new MediaBuffer(2048));
+
+    CHECK_EQ(OK, initCheck());
+
+    mNumInputSamples = 0;
+    mAnchorTimeUs = 0;
+    mFrameCount = 0;
+    mSource->start(params);
+
+    mStarted = true;
+
+    return OK;
+}
+
+status_t AACEncoder::stop() {
+    if (!mStarted) {
+        LOGW("Call stop() when encoder has not started");
+        return OK;
+    }
+
+    if (mInputBuffer) {
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    delete mBufferGroup;
+    mBufferGroup = NULL;
+
+    mSource->stop();
+
+    if (mEncoderHandle) {
+        CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
+        mEncoderHandle = NULL;
+    }
+    delete mApiHandle;
+    mApiHandle = NULL;
+
+    mStarted = false;
+
+    return OK;
+}
+
+sp<MetaData> AACEncoder::getFormat() {
+    sp<MetaData> srcFormat = mSource->getFormat();
+
+    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        mMeta->setInt64(kKeyDuration, durationUs);
+    }
+
+    mMeta->setCString(kKeyDecoderComponent, "AACEncoder");
+
+    return mMeta;
+}
+
+status_t AACEncoder::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    status_t err;
+
+    *out = NULL;
+
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode mode;
+    CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
+
+    MediaBuffer *buffer;
+    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
+    uint8_t *outPtr = (uint8_t *)buffer->data();
+
+    if (mFrameCount == 0) {
+        memcpy(outPtr, mAudioSpecificConfigData, 2);
+        buffer->set_range(0, 2);
+        buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
+        *out = buffer;
+        ++mFrameCount;
+        return OK;
+    } else if (mFrameCount == 1) {
+        buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
+    }
+
+    while (mNumInputSamples < kNumSamplesPerFrame) {
+        if (mInputBuffer == NULL) {
+            if (mSource->read(&mInputBuffer, options) != OK) {
+                if (mNumInputSamples == 0) {
+                    buffer->release();
+                    return ERROR_END_OF_STREAM;
+                }
+                memset(&mInputFrame[mNumInputSamples],
+                       0,
+                       sizeof(int16_t) * (kNumSamplesPerFrame - mNumInputSamples));
+                mNumInputSamples = 0;
+                break;
+            }
+
+            size_t align = mInputBuffer->range_length() % sizeof(int16_t);
+            CHECK_EQ(align, 0);
+
+            int64_t timeUs;
+            if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+                mAnchorTimeUs = timeUs;
+            }
+        }
+        size_t copy =
+            (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
+
+        if (copy > mInputBuffer->range_length()) {
+            copy = mInputBuffer->range_length();
+        }
+
+        memcpy(&mInputFrame[mNumInputSamples],
+               (const uint8_t *) mInputBuffer->data()
+                    + mInputBuffer->range_offset(),
+               copy);
+
+        mInputBuffer->set_range(
+               mInputBuffer->range_offset() + copy,
+               mInputBuffer->range_length() - copy);
+
+        if (mInputBuffer->range_length() == 0) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+        }
+        mNumInputSamples += copy / sizeof(int16_t);
+        if (mNumInputSamples >= kNumSamplesPerFrame) {
+            mNumInputSamples %= kNumSamplesPerFrame;
+            break;
+        }
+    }
+
+    VO_CODECBUFFER inputData;
+    memset(&inputData, 0, sizeof(inputData));
+    inputData.Buffer = (unsigned char*) mInputFrame;
+    inputData.Length = kNumSamplesPerFrame * sizeof(int16_t);
+    CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
+
+    VO_CODECBUFFER outputData;
+    memset(&outputData, 0, sizeof(outputData));
+    VO_AUDIO_OUTPUTINFO outputInfo;
+    memset(&outputInfo, 0, sizeof(outputInfo));
+
+    VO_U32 ret = VO_ERR_NONE;
+    outputData.Buffer = outPtr;
+    outputData.Length = buffer->size();
+    ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
+    CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
+    CHECK(outputData.Length != 0);
+    buffer->set_range(0, outputData.Length);
+
+    int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
+    ++mFrameCount;
+    buffer->meta_data()->setInt64(kKeyTime, timestampUs);
+
+    *out = buffer;
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk
new file mode 100644
index 0000000..cda4f9d
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/Android.mk
@@ -0,0 +1,87 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES := basic_op/basicop2.c basic_op/oper_32b.c
+
+LOCAL_SRC_FILES += \
+	AACEncoder.cpp \
+	src/aac_rom.c \
+	src/aacenc.c \
+	src/aacenc_core.c \
+	src/adj_thr.c \
+	src/band_nrg.c \
+	src/bit_cnt.c \
+	src/bitbuffer.c \
+	src/bitenc.c \
+	src/block_switch.c \
+	src/channel_map.c \
+	src/dyn_bits.c \
+	src/grp_data.c \
+	src/interface.c \
+	src/line_pe.c \
+	src/ms_stereo.c \
+	src/pre_echo_control.c \
+	src/psy_configuration.c \
+	src/psy_main.c \
+	src/qc_main.c \
+	src/quantize.c \
+	src/sf_estim.c \
+	src/spreading.c \
+	src/stat_bits.c \
+	src/tns.c \
+	src/transform.c \
+	src/memalign.c
+
+ifeq ($(VOTT), v5)
+LOCAL_SRC_FILES += \
+	src/asm/ARMV5E/AutoCorrelation_v5.s \
+	src/asm/ARMV5E/band_nrg_v5.s \
+	src/asm/ARMV5E/CalcWindowEnergy_v5.s \
+	src/asm/ARMV5E/PrePostMDCT_v5.s \
+	src/asm/ARMV5E/R4R8First_v5.s \
+	src/asm/ARMV5E/Radix4FFT_v5.s
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_SRC_FILES += \
+	src/asm/ARMV5E/AutoCorrelation_v5.s \
+	src/asm/ARMV5E/band_nrg_v5.s \
+	src/asm/ARMV5E/CalcWindowEnergy_v5.s \
+	src/asm/ARMV7/PrePostMDCT_v7.s \
+	src/asm/ARMV7/R4R8First_v7.s \
+	src/asm/ARMV7/Radix4FFT_v7.s
+endif
+
+LOCAL_MODULE := libstagefright_aacenc
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES := 
+
+LOCAL_SHARED_LIBRARIES :=
+
+LOCAL_C_INCLUDES := \
+	frameworks/base/media/libstagefright/include \
+	frameworks/base/media/libstagefright/codecs/common/include \
+	frameworks/base/include \
+	$(LOCAL_PATH)/src \
+	$(LOCAL_PATH)/inc \
+	$(LOCAL_PATH)/basic_op
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+ifeq ($(VOTT), v5)
+LOCAL_CFLAGS += -DARMV5E -DARM_INASM -DARMV5_INASM
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_CFLAGS += -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
new file mode 100644
index 0000000..64d012d
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
@@ -0,0 +1,283 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		AAC_E_SAMPLES.h

+

+	Content:	sample code for AAC encoder

+

+*******************************************************************************/

+

+#include		<dlfcn.h>

+#include		<stdio.h>

+#include		<stdlib.h>

+#include		<string.h>

+#include		<time.h>

+#include		"voAAC.h"

+#include		"cmnMemory.h"

+

+#define  VO_AAC_E_OUTPUT	  1

+#define READ_SIZE	(1024*8)	

+unsigned char outBuf[1024*8];

+unsigned char inBuf[READ_SIZE];

+

+const char* HelpString = 

+"VisualOn AAC encoder Usage:\n"

+"voAACEncTest -if <inputfile.pcm> -of <outputfile.aac> -sr <samplerate> -ch <channel> -br <bitrate> -adts <adts> \n"

+"-if input file name \n"

+"-of output file name \n"

+"-sr input pcm samplerate, default 44100 \n"

+"-ch input pcm channel, default 2 channel \n"

+"-br encoded aac bitrate, default 64000 * (samplerate/100)*channel/441(480)\n"

+"-adts add or no adts header, default add adts header\n"

+"For example: \n"

+"./voAACEncTest -if raw.pcm -of raw.aac -sr 44100 -ch 2 -br 128000\n";

+

+static int parsecmdline(int argc, char **argv,char  **input_filename, char  **output_filename, AACENC_PARAM *param)

+{

+	// notice that:

+	// bitRate/nChannels > 8000

+	// bitRate/nChannels < 160000 

+	// bitRate/nChannels < sampleRate*6

+	param->adtsUsed = 1;

+	param->bitRate = 0;

+	param->nChannels = 2;

+	param->sampleRate = 44100;

+

+	if(argc < 5 || argc > 13)

+	{

+		return -1;

+	}

+

+	argc--;

+	argv++;

+	while (argc > 0)

+	{

+		if (!strcmp(*argv, "-if"))

+		{

+			argv++;

+			argc--;

+			*input_filename = *argv; 

+		}

+		else if (!strcmp(*argv, "-of"))

+		{

+			argv++;

+			argc--;

+			*output_filename = *argv;

+		}

+		else if (!strcmp(*argv, "-sr"))

+		{

+			argv++;

+			argc--;

+			param->sampleRate = atoi(*argv);

+		}

+		else if (!strcmp(*argv, "-ch"))

+		{

+			argv++;

+			argc--;

+			param->nChannels = atoi(*argv);

+		}

+		else if (!strcmp(*argv, "-br"))

+		{

+			argv++;

+			argc--;

+			param->bitRate = atoi(*argv);

+		}

+		else if(!strcmp(*argv, "-adts"))

+		{

+			argv++;

+			argc--;

+			param->adtsUsed = atoi(*argv);

+		}

+		else

+		{

+			return -1;

+		}

+

+		argv++;

+		argc--;

+	}

+

+	if(param->bitRate == 0)

+	{

+		int scale = 441;

+		if(param->sampleRate%8000 == 0)

+			scale = 480;

+		param->bitRate = 640*param->nChannels*param->sampleRate/scale;

+	}

+

+	return 0;

+}

+

+int ReadFile2Buf(FILE* infile,unsigned char* dest,int readSize)

+{

+	int readBytes = 0;

+	readBytes = fread(dest, 1, readSize, infile);

+	return readBytes;

+}

+

+typedef int (VO_API * VOGETAUDIODECAPI) (VO_AUDIO_CODECAPI * pDecHandle);

+

+int main(int argc, char **argv)

+{

+	FILE						*infile, *outfile;

+	int							t1, t2;

+	VO_AUDIO_CODECAPI			AudioAPI;

+	VO_MEM_OPERATOR				moper;

+	VO_CODEC_INIT_USERDATA		useData;

+	VO_HANDLE					hCodec;

+	VO_CODECBUFFER				inData;

+	VO_CODECBUFFER				outData;

+	VO_AUDIO_OUTPUTINFO			outInfo;

+    int							firstWrite = 1;

+	int							eofFile = 0;

+	int							*info=(int*)inBuf;

+	int							bytesLeft, nRead;

+	int							EncoderdFrame = 0;

+	int							total = 0;

+	int							isOutput = 1;

+	int							returnCode;

+	AACENC_PARAM				aacpara;

+	void						*handle;

+	void						*pfunc;

+	VOGETAUDIODECAPI			pGetAPI;

+	const char					*infileName = NULL;

+    const char					*outfileName = NULL;

+

+	returnCode = parsecmdline(argc,argv, &infileName, &outfileName, &aacpara);

+	if(returnCode)

+	{

+		printf("%s", HelpString);

+		return 0;

+	}

+

+	/* open input file */

+	infile = fopen(infileName, "rb");

+	if (!infile) {

+		printf("Open input file fail...");

+		return -1;

+	}

+

+	/* open output file */

+	if(isOutput)

+	{

+		outfile = fopen(outfileName, "wb"); 

+		if (!outfile) {

+			printf("Open output file fail...");

+			return -1;

+		}

+	}

+	// set memory operators;

+	moper.Alloc = cmnMemAlloc;

+	moper.Copy = cmnMemCopy;

+	moper.Free = cmnMemFree;

+	moper.Set = cmnMemSet;

+	moper.Check = cmnMemCheck;

+	useData.memflag = VO_IMF_USERMEMOPERATOR;

+	useData.memData = (VO_PTR)(&moper);

+	// open encoder dll;

+	handle = dlopen("/data/local/tmp/libvoAACEncv7.so", RTLD_NOW);

+	if(handle == 0)

+	{

+		printf("open dll error......");

+		return -1;

+	}

+	// Get API;

+	pfunc = dlsym(handle, "voGetAACEncAPI");	

+	if(pfunc == 0)

+	{

+		printf("open function error......");

+		return -1;

+	}

+	pGetAPI = (VOGETAUDIODECAPI)pfunc;

+	returnCode  = pGetAPI(&AudioAPI);

+	if(returnCode)

+		return -1;

+

+

+//#######################################   Init Encoding Section   #########################################

+	returnCode = AudioAPI.Init(&hCodec, VO_AUDIO_CodingAAC, &useData);

+	if(returnCode < 0)

+	{

+		printf("#### VOI_Error2:fail to initialize the Encoderr###\n");

+		return -1;

+	}

+

+	returnCode = AudioAPI.SetParam(hCodec, VO_PID_AAC_ENCPARAM, &aacpara);	

+	

+	inData.Buffer = inBuf;

+	bytesLeft = ReadFile2Buf(infile,inData.Buffer,READ_SIZE);

+

+//#######################################    Encoding Section   #########################################

+	

+	do {

+

+		inData.Length    = bytesLeft;

+		outData.Buffer   = outBuf;

+		outData.Length = 1024*8;

+

+		t1 = clock();

+		

+		returnCode = AudioAPI.SetInputData(hCodec,&inData);

+		

+		do {

+			outData.Buffer   = outBuf;

+			outData.Length = 1024*8;

+

+			returnCode = AudioAPI.GetOutputData(hCodec,&outData, &outInfo);

+

+			if(returnCode == 0)

+				EncoderdFrame++;

+			if(returnCode == VO_ERR_LICENSE_ERROR)

+				break;

+

+#if VO_AAC_E_OUTPUT

+			if (isOutput && returnCode == 0)

+			{

+				fwrite(outData.Buffer, 1, outData.Length, outfile);

+			}

+#endif

+		} while(returnCode != (VO_ERR_INPUT_BUFFER_SMALL));

+

+		if(returnCode == VO_ERR_LICENSE_ERROR)

+			break;

+

+		t2 = clock();

+		total += t2 - t1;

+

+		if (!eofFile) {

+			nRead = ReadFile2Buf(infile, inBuf,READ_SIZE);

+			bytesLeft = nRead;

+			inData.Buffer = inBuf;

+			if (feof(infile))

+				eofFile = 1;

+		}

+

+	} while (!eofFile && returnCode);

+

+

+//################################################  End Encoding Section  #######################################################

+	returnCode = AudioAPI.Uninit(hCodec);

+

+	fclose(infile);

+	if (outfile)

+    {

+        fclose(outfile);

+    }

+	dlclose(handle);

+	return 0;

+}

+

+

diff --git a/media/libstagefright/codecs/aacenc/SampleCode/Android.mk b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
new file mode 100644
index 0000000..52c9c07
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := 	AAC_E_SAMPLES.c
+	
+LOCAL_SRC_FILES += 	\
+	../../../Common/cmnMemory.c 
+
+LOCAL_MODULE := TestvoAACEnc
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES := 
+
+LOCAL_SHARED_LIBRARIES := libvoAACEnc
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/ \
+	$(LOCAL_PATH)/../../../Common \
+	$(LOCAL_PATH)/../../../Include \
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+	
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile
new file mode 100644
index 0000000..22c5dc1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile
@@ -0,0 +1,55 @@
+#/*

+#** Copyright 2003-2010, VisualOn, Inc.

+#**

+#** 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.

+#*/

+

+# target6

+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

+VOTT:= v7

+

+

+# module type

+# please specify the type of your module: lib or exe

+VOMT:= exe

+

+

+# module macros

+# please append the additional macro definitions here for your module if necessary. 

+# e.g. -DVISUALON, macro VISUALON defined for your module 

+VOMM:= #ARMV5E

+

+

+

+# please specify the name of your module

+VOTARGET:= voAACEncTestv7

+

+

+# please modify here to be sure to see the g1.mk

+include ../../../../Tools/eclair.mk 

+

+# dependent libraries.

+VODEPLIBS:=-ldl

+

+# module source

+# please modify here to be sure to see the ms.mk which specifies all source info of your module

+include ../ms.mk

+

+

+# please specify where is the voRelease on your PC, relative path is suggested

+VORELDIR:=../../../../../Release/

+

+

+# please modify here to be sure to see the doit.mk

+include ../../../../Tools/doit.mk 

+

diff --git a/media/libstagefright/codecs/aacenc/SampleCode/ms.mk b/media/libstagefright/codecs/aacenc/SampleCode/ms.mk
new file mode 100644
index 0000000..771a569
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/ms.mk
@@ -0,0 +1,23 @@
+#/*

+#** Copyright 2003-2010, VisualOn, Inc.

+#**

+#** 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.

+#*/

+

+# please list all objects needed by your target here

+OBJS:=AAC_E_SAMPLES.o	cmnMemory.o

+			

+# please list all directories that all source files relative with your module(.h .c .cpp) locate 

+VOSRCDIR:=../ ../../../../include  ../../../../Common

+					

+				

diff --git a/media/libstagefright/codecs/aacenc/Tools/doit.mk b/media/libstagefright/codecs/aacenc/Tools/doit.mk
new file mode 100644
index 0000000..dea0b0a
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/Tools/doit.mk
@@ -0,0 +1,133 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** 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.
+# */
+
+VERBOSE:=@
+
+
+VOMT ?= lib
+
+ifeq ($(VOMT), lib)
+LIB_STATIC=$(VOTARGET).a
+LIB_DYNAMIC=$(VOTARGET).so
+endif
+
+ifeq ($(VOMT), exe)
+TARGET=$(VOTARGET)
+endif
+
+CFLAGS=$(VOCFLAGS) $(addprefix -I, $(VOSRCDIR)) 
+CPPFLAGS=$(VOCPPFLAGS) $(addprefix -I, $(VOSRCDIR)) 
+ifneq ($(VOTT), pc)
+ASFLAGS=$(VOASFLAGS) $(addprefix -I, $(VOSRCDIR)) 
+endif
+
+LDFLAGS:=$(VOLDFLAGS)
+VOTEDEPS+=$(VODEPLIBS)
+VOTLDEPS+=$(VODEPLIBS)
+VOSTCLIBS ?=
+
+vpath %.c $(VOSRCDIR)
+vpath %.cpp $(VOSRCDIR)
+ifneq ($(VOTT), pc)
+vpath %.s $(VOSRCDIR)
+endif
+
+ifeq ($(VOTT), pc)
+BLTDIRS=$(VORELDIR)/Linux/static
+BLTDIRD=$(VORELDIR)/Linux/shared
+else
+BLTDIRS=$(VORELDIR)/Google/$(VONJ)/lib/$(VOTT)
+BLTDIRD=$(VORELDIR)/Google/$(VONJ)/so/$(VOTT)
+endif
+
+
+.PRECIOUS: $(OBJDIR)/%.o
+
+ifeq ($(VOMT), lib)
+all: mkdirs $(LIB_STATIC) $(LIB_DYNAMIC)
+mkdirs: $(OBJDIR) $(BLTDIRS) $(BLTDIRD)
+else
+all: mkdirs $(TARGET)
+mkdirs: $(OBJDIR)
+endif
+
+$(OBJDIR):
+	@if test ! -d $@; then \
+		mkdir -p $@; \
+	fi;
+
+ifeq ($(VOMT), lib)
+$(BLTDIRS):
+	@if test ! -d $@; then \
+		mkdir -p $@; \
+	fi;
+$(BLTDIRD):
+	@if test ! -d $@; then \
+		mkdir -p $@; \
+	fi;
+endif
+
+
+ifeq ($(VOMT), lib)
+$(LIB_STATIC):$(OBJS)
+	$(AR) cr $@ $(OBJDIR)/*.o $(VOSTCLIBS)
+	$(RANLIB) $@
+ifneq ($(VODBG), yes)
+	#$(STRIP) $@
+endif
+
+$(LIB_DYNAMIC):$(OBJS)
+	$(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTLDEPS) 
+ifneq ($(VODBG), yes)
+		$(STRIP) $@
+endif
+
+else
+
+$(TARGET):$(OBJS)
+	$(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTEDEPS)
+ifneq ($(VODBG), yes)
+	$(STRIP) $@
+endif
+
+endif
+
+
+.SUFFIXES: .c .cpp .s .o
+.c.o:
+	$(VERBOSE) $(CC) $(CFLAGS) -o $(OBJDIR)/$@ -c $<
+#%.c:$(OBJDIR)/%.o
+#	$(VERBOSE) $(CC) $(CFLAGS) -o $@ -c $<
+.cpp.o:
+	$(VERBOSE) $(GG) $(CPPFLAGS) -o $(OBJDIR)/$@ -c $<
+ifneq ($(VOTT), pc)
+.s.o:
+	$(VERBOSE) $(AS) $(ASFLAGS) -o $(OBJDIR)/$@ $<
+endif
+
+
+.PHONY: clean devel
+clean:
+ifeq ($(VOMT), lib)
+	-rm -fr $(OBJDIR) .*.sw* $(VOTARGET).*
+else
+	-rm -fr $(OBJDIR) .*.sw* $(VOTARGET)
+endif
+
+devel:
+	cp -a $(LIB_STATIC) $(BLTDIRS)
+	cp -a $(LIB_DYNAMIC) $(BLTDIRD)
+
diff --git a/media/libstagefright/codecs/aacenc/Tools/eclair.mk b/media/libstagefright/codecs/aacenc/Tools/eclair.mk
new file mode 100644
index 0000000..1688361
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/Tools/eclair.mk
@@ -0,0 +1,172 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** 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.
+# */
+
+# special macro definitions for building 
+VOPREDEF=-DLINUX -D_LINUX 
+
+VOPRJ ?= 
+VONJ ?= eclair
+VOTT ?= v6
+# control the version to release out
+# available: eva(evaluation), rel(release)
+VOVER=
+ifeq ($(VOVER), eva)
+VOPREDEF+=-D__VOVER_EVA__
+endif
+
+# for debug or not: yes for debug, any other for release
+VODBG?=ye
+
+# for detecting memory leak
+VODML=
+ifeq ($(VODML), yes)
+VOPREDEF+=-DDMEMLEAK
+endif
+
+VOPREDEF+=-D__VOTT_ARM__ -D__VONJ_ECLAIR__
+TCROOTPATH:=/opt/eclair
+GCCVER:=4.4.0
+TCPATH:=$(TCROOTPATH)/prebuilt/linux-x86/toolchain/arm-eabi-$(GCCVER)
+CCTPRE:=$(TCPATH)/bin/arm-eabi-
+AS:=$(CCTPRE)as
+AR:=$(CCTPRE)ar
+NM:=$(CCTPRE)nm
+CC:=$(CCTPRE)gcc
+GG:=$(CCTPRE)g++
+LD:=$(CCTPRE)ld
+SIZE:=$(CCTPRE)size
+STRIP:=$(CCTPRE)strip
+RANLIB:=$(CCTPRE)ranlib
+OBJCOPY:=$(CCTPRE)objcopy
+OBJDUMP:=$(CCTPRE)objdump
+READELF:=$(CCTPRE)readelf
+STRINGS:=$(CCTPRE)strings
+
+# target product dependcy
+# available: dream, generic
+VOTP:=sapphire-open
+CCTLIB:=$(TCROOTPATH)/out/target/product/$(VOTP)/obj/lib
+CCTINC:=-I$(TCROOTPATH)/system/core/include \
+	-I$(TCROOTPATH)/hardware/libhardware/include \
+	-I$(TCROOTPATH)/hardware/ril/include \
+	-I$(TCROOTPATH)/hardware/libhardware_legacy/include \
+	-I$(TCROOTPATH)/dalvik/libnativehelper/include \
+	-I$(TCROOTPATH)/dalvik/libnativehelper/include/nativehelper \
+	-I$(TCROOTPATH)/frameworks/base/include \
+	-I$(TCROOTPATH)/frameworks/base/core/jni \
+	-I$(TCROOTPATH)/frameworks/base/libs/audioflinger \
+	-I$(TCROOTPATH)/external/skia/include \
+	-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/include \
+	-I$(TCROOTPATH)/bionic/libc/arch-arm/include \
+	-I$(TCROOTPATH)/bionic/libc/include \
+	-I$(TCROOTPATH)/bionic/libstdc++/include \
+	-I$(TCROOTPATH)/bionic/libc/kernel/common \
+	-I$(TCROOTPATH)/bionic/libc/kernel/arch-arm \
+	-I$(TCROOTPATH)/bionic/libm/include \
+	-I$(TCROOTPATH)/bionic/libm/include/arm \
+	-I$(TCROOTPATH)/bionic/libthread_db/include \
+	-I$(TCROOTPATH)/bionic/libm/arm \
+	-I$(TCROOTPATH)/bionic/libm \
+	-I$(TCROOTPATH)/frameworks/base/include/android_runtime 
+	#-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/SHARED_LIBRARIES/libm_intermediates
+
+CCTCFLAGS:=-msoft-float -mthumb-interwork -fno-exceptions -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fmessage-length=0 -finline-functions -finline-limit=600 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -fstrict-aliasing -funswitch-loops
+#-fwide-exec-charset=charset=UTF-32 
+
+# for target exe
+TELDFLAGS:=-nostdlib -Bdynamic -Wl,-T,$(TCROOTPATH)/build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-rpath-link=$(CCTLIB) -L$(CCTLIB) 
+
+VOTEDEPS:=$(CCTLIB)/crtbegin_dynamic.o $(CCTLIB)/crtend_android.o $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a -lc -lm
+
+# for target lib
+TLLDFLAGS:=-nostdlib -Wl,-T,$(TCROOTPATH)/build/core/armelf.xsc -Wl,--gc-sections -Wl,-shared,-Bsymbolic -L$(CCTLIB) -Wl,--no-whole-archive -Wl,--no-undefined $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a 
+
+VOTLDEPS:=-lm -lc
+
+
+ifeq ($(VOTT), v4)
+VOCFLAGS:=-mtune=arm9tdmi -march=armv4t
+VOASFLAGS:=-march=armv4t -mfpu=softfpa
+endif
+
+ifeq ($(VOTT), v5)
+VOCFLAGS:=-march=armv5te
+VOASFLAGS:=-march=armv5te -mfpu=vfp
+endif
+
+ifeq ($(VOTT), v5x)
+VOCFLAGS:=-march=armv5te -mtune=xscale
+VOASFLAGS:=-march=armv5te -mfpu=vfp
+endif
+
+ifeq ($(VOTT), v6)
+#VOCFLAGS:=-march=armv6 -mtune=arm1136jf-s 
+#VOASFLAGS:=-march=armv6
+VOCFLAGS:=-march=armv6j -mtune=arm1136jf-s -mfpu=vfp -mfloat-abi=softfp -mapcs -mtpcs-leaf-frame -mlong-calls
+VOASFLAGS:=-march=armv6j -mcpu=arm1136jf-s -mfpu=arm1136jf-s -mfloat-abi=softfp -mapcs-float -mapcs-reentrant
+endif
+
+#
+# global link options
+VOLDFLAGS:=-Wl,-x,-X,--as-needed
+
+
+ifeq ($(VOTT), v7)
+VOCFLAGS+=-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
+VOASFLAGS+=-march=armv7-a -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp
+VOLDFLAGS+=-Wl,--fix-cortex-a8
+endif
+
+#global compiling options for ARM target
+ifneq ($(VOTT), pc)
+VOASFLAGS+=--strip-local-absolute -R
+endif 
+
+
+ifeq ($(VODBG), yes)
+VOCFLAGS+=-D_DEBUG -g
+else
+VOCFLAGS+=-DNDEBUG -O3
+endif
+
+VOCFLAGS+=$(VOPREDEF) $(VOMM) -Wall -fsigned-char -fomit-frame-pointer -fno-leading-underscore -fpic -fPIC -pipe -ftracer -fforce-addr -fno-bounds-check #-fvisibility=hidden #-fvisibility-inlines-hidden ##-ftree-loop-linear  -mthumb -nostdinc  -dD -fprefetch-loop-arrays
+
+
+ifneq ($(VOTT), pc)
+VOCFLAGS+=$(CCTCFLAGS) $(CCTINC)
+VOCPPFLAGS:=-fno-rtti $(VOCFLAGS)
+
+ifeq ($(VOMT), exe)
+VOLDFLAGS+=$(TELDFLAGS)
+endif
+
+ifeq ($(VOMT), lib)
+VOLDFLAGS+=$(TLLDFLAGS)
+endif
+else
+VOCPPFLAGS:=$(VOCFLAGS)
+ifeq ($(VOMT), lib)
+VOLDFLAGS+=-shared
+endif
+endif
+
+ifeq ($(VODBG), yes)
+#VOLDFLAGS:=
+endif
+
+# where to place object files 
+OBJDIR=obj
+
diff --git a/media/libstagefright/codecs/aacenc/basic_op/basic_op.h b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h
new file mode 100644
index 0000000..5457f33
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h
@@ -0,0 +1,1166 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		basicop2.h

+

+	Content:	Constants , Globals and Basic arithmetic operators.

+

+*******************************************************************************/
+
+#ifndef __BASIC_OP_H
+#define __BASIC_OP_H

+
+#include "typedef.h"
+
+#define MAX_32 (Word32)0x7fffffffL
+#define MIN_32 (Word32)0x80000000L
+
+#define MAX_16 (Word16)0x7fff
+#define MIN_16 (Word16)0x8000
+#define ABS(a)	((a) >= 0) ? (a) : (-(a))

+

+/* Short abs,           1   */

+#define abs_s(x)       ((Word16)(((x) != MIN_16) ? (((x) >= 0) ? (x) : (-(x))) : MAX_16))

+

+/* 16 bit var1 -> MSB,     2 */

+#define L_deposit_h(x) (((Word32)(x)) << 16)

+

+

+/* 16 bit var1 -> LSB,     2 */

+#define L_deposit_l(x) ((Word32)(x))

+

+

+/* Long abs,              3  */

+#define L_abs(x) (((x) != MIN_32) ? (((x) >= 0) ? (x) : (-(x))) : MAX_32)

+

+

+/* Short negate,        1   */

+#define negate(var1) ((Word16)(((var1) == MIN_16) ? MAX_16 : (-(var1))))

+

+

+/* Long negate,     2 */

+#define L_negate(L_var1) (((L_var1) == (MIN_32)) ? (MAX_32) : (-(L_var1)))

+

+

+#define MULHIGH(A,B) (int)(((Word64)(A)*(Word64)(B)) >> 32)

+#define fixmul(a, b) (int)((((Word64)(a)*(Word64)(b)) >> 32) << 1)

+

+

+#if  (SATRUATE_IS_INLINE)

+__inline Word16 saturate(Word32 L_var1);

+#else

+Word16 saturate(Word32 L_var1);

+#endif

+

+/* Short shift left,    1   */

+#if (SHL_IS_INLINE)

+__inline Word16 shl (Word16 var1, Word16 var2);

+#else

+Word16 shl (Word16 var1, Word16 var2);

+#endif

+

+/* Short shift right,   1   */

+#if (SHR_IS_INLINE)

+__inline Word16 shr (Word16 var1, Word16 var2);

+#else

+Word16 shr (Word16 var1, Word16 var2);

+#endif

+

+#if (L_MULT_IS_INLINE)

+__inline Word32 L_mult(Word16 var1, Word16 var2);

+#else

+Word32 L_mult(Word16 var1, Word16 var2);

+#endif

+

+/* Msu,  1  */

+#if (L_MSU_IS_INLINE)

+__inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2);

+#else

+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2);

+#endif

+    

+/* Long sub,        2 */

+#if (L_SUB_IS_INLINE)

+__inline Word32 L_sub(Word32 L_var1, Word32 L_var2);

+#else

+Word32 L_sub(Word32 L_var1, Word32 L_var2);

+#endif

+

+/* Long shift left, 2 */

+#if (L_SHL_IS_INLINE)

+__inline Word32 L_shl (Word32 L_var1, Word16 var2);

+#else

+Word32 L_shl (Word32 L_var1, Word16 var2);

+#endif

+

+/* Long shift right, 2*/

+#if (L_SHR_IS_INLINE)

+__inline Word32 L_shr (Word32 L_var1, Word16 var2);

+#else

+Word32 L_shr (Word32 L_var1, Word16 var2);

+#endif

+

+/* Short add,           1   */

+#if (ADD_IS_INLINE)

+__inline Word16 add (Word16 var1, Word16 var2);

+#else

+Word16 add (Word16 var1, Word16 var2);

+#endif

+    

+/* Short sub,           1   */

+#if (SUB_IS_INLINE)

+__inline Word16 sub(Word16 var1, Word16 var2);

+#else

+Word16 sub(Word16 var1, Word16 var2);

+#endif

+

+/* Short division,       18  */

+#if (DIV_S_IS_INLINE)

+__inline Word16 div_s (Word16 var1, Word16 var2);

+#else

+Word16 div_s (Word16 var1, Word16 var2);

+#endif

+

+/* Short mult,          1   */

+#if (MULT_IS_INLINE)

+__inline Word16 mult (Word16 var1, Word16 var2);

+#else

+Word16 mult (Word16 var1, Word16 var2);

+#endif

+

+/* Short norm,           15  */

+#if (NORM_S_IS_INLINE)

+__inline Word16 norm_s (Word16 var1);

+#else

+Word16 norm_s (Word16 var1);

+#endif

+

+/* Long norm,            30  */

+#if (NORM_L_IS_INLINE)

+__inline Word16 norm_l (Word32 L_var1);

+#else

+Word16 norm_l (Word32 L_var1);

+#endif

+

+/* Round,               1   */

+#if (ROUND_IS_INLINE)

+__inline Word16 round16(Word32 L_var1);

+#else

+Word16 round16(Word32 L_var1);

+#endif

+

+/* Mac,  1  */

+#if (L_MAC_IS_INLINE)

+__inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2);

+#else

+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2);

+#endif

+

+#if (L_ADD_IS_INLINE)

+__inline Word32 L_add (Word32 L_var1, Word32 L_var2);

+#else

+Word32 L_add (Word32 L_var1, Word32 L_var2);

+#endif

+

+/* Extract high,        1   */

+#if (EXTRACT_H_IS_INLINE)

+__inline Word16 extract_h (Word32 L_var1);

+#else

+Word16 extract_h (Word32 L_var1);

+#endif

+

+/* Extract low,         1   */

+#if (EXTRACT_L_IS_INLINE)

+__inline Word16 extract_l(Word32 L_var1);

+#else

+Word16 extract_l(Word32 L_var1);

+#endif

+

+/* Mult with round, 2 */

+#if (MULT_R_IS_INLINE)

+__inline Word16 mult_r(Word16 var1, Word16 var2);

+#else

+Word16 mult_r(Word16 var1, Word16 var2);

+#endif

+

+/* Shift right with round, 2           */

+#if (SHR_R_IS_INLINE)

+__inline Word16 shr_r (Word16 var1, Word16 var2);

+#else

+Word16 shr_r (Word16 var1, Word16 var2);

+#endif

+

+/* Mac with rounding,2 */

+#if (MAC_R_IS_INLINE)

+__inline Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2);

+#else

+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2);

+#endif

+

+/* Msu with rounding,2 */

+#if (MSU_R_IS_INLINE)

+__inline Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2);

+#else

+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2);

+#endif

+

+/* Long shift right with round,  3             */

+#if (L_SHR_R_IS_INLINE)

+__inline Word32 L_shr_r (Word32 L_var1, Word16 var2);

+#else

+Word32 L_shr_r (Word32 L_var1, Word16 var2);

+#endif

+

+#if ARMV4_INASM

+__inline Word32 ASM_L_shr(Word32 L_var1, Word16 var2)

+{

+	Word32 result; 

+	asm volatile( 

+		"MOV %[result], %[L_var1], ASR %[var2] \n" 

+		:[result]"=r"(result)

+		:[L_var1]"r"(L_var1), [var2]"r"(var2)

+		); 

+	return result;	

+}

+ 

+__inline Word32 ASM_L_shl(Word32 L_var1, Word16 var2)

+{

+	Word32 result; 

+	asm volatile( 

+		"MOV	r2, %[L_var1] \n"

+		"MOV	r3, #0x7fffffff\n"

+		"MOV	%[result], %[L_var1], ASL %[var2] \n" 

+		"TEQ	r2, %[result], ASR %[var2]\n"

+		"EORNE  %[result],r3,r2,ASR#31\n"

+		:[result]"+r"(result)

+		:[L_var1]"r"(L_var1), [var2]"r"(var2)

+		:"r2", "r3"

+		); 

+	return result;	

+}

+

+__inline Word32 ASM_shr(Word32 L_var1, Word16 var2)

+{

+	Word32 result; 

+	asm volatile( 

+		"CMP	%[var2], #15\n"

+		"MOVGE  %[var2], #15\n"

+		"MOV	%[result], %[L_var1], ASR %[var2]\n"

+		:[result]"=r"(result)

+		:[L_var1]"r"(L_var1), [var2]"r"(var2) 

+		); 

+	return result;	

+} 

+

+__inline Word32 ASM_shl(Word32 L_var1, Word16 var2)

+{

+	Word32 result; 

+	asm volatile( 

+		"CMP	%[var2], #16\n"

+		"MOVGE  %[var2], #16\n"

+		"MOV    %[result], %[L_var1], ASL %[var2]\n"

+		"MOV    r3, #1\n"

+        "MOV    r2, %[result], ASR #15\n"

+        "RSB    r3,r3,r3,LSL #15 \n"

+        "TEQ    r2, %[result], ASR #31 \n"

+        "EORNE  %[result], r3, %[result],ASR #31"

+		:[result]"+r"(result)

+		:[L_var1]"r"(L_var1), [var2]"r"(var2)

+		:"r2", "r3"

+		); 

+	return result;	

+} 

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   definitions for inline basic arithmetic operators                       |

+ |___________________________________________________________________________|

+*/

+#if (SATRUATE_IS_INLINE)

+__inline Word16 saturate(Word32 L_var1)

+{

+#if ARMV5TE_SAT

+	Word16 result;

+	asm volatile (

+		"MOV	%[result], %[L_var1]\n"

+		"MOV	r3, #1\n"

+		"MOV	r2,%[L_var1],ASR#15\n"

+		"RSB	r3, r3, r3, LSL #15\n"

+		"TEQ	r2,%[L_var1],ASR#31\n"	

+		"EORNE	%[result],r3,%[L_var1],ASR#31\n"

+		:[result]"+r"(result)

+		:[L_var1]"r"(L_var1)

+		:"r2", "r3"			

+	);

+

+	return result;

+#else

+    Word16 var_out;

+    

+    //var_out = (L_var1 > (Word32)0X00007fffL) ? (MAX_16) : ((L_var1 < (Word32)0xffff8000L) ? (MIN_16) : ((Word16)L_var1));

+

+    if (L_var1 > 0X00007fffL)

+    {

+        var_out = MAX_16;

+    }

+    else if (L_var1 < (Word32) 0xffff8000L)

+    {

+        var_out = MIN_16;

+    }

+    else

+    {

+        var_out = extract_l(L_var1);

+    }

+

+    return (var_out);

+#endif

+}

+#endif

+

+/* Short shift left,    1   */

+#if (SHL_IS_INLINE)

+__inline Word16 shl (Word16 var1, Word16 var2)

+{

+#if ARMV5TE_SHL

+	if(var2>=0)

+	{

+		return ASM_shl( var1, var2);

+	}

+	else

+	{

+		return ASM_shr( var1, -var2);

+	}

+#else

+    Word16 var_out;

+    Word32 result;

+

+    if (var2 < 0)

+    {

+        var_out = shr (var1, (Word16)-var2);

+    }

+    else

+    {

+        result = (Word32) var1 *((Word32) 1 << var2);

+

+        if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))

+        {

+            var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);

+        }

+        else

+        {

+            var_out = extract_l(result);

+        }

+    }

+    return (var_out);

+#endif

+}

+#endif

+

+/* Short shift right,   1   */

+#if (SHR_IS_INLINE)

+__inline Word16 shr (Word16 var1, Word16 var2)

+{

+#if ARMV5TE_SHR

+	if(var2>=0)

+	{

+		return  ASM_shr( var1, var2);

+	}

+	else

+	{

+		return  ASM_shl( var1, -var2);

+	}

+#else

+    Word16 var_out;

+

+    if (var2 < 0)

+    {

+        var_out = shl (var1, (Word16)-var2);

+    }

+    else

+    {

+        if (var2 >= 15)

+        {

+            var_out = (Word16)((var1 < 0) ? -1 : 0);

+        }

+        else

+        {

+            if (var1 < 0)

+            {

+                var_out = (Word16)(~((~var1) >> var2));

+            }

+            else

+            {

+                var_out = (Word16)(var1 >> var2);

+            }

+        }

+    }

+

+    return (var_out);

+#endif

+}

+#endif

+

+

+#if (L_MULT_IS_INLINE)

+__inline Word32 L_mult(Word16 var1, Word16 var2)

+{

+#if ARMV5TE_L_MULT

+	Word32 result; 

+	asm volatile( 

+		"SMULBB %[result], %[var1], %[var2] \n" 

+		"QADD %[result], %[result], %[result] \n" 

+		:[result]"+r"(result)

+		:[var1]"r"(var1), [var2]"r"(var2)

+		); 

+	return result;

+#else

+    Word32 L_var_out;

+

+    L_var_out = (Word32) var1 *(Word32) var2;

+

+    if (L_var_out != (Word32) 0x40000000L)

+    {

+        L_var_out <<= 1;

+    }

+    else

+    {

+        L_var_out = MAX_32;

+    }

+    return (L_var_out);

+#endif

+}

+#endif

+

+#if (L_MSU_IS_INLINE)

+__inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)

+{

+#if ARMV5TE_L_MSU

+	Word32 result; 

+	asm volatile( 

+		"SMULBB %[result], %[var1], %[var2] \n" 

+		"QADD %[result], %[result], %[result] \n"

+		"QSUB %[result], %[L_var3], %[result]\n"

+		:[result]"+r"(result)

+		:[L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2)

+		); 

+	return result;

+#else

+    Word32 L_var_out;

+    Word32 L_product;

+

+    L_product = L_mult(var1, var2);

+    L_var_out = L_sub(L_var3, L_product);

+    return (L_var_out);

+#endif

+}

+#endif

+

+#if (L_SUB_IS_INLINE)

+__inline Word32 L_sub(Word32 L_var1, Word32 L_var2)

+{

+#if ARMV5TE_L_SUB

+	Word32 result; 

+	asm volatile( 

+		"QSUB %[result], %[L_var1], %[L_var2]\n"

+		:[result]"+r"(result)

+		:[L_var1]"r"(L_var1), [L_var2]"r"(L_var2)

+		); 

+	return result;

+#else

+    Word32 L_var_out;

+

+    L_var_out = L_var1 - L_var2;

+

+    if (((L_var1 ^ L_var2) & MIN_32) != 0)

+    {

+        if ((L_var_out ^ L_var1) & MIN_32)

+        {

+            L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;

+        }

+    }

+

+    return (L_var_out);

+#endif

+}

+#endif

+

+#if (L_SHL_IS_INLINE)

+__inline Word32 L_shl(Word32 L_var1, Word16 var2)

+{

+#if ARMV5TE_L_SHL

+    if(var2>=0)

+    {

+        return  ASM_L_shl( L_var1, var2);

+    }

+    else

+    {

+        return  ASM_L_shr( L_var1, -var2);

+    }

+#else

+    Word32 L_var_out = 0L;

+

+    if (var2 <= 0)

+    {

+        L_var1 = L_shr(L_var1, (Word16)-var2);

+    }

+    else

+    {

+        for (; var2 > 0; var2--)

+        {

+            if (L_var1 > (Word32) 0X3fffffffL)

+            {

+                return MAX_32;

+            }

+            else

+            {

+                if (L_var1 < (Word32) 0xc0000000L)

+                {

+                    return MIN_32;

+                }

+            }

+            L_var1 <<= 1;

+            L_var_out = L_var1;

+        }

+    }

+    return (L_var1);

+#endif

+}

+#endif

+

+#if (L_SHR_IS_INLINE)

+__inline Word32 L_shr (Word32 L_var1, Word16 var2)

+{

+#if ARMV5TE_L_SHR

+	if(var2>=0)

+	{

+		return ASM_L_shr( L_var1, var2);

+	}

+	else

+	{

+		return ASM_L_shl( L_var1, -var2);

+	}

+#else

+    Word32 L_var_out;

+

+    if (var2 < 0)

+    {

+        L_var_out = L_shl (L_var1, (Word16)-var2);

+    }

+    else

+    {

+        if (var2 >= 31)

+        {

+            L_var_out = (L_var1 < 0L) ? -1 : 0;

+        }

+        else

+        {

+            if (L_var1 < 0)

+            {

+                L_var_out = ~((~L_var1) >> var2);

+            }

+            else

+            {

+                L_var_out = L_var1 >> var2;

+            }

+        }

+    }

+    return (L_var_out);

+#endif

+}

+#endif

+

+/* Short add,           1   */

+#if (ADD_IS_INLINE)

+__inline Word16 add (Word16 var1, Word16 var2)

+{

+#if ARMV5TE_ADD

+	Word32 result; 

+	asm volatile( 

+		"ADD  %[result], %[var1], %[var2] \n" 

+		"MOV  r3, #0x1\n"

+		"MOV  r2, %[result], ASR #15\n"

+		"RSB  r3, r3, r3, LSL, #15\n"

+		"TEQ  r2, %[result], ASR #31\n"

+		"EORNE %[result], r3, %[result], ASR #31"

+		:[result]"+r"(result)

+		:[var1]"r"(var1), [var2]"r"(var2)

+		:"r2", "r3"

+		); 

+	return result;

+#else

+    Word16 var_out;

+    Word32 L_sum;

+

+    L_sum = (Word32) var1 + var2;

+    var_out = saturate(L_sum);

+

+    return (var_out);

+#endif

+}

+#endif

+

+/* Short sub,           1   */

+#if (SUB_IS_INLINE)

+__inline Word16 sub(Word16 var1, Word16 var2)

+{

+#if ARMV5TE_SUB

+	Word32 result; 

+	asm volatile( 

+		"MOV   r3, #1\n"

+		"SUB   %[result], %[var1], %[var2] \n"		

+		"RSB   r3,r3,r3,LSL#15\n"

+		"MOV   r2, %[var1], ASR #15 \n" 

+		"TEQ   r2, %[var1], ASR #31 \n"

+		"EORNE %[result], r3, %[result], ASR #31 \n"

+		:[result]"+r"(result)

+		:[var1]"r"(var1), [var2]"r"(var2)

+		:"r2", "r3"

+		); 

+	return result;

+#else

+    Word16 var_out;

+    Word32 L_diff;

+

+    L_diff = (Word32) var1 - var2;

+    var_out = saturate(L_diff);

+   

+    return (var_out);

+#endif

+}

+#endif

+

+/* Short division,       18  */

+#if (DIV_S_IS_INLINE)

+__inline Word16 div_s (Word16 var1, Word16 var2)

+{

+    Word16 var_out = 0;

+    Word16 iteration;

+    Word32 L_num;

+    Word32 L_denom;

+

+    var_out = MAX_16;

+    if (var1!= var2)//var1!= var2

+    {

+    	var_out = 0;

+    	L_num = (Word32) var1;

+    

+    	L_denom = (Word32) var2;

+    	

+		//return (L_num<<15)/var2;

+

+    	for (iteration = 0; iteration < 15; iteration++)

+    	{

+    		var_out <<= 1;

+    		L_num <<= 1;

+    		

+    		if (L_num >= L_denom)

+    		{

+    			L_num -= L_denom;

+    			var_out++;

+    		}

+    	}

+    }

+    return (var_out);

+}

+#endif

+

+/* Short mult,          1   */

+#if (MULT_IS_INLINE)

+__inline Word16 mult (Word16 var1, Word16 var2)

+{

+#if ARMV5TE_MULT

+	Word32 result; 

+	asm volatile( 

+		"SMULBB r2, %[var1], %[var2] \n"

+		"MOV	r3, #1\n"

+		"MOV	%[result], r2, ASR #15\n"

+		"RSB	r3, r3, r3, LSL #15\n"

+		"MOV	r2, %[result], ASR #15\n"

+		"TEQ	r2, %[result], ASR #31\n"

+		"EORNE  %[result], r3, %[result], ASR #31 \n"

+		:[result]"+r"(result)

+		:[var1]"r"(var1), [var2]"r"(var2)

+		:"r2", "r3"

+		); 

+	return result;

+#else

+    Word16 var_out;

+    Word32 L_product;

+

+    L_product = (Word32) var1 *(Word32) var2;

+    L_product = (L_product & (Word32) 0xffff8000L) >> 15;

+    if (L_product & (Word32) 0x00010000L)

+        L_product = L_product | (Word32) 0xffff0000L;

+    var_out = saturate(L_product);

+

+    return (var_out);

+#endif

+}

+#endif

+

+

+/* Short norm,           15  */

+#if (NORM_S_IS_INLINE)

+__inline Word16 norm_s (Word16 var1)

+{

+#if ARMV5TE_NORM_S

+	Word16 result; 

+	asm volatile( 

+		"MOV   r2,%[var1] \n"

+		"CMP   r2, #0\n"

+		"RSBLT %[var1], %[var1], #0 \n"

+		"CLZNE %[result], %[var1]\n"

+		"SUBNE %[result], %[result], #17\n"

+		"MOVEQ %[result], #0\n"

+		"CMP   r2, #-1\n"

+		"MOVEQ %[result], #15\n" 

+		:[result]"+r"(result)

+		:[var1]"r"(var1)

+		:"r2"

+		); 

+	return result;

+#else

+    Word16 var_out;

+

+    if (var1 == 0)

+    {

+        var_out = 0;

+    }

+    else

+    {

+        if (var1 == -1)

+        {

+            var_out = 15;

+        }

+        else

+        {

+            if (var1 < 0)

+            {

+                var1 = (Word16)~var1;

+            }

+            for (var_out = 0; var1 < 0x4000; var_out++)

+            {

+                var1 <<= 1;

+            }

+        }

+    }

+    return (var_out);

+#endif

+}

+#endif

+

+/* Long norm,            30  */

+#if (NORM_L_IS_INLINE)

+__inline Word16 norm_l (Word32 L_var1)

+{

+#if ARMV5TE_NORM_L

+	Word16 result; 

+	asm volatile( 

+		"CMP    %[L_var1], #0\n"

+		"CLZNE  %[result], %[L_var1]\n"

+		"SUBNE  %[result], %[result], #1\n" 

+		"MOVEQ  %[result], #0\n"

+		:[result]"+r"(result)

+		:[L_var1]"r"(L_var1)

+		); 

+	return result;

+#else

+    //Word16 var_out;

+

+    //if (L_var1 == 0)

+    //{

+    //    var_out = 0;

+    //}

+    //else

+    //{

+    //    if (L_var1 == (Word32) 0xffffffffL)

+    //    {

+    //        var_out = 31;

+    //    }

+    //    else

+    //    {

+    //        if (L_var1 < 0)

+    //        {

+    //            L_var1 = ~L_var1;

+    //        }

+    //        for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)

+    //        {

+    //            L_var1 <<= 1;

+    //        }

+    //    }

+    //}

+    //return (var_out);

+  Word16 a16;

+  Word16 r = 0 ;       

+

+   

+  if ( L_var1 < 0 ) {

+    L_var1 = ~L_var1; 

+  }

+

+  if (0 == (L_var1 & 0x7fff8000)) {

+    a16 = extract_l(L_var1);

+    r += 16;

+       

+    if (0 == (a16 & 0x7f80)) {

+      r += 8;

+         

+      if (0 == (a16 & 0x0078)) {

+        r += 4;

+           

+        if (0 == (a16 & 0x0006)) {

+          r += 2;

+             

+          if (0 == (a16 & 0x0001)) {

+            r += 1;

+          }

+        }

+        else {

+             

+          if (0 == (a16 & 0x0004)) {

+            r += 1;

+          }

+        }

+      }

+      else {

+           

+        if (0 == (a16 & 0x0060)) {

+          r += 2;

+             

+          if (0 == (a16 & 0x0010)) {

+            r += 1;

+          }

+        }

+        else {

+             

+          if (0 == (a16 & 0x0040)) {

+            r += 1;

+          }

+        }

+      }

+    } 

+    else { 

+         

+      if (0 == (a16 & 0x7800)) {

+        r += 4;

+           

+        if (0 == (a16 & 0x0600)) {

+          r += 2;

+             

+          if (0 == (a16 & 0x0100)) {

+            r += 1;

+          }

+        }

+        else {

+             

+          if (0 == (a16 & 0x0400)) {

+            r += 1;

+          }

+        }

+      }

+      else {

+           

+        if (0 == (a16 & 0x6000)) {

+          r += 2;

+             

+          if (0 == (a16 & 0x1000)) {

+            r += 1;

+          }

+        }

+        else {

+             

+          if (0 == (a16 & 0x4000)) {

+            r += 1;

+          }

+        }

+      }

+    }

+  }

+  else {

+    a16 = extract_h(L_var1);

+       

+    if (0 == (a16 & 0x7f80)) {

+      r += 8;

+         

+      if (0 == (a16 & 0x0078)) {

+        r += 4 ;

+           

+        if (0 == (a16 & 0x0006)) {

+          r += 2;

+             

+          if (0 == (a16 & 0x0001)) {

+            r += 1;

+          }

+        }

+        else {

+             

+          if (0 == (a16 & 0x0004)) {

+            r += 1;

+          }

+        }

+      }

+      else {

+           

+        if (0 == (a16 & 0x0060)) {

+          r += 2;

+             

+          if (0 == (a16 & 0x0010)) {

+            r += 1;

+          }

+        }

+        else {

+             

+          if (0 == (a16 & 0x0040)) {

+            r += 1;

+          }

+        }

+      }

+    }

+    else {

+         

+      if (0 == (a16 & 0x7800)) {

+        r += 4;

+           

+        if (0 == (a16 & 0x0600)) {

+          r += 2;

+             

+          if (0 == (a16 & 0x0100)) {

+            r += 1;

+          }

+        }

+        else {

+             

+          if (0 == (a16 & 0x0400)) {

+            r += 1;

+          }

+        }

+      }

+      else {

+           

+        if (0 == (a16 & 0x6000)) {

+          r += 2;

+             

+          if (0 == (a16 & 0x1000)) {

+            r += 1;

+          }

+        }

+        else {

+             

+          if (0 == (a16 & 0x4000)) {

+            return 1;

+          }

+        }

+      }

+    }

+  }

+  

+  return r ;

+#endif

+}

+#endif

+

+/* Round,               1   */

+#if (ROUND_IS_INLINE)

+__inline Word16 round16(Word32 L_var1)

+{

+#if ARMV5TE_ROUND

+	Word16 result; 

+	asm volatile( 

+		"MOV   r1,#0x00008000\n"

+		"QADD  %[result], %[L_var1], r1\n"

+		"MOV   %[result], %[result], ASR #16 \n" 

+		:[result]"+r"(result)

+		:[L_var1]"r"(L_var1)

+		:"r1"

+		); 

+	return result;

+#else   

+    Word16 var_out;

+    Word32 L_rounded;

+

+    L_rounded = L_add (L_var1, (Word32) 0x00008000L);

+    var_out = extract_h (L_rounded);

+    return (var_out);

+#endif

+}

+#endif

+

+/* Mac,  1  */

+#if (L_MAC_IS_INLINE)

+__inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)

+{

+#if ARMV5TE_L_MAC

+	Word32 result; 

+	asm volatile( 

+		"SMULBB %[result], %[var1], %[var2]\n"

+		"QADD	%[result], %[result], %[result]\n"

+		"QADD   %[result], %[result], %[L_var3]\n"

+		:[result]"+r"(result)

+		: [L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2)

+		); 

+	return result;

+#else

+    Word32 L_var_out;

+    Word32 L_product;

+

+    L_product = L_mult(var1, var2);

+    L_var_out = L_add (L_var3, L_product);

+    return (L_var_out);

+#endif

+}

+#endif

+

+#if (L_ADD_IS_INLINE)

+__inline Word32 L_add (Word32 L_var1, Word32 L_var2)

+{

+#if ARMV5TE_L_ADD

+	Word32 result; 

+	asm volatile( 

+		"QADD %[result], %[L_var1], %[L_var2]\n"

+		:[result]"+r"(result)

+		:[L_var1]"r"(L_var1), [L_var2]"r"(L_var2)

+		); 

+	return result;

+#else

+    Word32 L_var_out;

+

+    L_var_out = L_var1 + L_var2;

+    if (((L_var1 ^ L_var2) & MIN_32) == 0)

+    {

+        if ((L_var_out ^ L_var1) & MIN_32)

+        {

+            L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;

+        }

+    }

+    return (L_var_out);

+#endif

+}

+#endif

+

+

+

+#if (MULT_R_IS_INLINE)

+__inline Word16 mult_r (Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+    Word32 L_product_arr;

+

+    L_product_arr = (Word32)var1 *(Word32)var2;       /* product */

+    L_product_arr += (Word32)0x00004000L;      /* round */

+    L_product_arr >>= 15;       /* shift */

+

+    var_out = saturate(L_product_arr);

+

+    return (var_out);

+}

+#endif

+

+#if (SHR_R_IS_INLINE)

+__inline Word16 shr_r (Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+

+    if (var2 > 15)

+    {

+        var_out = 0;

+    }

+    else

+    {

+        var_out = shr(var1, var2);

+

+        if (var2 > 0)

+        {

+            if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)

+            {

+                var_out++;

+            }

+        }

+    }

+

+    return (var_out);

+}

+#endif

+

+#if (MAC_R_IS_INLINE)

+__inline Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+

+    L_var3 = L_mac (L_var3, var1, var2);

+    var_out = (Word16)((L_var3 + 0x8000L) >> 16);

+

+    return (var_out);

+}

+#endif

+

+#if (MSU_R_IS_INLINE)

+__inline Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+

+    L_var3 = L_msu (L_var3, var1, var2);

+    var_out = (Word16)((L_var3 + 0x8000L) >> 16);

+    

+    return (var_out);

+}

+#endif

+

+#if (L_SHR_R_IS_INLINE)

+__inline Word32 L_shr_r (Word32 L_var1, Word16 var2)

+{

+    Word32 L_var_out;

+

+    if (var2 > 31)

+    {

+        L_var_out = 0;

+    }

+    else

+    {

+        L_var_out = L_shr(L_var1, var2);

+

+        if (var2 > 0)

+        {

+            if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)

+            {

+                L_var_out++;

+            }

+        }

+    }

+

+    return (L_var_out);

+}

+#endif

+

+#if (EXTRACT_H_IS_INLINE)

+__inline Word16 extract_h (Word32 L_var1)

+{

+    Word16 var_out;

+

+    var_out = (Word16) (L_var1 >> 16);

+

+    return (var_out);

+}

+#endif

+

+#if (EXTRACT_L_IS_INLINE)

+__inline Word16 extract_l(Word32 L_var1)

+{

+	return (Word16) L_var1;

+}

+#endif

+

+#endif
diff --git a/media/libstagefright/codecs/aacenc/basic_op/basicop2.c b/media/libstagefright/codecs/aacenc/basic_op/basicop2.c
new file mode 100644
index 0000000..a0d5dba
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/basicop2.c
@@ -0,0 +1,1624 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		basicop2.c

+

+	Content:	Basic arithmetic operators. 

+

+*******************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Functions                                                               |

+ |___________________________________________________________________________|

+*/

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : saturate                                                |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |    Limit the 32 bit input to the range of a 16 bit word.                  |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1                                                                 |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+

+#if (!SATRUATE_IS_INLINE)

+Word16 saturate(Word32 L_var1)

+{

+    Word16 var_out;

+

+    if (L_var1 > 0X00007fffL)

+    {

+        var_out = MAX_16;

+    }

+    else if (L_var1 < (Word32) 0xffff8000L)

+    {

+        var_out = MIN_16;

+    }

+    else

+    {

+        var_out = extract_l(L_var1);

+    }

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : add                                                     |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |    Performs the addition (var1+var2) with overflow control and saturation;|

+ |    the 16 bit result is set at +32767 when overflow occurs or at -32768   |

+ |    when underflow occurs.                                                 |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+

+#if (!ADD_IS_INLINE)

+Word16 add (Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+    Word32 L_sum;

+

+    L_sum = (Word32)var1 + (Word32)var2;

+    var_out = saturate(L_sum);

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : sub                                                     |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |    Performs the subtraction (var1+var2) with overflow control and satu-   |

+ |    ration; the 16 bit result is set at +32767 when overflow occurs or at  |

+ |    -32768 when underflow occurs.                                          |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+#if (!SUB_IS_INLINE)

+Word16 sub(Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+    Word32 L_diff;

+

+    L_diff = (Word32) var1 - var2;

+    var_out = saturate(L_diff);

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : abs_s                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |    Absolute value of var1; abs_s(-32768) = 32767.                         |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0x0000 0000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+//Word16 abs_s (Word16 var1)

+//{

+//    Word16 var_out;

+//

+//    if (var1 == MIN_16)

+//    {

+//        var_out = MAX_16;

+//    }

+//    else

+//    {

+//        if (var1 < 0)

+//        {

+//            var_out = (Word16)-var1;

+//        }

+//        else

+//        {

+//            var_out = var1;

+//        }

+//    }

+//

+//    return (var_out);

+//}

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : shl                                                     |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|

+ |   the var2 LSB of the result. If var2 is negative, arithmetically shift   |

+ |   var1 right by -var2 with sign extension. Saturate the result in case of |

+ |   underflows or overflows.                                                |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+

+#if (!SHL_IS_INLINE)

+Word16 shl (Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+    Word32 result;

+

+    if (var2 < 0)

+    {

+        if (var2 < -16)

+            var2 = -16;

+        var_out = shr (var1, (Word16)-var2);

+    }

+    else

+    {

+        result = (Word32) var1 *((Word32) 1 << var2);

+

+        if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))

+        {

+            //Overflow = 1;

+            var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);

+        }

+        else

+        {

+            var_out = extract_l(result);

+        }

+    }

+

+    return (var_out);

+}

+#endif

+// end

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : shr                                                     |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Arithmetically shift the 16 bit input var1 right var2 positions with    |

+ |   sign extension. If var2 is negative, arithmetically shift var1 left by  |

+ |   -var2 with sign extension. Saturate the result in case of underflows or |

+ |   overflows.                                                              |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+

+#if (!SHR_IS_INLINE)

+Word16 shr (Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+

+    if (var2 < 0)

+    {

+        if (var2 < -16)

+            var2 = -16;

+        var_out = shl (var1, (Word16)-var2);

+    }

+    else

+    {

+        if (var2 >= 15)

+        {

+            var_out = (Word16)((var1 < 0) ? -1 : 0);

+        }

+        else

+        {

+            if (var1 < 0)

+            {

+                var_out = (Word16)(~((~var1) >> var2));

+            }

+            else

+            {

+                var_out = (Word16)(var1 >> var2);

+            }

+        }

+    }

+

+    return (var_out);

+}

+#endif

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : mult                                                    |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |    Performs the multiplication of var1 by var2 and gives a 16 bit result  |

+ |    which is scaled i.e.:                                                  |

+ |             mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and  |

+ |             mult(-32768,-32768) = 32767.                                  |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+#if (!MULT_IS_INLINE)

+Word16 mult (Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+    Word32 L_product;

+

+    L_product = (Word32) var1 *(Word32) var2;

+

+    L_product = (L_product & (Word32) 0xffff8000L) >> 15;

+

+    if (L_product & (Word32) 0x00010000L)

+        L_product = L_product | (Word32) 0xffff0000L;

+

+    var_out = saturate(L_product);

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_mult                                                  |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   L_mult is the 32 bit result of the multiplication of var1 times var2    |

+ |   with one shift left i.e.:                                               |

+ |        L_mult(var1,var2) = L_shl((var1 times var2),1) and                 |

+ |        L_mult(-32768,-32768) = 2147483647.                                |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+ |___________________________________________________________________________|

+*/

+

+#if (!L_MULT_IS_INLINE)

+Word32 L_mult(Word16 var1, Word16 var2)

+{

+    Word32 L_var_out;

+

+    L_var_out = (Word32) var1 *(Word32) var2;

+

+    if (L_var_out != (Word32) 0x40000000L)

+    {

+        L_var_out <<= 1;

+    }

+    else

+    {

+        L_var_out = MAX_32;

+    }

+        

+    return (L_var_out);

+}

+#endif

+// end

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : negate                                                  |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Negate var1 with saturation, saturate in the case where input is -32768:|

+ |                negate(var1) = sub(0,var1).                                |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+//Word16 negate (Word16 var1)

+//{

+//    Word16 var_out;

+//

+//    var_out = (Word16)((var1 == MIN_16) ? MAX_16 : -var1);

+//

+//    return (var_out);

+//}

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : extract_h                                               |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Return the 16 MSB of L_var1.                                            |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1                                                                 |

+ |             32 bit long signed integer (Word32 ) whose value falls in the |

+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+#if (!EXTRACT_H_IS_INLINE)

+Word16 extract_h (Word32 L_var1)

+{

+    Word16 var_out;

+

+    var_out = (Word16) (L_var1 >> 16);

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : extract_l                                               |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Return the 16 LSB of L_var1.                                            |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1                                                                 |

+ |             32 bit long signed integer (Word32 ) whose value falls in the |

+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+#if (!EXTRACT_L_IS_INLINE)

+Word16 extract_l(Word32 L_var1)

+{

+    Word16 var_out;

+

+    var_out = (Word16) L_var1;

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : round                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Round the lower 16 bits of the 32 bit input number into the MS 16 bits  |

+ |   with saturation. Shift the resulting bits right by 16 and return the 16 |

+ |   bit number:                                                             |

+ |               round(L_var1) = extract_h(L_add(L_var1,32768))              |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1                                                                 |

+ |             32 bit long signed integer (Word32 ) whose value falls in the |

+ |             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+

+#if (!ROUND_IS_INLINE)

+Word16 round16(Word32 L_var1)

+{

+    Word16 var_out;

+    Word32 L_rounded;

+

+    L_rounded = L_add (L_var1, (Word32) 0x00008000L);

+    var_out = extract_h (L_rounded);

+

+    return (var_out);

+}

+#endif

+// end

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_mac                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |

+ |   result to L_var3 with saturation, return a 32 bit result:               |

+ |        L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)).         |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+ |___________________________________________________________________________|

+*/

+#if (!L_MSU_IS_INLINE)

+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)

+{

+    Word32 L_var_out;

+    Word32 L_product;

+

+    L_product = L_mult(var1, var2);

+    L_var_out = L_add (L_var3, L_product);

+

+    return (L_var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_msu                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |

+ |   bit result to L_var3 with saturation, return a 32 bit result:           |

+ |        L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)).         |

+ |                                                                           |

+ |   Complexity weight : 1                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+ |___________________________________________________________________________|

+*/

+

+#if (!L_MSU_IS_INLINE)

+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)

+{

+    Word32 L_var_out;

+    Word32 L_product;

+

+    L_product = L_mult(var1, var2);

+    L_var_out = L_sub (L_var3, L_product);

+

+    return (L_var_out);

+}

+#endif

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_add                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   32 bits addition of the two 32 bits variables (L_var1+L_var2) with      |

+ |   overflow control and saturation; the result is set at +2147483647 when  |

+ |   overflow occurs or at -2147483648 when underflow occurs.                |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+ |___________________________________________________________________________|

+*/

+#if (!L_ADD_IS_INLINE)

+Word32 L_add (Word32 L_var1, Word32 L_var2)

+{

+    Word32 L_var_out;

+

+    L_var_out = L_var1 + L_var2;

+

+    if (((L_var1 ^ L_var2) & MIN_32) == 0)

+    {

+        if ((L_var_out ^ L_var1) & MIN_32)

+        {

+            L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;

+            //Overflow = 1;

+        }

+    }

+

+    return (L_var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_sub                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with   |

+ |   overflow control and saturation; the result is set at +2147483647 when  |

+ |   overflow occurs or at -2147483648 when underflow occurs.                |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |    L_var2   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+ |___________________________________________________________________________|

+*/

+#if (!L_SUB_IS_INLINE)

+Word32 L_sub(Word32 L_var1, Word32 L_var2)

+{

+    Word32 L_var_out;

+

+    L_var_out = L_var1 - L_var2;

+

+    if (((L_var1 ^ L_var2) & MIN_32) != 0)

+    {

+        if ((L_var_out ^ L_var1) & MIN_32)

+        {

+            L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;

+            //Overflow = 1;

+        }

+    }

+

+    return (L_var_out);

+}

+#endif

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_negate                                                |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Negate the 32 bit variable L_var1 with saturation; saturate in the case |

+ |   where input is -2147483648 (0x8000 0000).                               |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+ |___________________________________________________________________________|

+*/

+//Word32 L_negate (Word32 L_var1)

+//{

+//    Word32 L_var_out;

+//

+//    L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1;

+//

+//    return (L_var_out);

+//}

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : mult_r                                                  |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Same as mult with rounding, i.e.:                                       |

+ |     mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and  |

+ |     mult_r(-32768,-32768) = 32767.                                        |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+#if (!MULT_R_IS_INLINE)

+Word16 mult_r (Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+    Word32 L_product_arr;

+

+    L_product_arr = (Word32) var1 *(Word32) var2;       /* product */

+    L_product_arr += (Word32) 0x00004000L;      /* round */

+    L_product_arr &= (Word32) 0xffff8000L;

+    L_product_arr >>= 15;       /* shift */

+

+    if (L_product_arr & (Word32) 0x00010000L)   /* sign extend when necessary */

+    {

+        L_product_arr |= (Word32) 0xffff0000L;

+    }

+    var_out = saturate(L_product_arr);

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_shl                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero  |

+ |   fill the var2 LSB of the result. If var2 is negative, arithmetically    |

+ |   shift L_var1 right by -var2 with sign extension. Saturate the result in |

+ |   case of underflows or overflows.                                        |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+ |___________________________________________________________________________|

+*/

+

+#if (!L_SHL_IS_INLINE)

+Word32 L_shl (Word32 L_var1, Word16 var2)

+{

+    Word32 L_var_out = 0L;

+

+    if (var2 <= 0)

+    {

+        L_var1 = L_shr(L_var1, (Word16)-var2);

+    }

+    else

+    {

+        for (; var2 > 0; var2--)

+        {

+            if (L_var1 > (Word32) 0X3fffffffL)

+            {

+                return MAX_32;

+            }

+            else

+            {

+                if (L_var1 < (Word32) 0xc0000000L)

+                {

+                    return MIN_32;

+                }

+            }

+            L_var1 <<= 1;

+        }

+    }

+    return (L_var1);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_shr                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Arithmetically shift the 32 bit input L_var1 right var2 positions with  |

+ |   sign extension. If var2 is negative, arithmetically shift L_var1 left   |

+ |   by -var2 and zero fill the -var2 LSB of the result. Saturate the result |

+ |   in case of underflows or overflows.                                     |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+ |___________________________________________________________________________|

+*/

+

+#if (!L_SHR_IS_INLINE)

+Word32 L_shr (Word32 L_var1, Word16 var2)

+{

+    Word32 L_var_out;

+

+    if (var2 < 0)

+    {

+        L_var_out = L_shl (L_var1, (Word16)-var2);

+    }

+    else

+    {

+        if (var2 >= 31)

+        {

+            L_var_out = (L_var1 < 0L) ? -1 : 0;

+        }

+        else

+        {

+            if (L_var1 < 0)

+            {

+                L_var_out = ~((~L_var1) >> var2);

+            }

+            else

+            {

+                L_var_out = L_var1 >> var2;

+            }

+        }

+    }

+    return (L_var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : shr_r                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Same as shr(var1,var2) but with rounding. Saturate the result in case of|

+ |   underflows or overflows :                                               |

+ |    - If var2 is greater than zero :                                       |

+ |          if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1))))            |

+ |          is equal to zero                                                 |

+ |                     then                                                  |

+ |                     shr_r(var1,var2) = shr(var1,var2)                     |

+ |                     else                                                  |

+ |                     shr_r(var1,var2) = add(shr(var1,var2),1)              |

+ |    - If var2 is less than or equal to zero :                              |

+ |                     shr_r(var1,var2) = shr(var1,var2).                    |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+#if (!SHR_R_IS_INLINE)

+Word16 shr_r (Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+

+    if (var2 > 15)

+    {

+        var_out = 0;

+    }

+    else

+    {

+        var_out = shr (var1, var2);

+

+        if (var2 > 0)

+        {

+            if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)

+            {

+                var_out++;

+            }

+        }

+    }

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : mac_r                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |

+ |   result to L_var3 with saturation. Round the LS 16 bits of the result    |

+ |   into the MS 16 bits with saturation and shift the result right by 16.   |

+ |   Return a 16 bit result.                                                 |

+ |            mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2))       |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0x0000 8000 <= L_var_out <= 0x0000 7fff.              |

+ |___________________________________________________________________________|

+*/

+#if (!MAC_R_IS_INLINE)

+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+

+    L_var3 = L_mac (L_var3, var1, var2);

+    L_var3 = L_add (L_var3, (Word32) 0x00008000L);

+    var_out = extract_h (L_var3);

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : msu_r                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |

+ |   bit result to L_var3 with saturation. Round the LS 16 bits of the res-  |

+ |   ult into the MS 16 bits with saturation and shift the result right by   |

+ |   16. Return a 16 bit result.                                             |

+ |            msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2))       |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var3   32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0x0000 8000 <= L_var_out <= 0x0000 7fff.              |

+ |___________________________________________________________________________|

+*/

+#if (!MSU_R_IS_INLINE)

+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)

+{

+    Word16 var_out;

+

+    L_var3 = L_msu (L_var3, var1, var2);

+    L_var3 = L_add (L_var3, (Word32) 0x00008000L);

+    var_out = extract_h (L_var3);

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_deposit_h                                             |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The   |

+ |   16 LS bits of the output are zeroed.                                    |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= var_out <= 0x7fff 0000.                |

+ |___________________________________________________________________________|

+*/

+//Word32 L_deposit_h (Word16 var1)

+//{

+//    Word32 L_var_out;

+//

+//    L_var_out = (Word32) var1 << 16;

+//

+//    return (L_var_out);

+//}

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_deposit_l                                             |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The   |

+ |   16 MS bits of the output are sign extended.                             |

+ |                                                                           |

+ |   Complexity weight : 2                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0xFFFF 8000 <= var_out <= 0x0000 7fff.                |

+ |___________________________________________________________________________|

+*/

+//Word32 L_deposit_l (Word16 var1)

+//{

+//    Word32 L_var_out;

+//

+//    L_var_out = (Word32) var1;

+//

+//    return (L_var_out);

+//}

+

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_shr_r                                                 |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Same as L_shr(L_var1,var2) but with rounding. Saturate the result in    |

+ |   case of underflows or overflows :                                       |

+ |    - If var2 is greater than zero :                                       |

+ |          if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|

+ |          is equal to zero                                                 |

+ |                     then                                                  |

+ |                     L_shr_r(L_var1,var2) = L_shr(L_var1,var2)             |

+ |                     else                                                  |

+ |                     L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1)    |

+ |    - If var2 is less than or equal to zero :                              |

+ |                     L_shr_r(L_var1,var2) = L_shr(L_var1,var2).            |

+ |                                                                           |

+ |   Complexity weight : 3                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1                                                                 |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= var_out <= 0x7fff ffff.                |

+ |___________________________________________________________________________|

+*/

+#if (!L_SHR_R_IS_INLINE)

+Word32 L_shr_r (Word32 L_var1, Word16 var2)

+{

+    Word32 L_var_out;

+

+    if (var2 > 31)

+    {

+        L_var_out = 0;

+    }

+    else

+    {

+        L_var_out = L_shr (L_var1, var2);

+

+        if (var2 > 0)

+        {

+            if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)

+            {

+                L_var_out++;

+            }

+        }

+    }

+

+    return (L_var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : L_abs                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |    Absolute value of L_var1; Saturate in case where the input is          |

+ |                                                               -214783648  |

+ |                                                                           |

+ |   Complexity weight : 3                                                   |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1                                                                 |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    L_var_out                                                              |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x0000 0000 <= var_out <= 0x7fff ffff.                |

+ |___________________________________________________________________________|

+*/

+//Word32 L_abs (Word32 L_var1)

+//{

+//    Word32 L_var_out;

+//

+//    if (L_var1 == MIN_32)

+//    {

+//        L_var_out = MAX_32;

+//    }

+//    else

+//    {

+//        if (L_var1 < 0)

+//        {

+//            L_var_out = -L_var1;

+//        }

+//        else

+//        {

+//            L_var_out = L_var1;

+//        }

+//    }

+//

+//    return (L_var_out);

+//}

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : norm_s                                                  |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Produces the number of left shift needed to normalize the 16 bit varia- |

+ |   ble var1 for positive values on the interval with minimum of 16384 and  |

+ |   maximum of 32767, and for negative values on the interval with minimum  |

+ |   of -32768 and maximum of -16384; in order to normalize the result, the  |

+ |   following operation must be done :                                      |

+ |                    norm_var1 = shl(var1,norm_s(var1)).                    |

+ |                                                                           |

+ |   Complexity weight : 15                                                  |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0x0000 0000 <= var_out <= 0x0000 000f.                |

+ |___________________________________________________________________________|

+*/

+

+#if (!NORM_S_IS_INLINE)

+Word16 norm_s (Word16 var1)

+{

+    Word16 var_out;

+

+    if (var1 == 0)

+    {

+        var_out = 0;

+    }

+    else

+    {

+        if (var1 == -1)

+        {

+            var_out = 15;

+        }

+        else

+        {

+            if (var1 < 0)

+            {

+                var1 = (Word16)~var1;

+            }

+            for (var_out = 0; var1 < 0x4000; var_out++)

+            {

+                var1 <<= 1;

+            }

+        }

+    }

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : div_s                                                   |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Produces a result which is the fractional integer division of var1  by  |

+ |   var2; var1 and var2 must be positive and var2 must be greater or equal  |

+ |   to var1; the result is positive (leading bit equal to 0) and truncated  |

+ |   to 16 bits.                                                             |

+ |   If var1 = var2 then div(var1,var2) = 32767.                             |

+ |                                                                           |

+ |   Complexity weight : 18                                                  |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    var1                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0x0000 0000 <= var1 <= var2 and var2 != 0.            |

+ |                                                                           |

+ |    var2                                                                   |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : var1 <= var2 <= 0x0000 7fff and var2 != 0.            |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0x0000 0000 <= var_out <= 0x0000 7fff.                |

+ |             It's a Q15 value (point between b15 and b14).                 |

+ |___________________________________________________________________________|

+*/

+

+#if (!DIV_S_IS_INLINE)

+Word16 div_s (Word16 var1, Word16 var2)

+{

+    Word16 var_out = 0;

+    Word16 iteration;

+    Word32 L_num;

+    Word32 L_denom;

+

+    if (var1 == 0)

+    {

+        var_out = 0;

+    }

+    else

+    {

+        if (var1 == var2)

+        {

+            var_out = MAX_16;

+        }

+        else

+        {

+            L_num = L_deposit_l (var1);

+            L_denom = L_deposit_l (var2);

+

+            for (iteration = 0; iteration < 15; iteration++)

+            {

+                var_out <<= 1;

+                L_num <<= 1;

+

+                if (L_num >= L_denom)

+                {

+                    L_num = L_sub(L_num, L_denom);

+                    var_out = add (var_out, 1);

+                }

+            }

+        }

+    }

+

+    return (var_out);

+}

+#endif

+

+/*___________________________________________________________________________

+ |                                                                           |

+ |   Function Name : norm_l                                                  |

+ |                                                                           |

+ |   Purpose :                                                               |

+ |                                                                           |

+ |   Produces the number of left shifts needed to normalize the 32 bit varia-|

+ |   ble L_var1 for positive values on the interval with minimum of          |

+ |   1073741824 and maximum of 2147483647, and for negative values on the in-|

+ |   terval with minimum of -2147483648 and maximum of -1073741824; in order |

+ |   to normalize the result, the following operation must be done :         |

+ |                   norm_L_var1 = L_shl(L_var1,norm_l(L_var1)).             |

+ |                                                                           |

+ |   Complexity weight : 30                                                  |

+ |                                                                           |

+ |   Inputs :                                                                |

+ |                                                                           |

+ |    L_var1                                                                 |

+ |             32 bit long signed integer (Word32) whose value falls in the  |

+ |             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |

+ |                                                                           |

+ |   Outputs :                                                               |

+ |                                                                           |

+ |    none                                                                   |

+ |                                                                           |

+ |   Return Value :                                                          |

+ |                                                                           |

+ |    var_out                                                                |

+ |             16 bit short signed integer (Word16) whose value falls in the |

+ |             range : 0x0000 0000 <= var_out <= 0x0000 001f.                |

+ |___________________________________________________________________________|

+*/

+

+#if (!NORM_L_IS_INLINE)

+Word16 norm_l (Word32 L_var1)

+{

+    Word16 var_out;

+

+    if (L_var1 == 0)

+    {

+        var_out = 0;

+    }

+    else

+    {

+        if (L_var1 == (Word32) 0xffffffffL)

+        {

+            var_out = 31;

+        }

+        else

+        {

+            if (L_var1 < 0)

+            {

+                L_var1 = ~L_var1;

+            }

+            for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)

+            {

+                L_var1 <<= 1;

+            }

+        }

+    }

+

+    return (var_out);

+}

+#endif

+
diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
new file mode 100644
index 0000000..906a9df
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
@@ -0,0 +1,361 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		oper_32b.c

+

+	Content:	  This file contains operations in double precision.
+ 

+*******************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+
+/*****************************************************************************
+ *                                                                           *
+ *  Function L_Extract()                                                     *
+ *                                                                           *
+ *  Extract from a 32 bit integer two 16 bit DPF.                            *
+ *                                                                           *
+ *  Arguments:                                                               *
+ *                                                                           *
+ *   L_32      : 32 bit integer.                                             *
+ *               0x8000 0000 <= L_32 <= 0x7fff ffff.                         *
+ *   hi        : b16 to b31 of L_32                                          *
+ *   lo        : (L_32 - hi<<16)>>1                                          *
+ *****************************************************************************
+*/
+
+void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo)
+{
+    *hi = extract_h (L_32);
+    *lo = extract_l (L_msu (L_shr (L_32, 1), *hi, 16384));
+    return;
+}
+
+/*****************************************************************************
+ *                                                                           *
+ *  Function L_Comp()                                                        *
+ *                                                                           *
+ *  Compose from two 16 bit DPF a 32 bit integer.                            *
+ *                                                                           *
+ *     L_32 = hi<<16 + lo<<1                                                 *
+ *                                                                           *
+ *  Arguments:                                                               *
+ *                                                                           *
+ *   hi        msb                                                           *
+ *   lo        lsf (with sign)                                               *
+ *                                                                           *
+ *   Return Value :                                                          *
+ *                                                                           *
+ *             32 bit long signed integer (Word32) whose value falls in the  *
+ *             range : 0x8000 0000 <= L_32 <= 0x7fff fff0.                   *
+ *                                                                           *
+ *****************************************************************************
+*/
+
+Word32 L_Comp (Word16 hi, Word16 lo)
+{
+    Word32 L_32;
+
+    L_32 = L_deposit_h (hi);
+    return (L_mac (L_32, lo, 1));       /* = hi<<16 + lo<<1 */
+}
+
+/*****************************************************************************
+ * Function Mpy_32()                                                         *
+ *                                                                           *
+ *   Multiply two 32 bit integers (DPF). The result is divided by 2**31      *
+ *                                                                           *
+ *   L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1              *
+ *                                                                           *
+ *   This operation can also be viewed as the multiplication of two Q31      *
+ *   number and the result is also in Q31.                                   *
+ *                                                                           *
+ * Arguments:                                                                *
+ *                                                                           *
+ *  hi1         hi part of first number                                      *
+ *  lo1         lo part of first number                                      *
+ *  hi2         hi part of second number                                     *
+ *  lo2         lo part of second number                                     *
+ *                                                                           *
+ *****************************************************************************
+*/
+
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)
+{
+    Word32 L_32;
+
+    L_32 = L_mult (hi1, hi2);
+    L_32 = L_mac (L_32, mult (hi1, lo2), 1);
+    L_32 = L_mac (L_32, mult (lo1, hi2), 1);
+
+    return (L_32);
+}
+
+/*****************************************************************************
+ * Function Mpy_32_16()                                                      *
+ *                                                                           *
+ *   Multiply a 16 bit integer by a 32 bit (DPF). The result is divided      *
+ *   by 2**15                                                                *
+ *                                                                           *
+ *                                                                           *
+ *   L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1                                *
+ *                                                                           *
+ * Arguments:                                                                *
+ *                                                                           *
+ *  hi          hi part of 32 bit number.                                    *
+ *  lo          lo part of 32 bit number.                                    *
+ *  n           16 bit number.                                               *
+ *                                                                           *
+ *****************************************************************************
+*/
+
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n)
+{
+    Word32 L_32;
+
+    L_32 = L_mult (hi, n);
+    L_32 = L_mac (L_32, mult (lo, n), 1);
+
+    return (L_32);
+}
+
+/*****************************************************************************
+ *                                                                           *
+ *   Function Name : Div_32                                                  *
+ *                                                                           *
+ *   Purpose :                                                               *
+ *             Fractional integer division of two 32 bit numbers.            *
+ *             L_num / L_denom.                                              *
+ *             L_num and L_denom must be positive and L_num < L_denom.       *
+ *             L_denom = denom_hi<<16 + denom_lo<<1                          *
+ *             denom_hi is a normalize number.                               *
+ *                                                                           *
+ *   Inputs :                                                                *
+ *                                                                           *
+ *    L_num                                                                  *
+ *             32 bit long signed integer (Word32) whose value falls in the  *
+ *             range : 0x0000 0000 < L_num < L_denom                         *
+ *                                                                           *
+ *    L_denom = denom_hi<<16 + denom_lo<<1      (DPF)                        *
+ *                                                                           *
+ *       denom_hi                                                            *
+ *             16 bit positive normalized integer whose value falls in the   *
+ *             range : 0x4000 < hi < 0x7fff                                  *
+ *       denom_lo                                                            *
+ *             16 bit positive integer whose value falls in the              *
+ *             range : 0 < lo < 0x7fff                                       *
+ *                                                                           *
+ *   Return Value :                                                          *
+ *                                                                           *
+ *    L_div                                                                  *
+ *             32 bit long signed integer (Word32) whose value falls in the  *
+ *             range : 0x0000 0000 <= L_div <= 0x7fff ffff.                  *
+ *                                                                           *
+ *  Algorithm:                                                               *
+ *                                                                           *
+ *  - find = 1/L_denom.                                                      *
+ *      First approximation: approx = 1 / denom_hi                           *
+ *      1/L_denom = approx * (2.0 - L_denom * approx )                       *
+ *                                                                           *
+ *  -  result = L_num * (1/L_denom)                                          *
+ *****************************************************************************
+*/
+
+Word32 Div_32 (Word32 L_num, Word32 denom)
+{
+    Word16 approx;
+    Word32 L_32;
+    /* First approximation: 1 / L_denom = 1/denom_hi */
+
+    approx = div_s ((Word16) 0x3fff, denom >> 16);
+
+    /* 1/L_denom = approx * (2.0 - L_denom * approx) */
+
+    L_32 = L_mpy_ls (denom, approx);
+
+    L_32 = L_sub ((Word32) 0x7fffffffL, L_32);
+
+	L_32 = L_mpy_ls (L_32, approx);
+    /* L_num * (1/L_denom) */
+
+	L_32 = MULHIGH(L_32, L_num);
+    L_32 = L_shl (L_32, 3);
+
+    return (L_32);
+}
+

+/*!

+ 

+  \brief  calculates the log dualis times 4 of argument 

+          iLog4(x) = (Word32)(4 * log(value)/log(2.0))

+

+  \return ilog4 value

+ 

+*/

+Word16 iLog4(Word32 value)

+{

+  Word16 iLog4;

+

+  if(value != 0){

+    Word32 tmp;

+    Word16 tmp16;

+    iLog4 = norm_l(value);

+    tmp = (value << iLog4);

+    tmp16 = round16(tmp);

+    tmp = L_mult(tmp16, tmp16);

+    tmp16 = round16(tmp);

+    tmp = L_mult(tmp16, tmp16);

+    tmp16 = round16(tmp);

+

+    iLog4 = (-(iLog4 << 2) - norm_s(tmp16)) - 1;

+  }

+  else {

+    iLog4 = -128; /* -(INT_BITS*4); */                                          

+  }

+

+  return iLog4;

+}

+

+#define step(shift) \

+    if ((0x40000000l >> shift) + root <= value)       \

+    {                                                 \

+        value -= (0x40000000l >> shift) + root;       \

+        root = (root >> 1) | (0x40000000l >> shift);  \

+    } else {                                          \

+        root = root >> 1;                             \

+    }

+

+Word32 rsqrt(Word32 value,     /*!< Operand to square root (0.0 ... 1) */

+             Word32 accuracy)  /*!< Number of valid bits that will be calculated */

+{

+    Word32 root = 0;

+	Word32 scale;

+

+	if(value < 0)

+		return 0;

+

+	scale = norm_l(value);

+	if(scale & 1) scale--;

+

+	value <<= scale;

+

+	step( 0); step( 2); step( 4); step( 6);

+    step( 8); step(10); step(12); step(14);

+    step(16); step(18); step(20); step(22);

+    step(24); step(26); step(28); step(30);

+

+    scale >>= 1;

+	if (root < value)

+        ++root;

+

+	root >>= scale;

+    return root* 46334;

+}

+

+static const Word32 pow2Table[POW2_TABLE_SIZE] = {

+0x7fffffff, 0x7fa765ad, 0x7f4f08ae, 0x7ef6e8da, 

+0x7e9f0606, 0x7e476009, 0x7deff6b6, 0x7d98c9e6, 

+0x7d41d96e, 0x7ceb2523, 0x7c94acde, 0x7c3e7073, 

+0x7be86fb9, 0x7b92aa88, 0x7b3d20b6, 0x7ae7d21a, 

+0x7a92be8b, 0x7a3de5df, 0x79e947ef, 0x7994e492, 

+0x7940bb9e, 0x78ecccec, 0x78991854, 0x78459dac, 

+0x77f25cce, 0x779f5591, 0x774c87cc, 0x76f9f359, 

+0x76a7980f, 0x765575c8, 0x76038c5b, 0x75b1dba2, 

+0x75606374, 0x750f23ab, 0x74be1c20, 0x746d4cac, 

+0x741cb528, 0x73cc556d, 0x737c2d55, 0x732c3cba, 

+0x72dc8374, 0x728d015d, 0x723db650, 0x71eea226, 

+0x719fc4b9, 0x71511de4, 0x7102ad80, 0x70b47368, 

+0x70666f76, 0x7018a185, 0x6fcb096f, 0x6f7da710, 

+0x6f307a41, 0x6ee382de, 0x6e96c0c3, 0x6e4a33c9, 

+0x6dfddbcc, 0x6db1b8a8, 0x6d65ca38, 0x6d1a1057, 

+0x6cce8ae1, 0x6c8339b2, 0x6c381ca6, 0x6bed3398, 

+0x6ba27e66, 0x6b57fce9, 0x6b0daeff, 0x6ac39485, 

+0x6a79ad56, 0x6a2ff94f, 0x69e6784d, 0x699d2a2c, 

+0x69540ec9, 0x690b2601, 0x68c26fb1, 0x6879ebb6, 

+0x683199ed, 0x67e97a34, 0x67a18c68, 0x6759d065, 

+0x6712460b, 0x66caed35, 0x6683c5c3, 0x663ccf92, 

+0x65f60a80, 0x65af766a, 0x6569132f, 0x6522e0ad, 

+0x64dcdec3, 0x64970d4f, 0x64516c2e, 0x640bfb41, 

+0x63c6ba64, 0x6381a978, 0x633cc85b, 0x62f816eb, 

+0x62b39509, 0x626f4292, 0x622b1f66, 0x61e72b65, 

+0x61a3666d, 0x615fd05f, 0x611c6919, 0x60d9307b, 

+0x60962665, 0x60534ab7, 0x60109d51, 0x5fce1e12, 

+0x5f8bccdb, 0x5f49a98c, 0x5f07b405, 0x5ec5ec26, 

+0x5e8451d0, 0x5e42e4e3, 0x5e01a540, 0x5dc092c7, 

+0x5d7fad59, 0x5d3ef4d7, 0x5cfe6923, 0x5cbe0a1c, 

+0x5c7dd7a4, 0x5c3dd19c, 0x5bfdf7e5, 0x5bbe4a61, 

+0x5b7ec8f2, 0x5b3f7377, 0x5b0049d4, 0x5ac14bea, 

+0x5a82799a, 0x5a43d2c6, 0x5a055751, 0x59c7071c, 

+0x5988e209, 0x594ae7fb, 0x590d18d3, 0x58cf7474, 

+0x5891fac1, 0x5854ab9b, 0x581786e6, 0x57da8c83, 

+0x579dbc57, 0x57611642, 0x57249a29, 0x56e847ef, 

+0x56ac1f75, 0x567020a0, 0x56344b52, 0x55f89f70, 

+0x55bd1cdb, 0x5581c378, 0x55469329, 0x550b8bd4, 

+0x54d0ad5b, 0x5495f7a1, 0x545b6a8b, 0x542105fd, 

+0x53e6c9db, 0x53acb607, 0x5372ca68, 0x533906e0, 

+0x52ff6b55, 0x52c5f7aa, 0x528cabc3, 0x52538786, 

+0x521a8ad7, 0x51e1b59a, 0x51a907b4, 0x5170810b, 

+0x51382182, 0x50ffe8fe, 0x50c7d765, 0x508fec9c, 

+0x50582888, 0x50208b0e, 0x4fe91413, 0x4fb1c37c, 

+0x4f7a9930, 0x4f439514, 0x4f0cb70c, 0x4ed5ff00, 

+0x4e9f6cd4, 0x4e69006e, 0x4e32b9b4, 0x4dfc988c, 

+0x4dc69cdd, 0x4d90c68b, 0x4d5b157e, 0x4d25899c, 

+0x4cf022ca, 0x4cbae0ef, 0x4c85c3f1, 0x4c50cbb8, 

+0x4c1bf829, 0x4be7492b, 0x4bb2bea5, 0x4b7e587d, 

+0x4b4a169c, 0x4b15f8e6, 0x4ae1ff43, 0x4aae299b, 

+0x4a7a77d5, 0x4a46e9d6, 0x4a137f88, 0x49e038d0, 

+0x49ad1598, 0x497a15c4, 0x4947393f, 0x49147fee, 

+0x48e1e9ba, 0x48af768a, 0x487d2646, 0x484af8d6, 

+0x4818ee22, 0x47e70611, 0x47b5408c, 0x47839d7b, 

+0x47521cc6, 0x4720be55, 0x46ef8210, 0x46be67e0, 

+0x468d6fae, 0x465c9961, 0x462be4e2, 0x45fb521a, 

+0x45cae0f2, 0x459a9152, 0x456a6323, 0x453a564d, 

+0x450a6abb, 0x44daa054, 0x44aaf702, 0x447b6ead, 

+0x444c0740, 0x441cc0a3, 0x43ed9ac0, 0x43be9580, 

+0x438fb0cb, 0x4360ec8d, 0x433248ae, 0x4303c517, 

+0x42d561b4, 0x42a71e6c, 0x4278fb2b, 0x424af7da, 

+0x421d1462, 0x41ef50ae, 0x41c1aca8, 0x41942839, 

+0x4166c34c, 0x41397dcc, 0x410c57a2, 0x40df50b8, 

+0x40b268fa, 0x4085a051, 0x4058f6a8, 0x402c6be9 

+};

+

+/*!

+ 

+  \brief calculates 2 ^ (x/y) for x<=0, y > 0, x <= 32768 * y 

+  

+  avoids integer division

+  

+  \return 

+*/

+Word32 pow2_xy(Word32 x, Word32 y)

+{

+  Word32 iPart;

+  Word32 fPart;

+  Word32 res;

+  Word32 tmp, tmp2;

+  Word32 shift, shift2;

+

+  tmp2 = -x;

+  iPart = tmp2 / y;

+  fPart = tmp2 - iPart*y;

+  iPart = min(iPart,INT_BITS-1);

+

+  res = pow2Table[(POW2_TABLE_SIZE*fPart)/y] >> iPart; 

+ 

+  return(res);

+}
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h
new file mode 100644
index 0000000..4119bc3
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h
@@ -0,0 +1,89 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		oper_32b.h

+

+	Content:	Double precision operations

+

+*******************************************************************************/
+
+#ifndef __OPER_32b_H
+#define __OPER_32b_H
+

+#include "typedef.h"

+
+#ifdef __cplusplus
+extern "C" {
+#endif
+

+#define POW2_TABLE_BITS 8

+#define POW2_TABLE_SIZE (1<<POW2_TABLE_BITS)

+
+void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo);
+Word32 L_Comp (Word16 hi, Word16 lo);
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n);
+Word32 Div_32 (Word32 L_num, Word32 denom);
+Word16 iLog4(Word32 value);

+Word32 rsqrt(Word32 value,  Word32 accuracy);

+Word32 pow2_xy(Word32 x, Word32 y);

+

+__inline Word32 L_mpy_ls(Word32 L_var2, Word16 var1)

+{

+    unsigned short swLow1;

+    Word16 swHigh1;

+    Word32 l_var_out;

+

+    swLow1 = (unsigned short)(L_var2);

+    swHigh1 = (Word16)(L_var2 >> 16);

+

+    l_var_out = (long)swLow1 * (long)var1 >> 15;

+    

+    l_var_out += swHigh1 * var1 << 1;

+    

+    return(l_var_out);

+}

+

+__inline Word32 L_mpy_wx(Word32 L_var2, Word16 var1)

+{

+#if ARMV5TE_L_MPY_LS

+	Word32 result; 

+	asm volatile( 

+		"SMULWB  %[result], %[L_var2], %[var1] \n" 

+		:[result]"+r"(result)

+		:[L_var2]"r"(L_var2), [var1]"r"(var1)

+		); 

+	return result;

+#else

+    unsigned short swLow1;

+    Word16 swHigh1;

+    Word32 l_var_out;

+

+    swLow1 = (unsigned short)(L_var2);

+    swHigh1 = (Word16)(L_var2 >> 16);

+

+    l_var_out = (long)swLow1 * (long)var1 >> 16;    

+    l_var_out += swHigh1 * var1;

+    

+    return(l_var_out);

+#endif

+}

+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/basic_op/typedef.h b/media/libstagefright/codecs/aacenc/basic_op/typedef.h
new file mode 100644
index 0000000..d3a626a
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/typedef.h
@@ -0,0 +1,63 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		typedef.h

+

+	Content:	type defined for defferent paltform

+

+*******************************************************************************/
+
+#ifndef typedef_h
+#define typedef_h "$Id $"
+
+#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version
+                             of typedef.h                           */
+
+#ifdef ORIGINAL_TYPEDEF_H
+/*
+ * this is the original code from the ETSI file typedef.h
+ */
+   
+#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__)
+typedef signed char Word8;
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__sun)
+typedef signed char Word8;
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__unix__) || defined(__unix)
+typedef signed char Word8;
+typedef short Word16;
+typedef int Word32;
+typedef int Flag;
+
+#endif
+#else /* not original typedef.h */
+
+/*
+ * use (improved) type definition file typdefs.h and add a "Flag" type
+ */

+#include "typedefs.h"
+typedef int Flag;
+
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/basic_op/typedefs.h b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h
new file mode 100644
index 0000000..7d16fca
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h
@@ -0,0 +1,179 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		typedefs.h

+

+	Content:	type defined or const defined

+

+*******************************************************************************/
+
+#ifndef typedefs_h
+#define typedefs_h "$Id $"
+
+#ifndef CHAR_BIT

+#define CHAR_BIT      8         /* number of bits in a char */

+#endif

+

+#ifndef VOAAC_SHRT_MAX

+#define VOAAC_SHRT_MAX    (32767)        /* maximum (signed) short value */

+#endif

+
+#ifndef VOAAC_SHRT_MIN

+#define VOAAC_SHRT_MIN    (-32768)        /* minimum (signed) short value */

+#endif

+
+/* Define NULL pointer value */

+#ifndef NULL

+#ifdef __cplusplus

+#define NULL    0

+#else

+#define NULL    ((void *)0)

+#endif

+#endif
+
+#ifndef assert
+#define assert(_Expression)     ((void)0)
+#endif
+

+#ifdef LINUX

+#define __inline static __inline__

+#endif

+
+#define INT_BITS   32
+/*
+********************************************************************************
+*                         DEFINITION OF CONSTANTS 
+********************************************************************************
+*/
+/*
+ ********* define char type
+ */
+typedef char Char;
+
+/*
+ ********* define 8 bit signed/unsigned types & constants
+ */
+typedef signed char Word8;
+typedef unsigned char UWord8;
+/*
+ ********* define 16 bit signed/unsigned types & constants
+ */
+typedef short Word16;
+typedef unsigned short UWord16;
+
+/*
+ ********* define 32 bit signed/unsigned types & constants
+ */
+typedef long Word32;
+typedef unsigned long UWord32;
+
+

+

+#ifdef LINUX
+typedef long long Word64;
+typedef unsigned long long UWord64;
+#else
+typedef __int64 Word64;

+typedef unsigned __int64 UWord64;
+#endif
+
+#ifndef min

+#define min(a,b) ( a < b ? a : b)

+#endif

+

+#ifndef max

+#define max(a,b) ( a > b ? a : b)

+#endif

+

+#ifdef ARM_INASM

+#ifdef ARMV5_INASM

+#define ARMV5E_INASM	1

+#endif

+#define ARMV4_INASM		1

+#endif

+
+#if ARMV4_INASM

+	#define ARMV5TE_SAT           1

+    #define ARMV5TE_ADD           1

+    #define ARMV5TE_SUB           1

+	#define ARMV5TE_SHL           1

+    #define ARMV5TE_SHR           1

+	#define ARMV5TE_L_SHL         1

+    #define ARMV5TE_L_SHR         1

+#endif//ARMV4

+#if ARMV5E_INASM

+    #define ARMV5TE_L_ADD         1

+    #define ARMV5TE_L_SUB         1

+    #define ARMV5TE_L_MULT        1

+    #define ARMV5TE_L_MAC         1

+    #define ARMV5TE_L_MSU         1

+   

+    

+    #define ARMV5TE_DIV_S         1

+    #define ARMV5TE_ROUND         1

+    #define ARMV5TE_MULT          1

+    

+    #define ARMV5TE_NORM_S        1

+    #define ARMV5TE_NORM_L        1

+	#define ARMV5TE_L_MPY_LS	  1

+#endif
+

+//basic operation functions optimization flags

+#define SATRUATE_IS_INLINE              1   //define saturate as inline function

+#define SHL_IS_INLINE                   1  //define shl as inline function

+#define SHR_IS_INLINE                   1   //define shr as inline function

+#define L_MULT_IS_INLINE                1   //define L_mult as inline function

+#define L_MSU_IS_INLINE                 1   //define L_msu as inline function

+#define L_SUB_IS_INLINE                 1   //define L_sub as inline function

+#define L_SHL_IS_INLINE                 1   //define L_shl as inline function

+#define L_SHR_IS_INLINE                 1   //define L_shr as inline function

+#define ADD_IS_INLINE                   1   //define add as inline function //add, inline is the best

+#define SUB_IS_INLINE                   1   //define sub as inline function //sub, inline is the best

+#define DIV_S_IS_INLINE                 1   //define div_s as inline function

+#define MULT_IS_INLINE                  1   //define mult as inline function

+#define NORM_S_IS_INLINE                1   //define norm_s as inline function

+#define NORM_L_IS_INLINE                1   //define norm_l as inline function

+#define ROUND_IS_INLINE                 1   //define round as inline function

+#define L_MAC_IS_INLINE                 1   //define L_mac as inline function

+#define L_ADD_IS_INLINE                 1   //define L_add as inline function

+#define EXTRACT_H_IS_INLINE             1   //define extract_h as inline function 

+#define EXTRACT_L_IS_INLINE             1   //define extract_l as inline function        //???

+#define MULT_R_IS_INLINE                1   //define mult_r as inline function

+#define SHR_R_IS_INLINE                 1   //define shr_r as inline function

+#define MAC_R_IS_INLINE                 1   //define mac_r as inline function

+#define MSU_R_IS_INLINE                 1   //define msu_r as inline function

+#define L_SHR_R_IS_INLINE               1   //define L_shr_r as inline function

+

+#define PREFIX				voAACEnc

+#define LINK0(x, y, z)		LINK1(x,y,z)

+#define LINK1(x,y,z)		x##y##z

+#define ADD_PREFIX(func)	LINK0(PREFIX, _, func)

+

+#define  L_Extract		ADD_PREFIX(L_Extract)

+#define  L_Comp			ADD_PREFIX(L_Comp)

+#define  Mpy_32			ADD_PREFIX(Mpy_32)

+#define  Mpy_32_16		ADD_PREFIX(Mpy_32_16)

+#define  Div_32			ADD_PREFIX(Div_32)

+#define  iLog4			ADD_PREFIX(iLog4)

+#define  rsqrt			ADD_PREFIX(rsqrt)

+#define  pow2_xy		ADD_PREFIX(pow2_xy)

+#define  L_mpy_ls		ADD_PREFIX(L_mpy_ls)

+#define  L_mpy_wx		ADD_PREFIX(L_mpy_wx)

+

+#define mem_malloc		ADD_PREFIX(mem_malloc)

+#define mem_free		ADD_PREFIX(mem_free)

+

+#endif
diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile
new file mode 100644
index 0000000..b4f63af
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile
@@ -0,0 +1,55 @@
+#/*

+#** Copyright 2003-2010, VisualOn, Inc.

+#**

+#** 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.

+#*/

+

+# target6

+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

+VOTT:= v5

+

+

+# module type

+# please specify the type of your module: lib or exe

+VOMT:= lib

+

+

+# module macros

+# please append the additional macro definitions here for your module if necessary. 

+# e.g. -DVISUALON, macro VISUALON defined for your module 

+VOMM:= -DARMV5E -DARM_INASM -DARMV5_INASM 

+

+

+

+# please specify the name of your module

+VOTARGET:=libvoAACEncv5

+

+

+# please modify here to be sure to see the g1.mk

+include ../../../../../Tools/eclair.mk 

+

+# dependent libraries.

+VODEPLIBS:=#-ldl -lstdc++ 

+

+# module source

+# please modify here to be sure to see the ms.mk which specifies all source info of your module

+include ../../ms.mk

+

+

+# please specify where is the voRelease on your PC, relative path is suggested

+VORELDIR:=../../../../../../Release

+

+

+# please modify here to be sure to see the doit.mk

+include ../../../../../Tools/doit.mk 

+

diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile
new file mode 100644
index 0000000..cdce2c1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile
@@ -0,0 +1,55 @@
+#/*

+#** Copyright 2003-2010, VisualOn, Inc.

+#**

+#** 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.

+#*/

+

+# target6

+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

+VOTT:= v7

+

+

+# module type

+# please specify the type of your module: lib or exe

+VOMT:= lib

+

+

+# module macros

+# please append the additional macro definitions here for your module if necessary. 

+# e.g. -DVISUALON, macro VISUALON defined for your module 

+VOMM:= -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM 

+

+

+

+# please specify the name of your module

+VOTARGET:=libvoAACEncv7

+

+

+# please modify here to be sure to see the g1.mk

+include ../../../../../Tools/eclair.mk 

+

+# dependent libraries.

+VODEPLIBS:=#-ldl -lstdc++ 

+

+# module source

+# please modify here to be sure to see the ms.mk which specifies all source info of your module

+include ../../ms.mk

+

+

+# please specify where is the voRelease on your PC, relative path is suggested

+VORELDIR:=../../../../../../Release

+

+

+# please modify here to be sure to see the doit.mk

+include ../../../../../Tools/doit.mk  

+

diff --git a/media/libstagefright/codecs/aacenc/build/eclair/makefile b/media/libstagefright/codecs/aacenc/build/eclair/makefile
new file mode 100644
index 0000000..6bb3c13
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/build/eclair/makefile
@@ -0,0 +1,40 @@
+#/*
+#** Copyright 2003-2010, VisualOn, Inc.
+#**
+#** 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.
+#*/
+
+# Just acting as Father Makefile of Modules
+# please keep the name 'makefile' unchanged
+ 
+# Module Subdirs
+VOMSD:=$(dir $(shell find . -name 'Makefile'))
+
+all:
+	for dir in $(VOMSD); \
+		do \
+			$(MAKE) -C $$dir; \
+		done
+
+.PHONY:clean devel
+clean:
+	for dir in $(VOMSD); \
+		do \
+			$(MAKE) -C $$dir clean; \
+		done
+
+devel:
+	for dir in $(VOMSD); \
+		do \
+			$(MAKE) -C $$dir devel; \
+		done
diff --git a/media/libstagefright/codecs/aacenc/build/ms.mk b/media/libstagefright/codecs/aacenc/build/ms.mk
new file mode 100644
index 0000000..b67efbc
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/build/ms.mk
@@ -0,0 +1,42 @@
+#/*

+#** Copyright 2003-2010, VisualOn, Inc.

+#**

+#** 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.

+#*/

+

+

+# please list all objects needed by your target here

+OBJS:=basicop2.o oper_32b.o aac_rom.o aacenc.o aacenc_core.o adj_thr.o \

+			band_nrg.o bit_cnt.o bitbuffer.o bitenc.o block_switch.o channel_map.o \

+			dyn_bits.o grp_data.o interface.o line_pe.o memalign.o ms_stereo.o \

+			pre_echo_control.o psy_configuration.o psy_main.o qc_main.o quantize.o sf_estim.o \

+			spreading.o stat_bits.o tns.o transform.o

+			

+# please list all directories that all source files relative with your module(.h .c .cpp) locate 

+VOSRCDIR:=../../../src \

+					../../../inc \

+					../../../basic_op\

+					../../../../../Include 

+					

+ifeq ($(VOTT), v5)

+OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \

+				PrePostMDCT_v5.o R4R8First_v5.o Radix4FFT_v5.o

+VOSRCDIR+= ../../../src/asm/ARMV5E/

+endif	

+

+ifeq ($(VOTT), v7)

+OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \

+			 PrePostMDCT_v7.o R4R8First_v7.o Radix4FFT_v7.o

+VOSRCDIR+= ../../../src/asm/ARMV5E/

+VOSRCDIR+= ../../../src/asm/ARMV7/

+endif		
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf b/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf
new file mode 100644
index 0000000..874d0f7
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf
Binary files differ
diff --git a/media/libstagefright/codecs/aacenc/inc/aac_rom.h b/media/libstagefright/codecs/aacenc/inc/aac_rom.h
new file mode 100644
index 0000000..b0429fc
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/aac_rom.h
@@ -0,0 +1,117 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		aac_rom.h

+

+	Content:	constant tables 

+

+*******************************************************************************/
+
+#ifndef ROM_H
+#define ROM_H
+

+#include "config.h"
+#include "psy_const.h"
+#include "tns_param.h"
+
+/*
+  mdct
+*/
+extern const int ShortWindowSine[FRAME_LEN_SHORT/2];
+extern const int LongWindowKBD[FRAME_LEN_LONG/2];

+

+extern const unsigned char bitrevTab[17 + 129];

+extern const int cossintab[128 + 1024];

+

+#if defined (ARMV5E) && !defined (ARMV7Neon)

+extern const int twidTab64[(4*6 + 16*6)/2];

+extern const int twidTab512[(8*6 + 32*6 + 128*6)/2];

+#else

+extern const int twidTab64[4*6 + 16*6];

+extern const int twidTab512[8*6 + 32*6 + 128*6];
+#endif
+
+/*
+  form factor
+*/
+extern const Word32 formfac_sqrttable[96];
+
+/*
+  quantizer
+*/
+extern const Word32 mTab_3_4[512];
+extern const Word32 mTab_4_3[512];
+/*! $2^{-\frac{n}{16}}$ table */
+extern const Word16 pow2tominusNover16[17] ;
+
+extern Word32 specExpMantTableComb_enc[4][14];
+extern const UWord8 specExpTableComb_enc[4][14];
+
+extern const Word16 quantBorders[4][4];
+//extern const Word16 quantRecon[3][4];

+extern const Word16 quantRecon[4][3];
+
+/*
+  huffman
+*/
+extern const UWord16 huff_ltab1_2[3][3][3][3];
+extern const UWord16 huff_ltab3_4[3][3][3][3];
+extern const UWord16 huff_ltab5_6[9][9];
+extern const UWord16 huff_ltab7_8[8][8];
+extern const UWord16 huff_ltab9_10[13][13];
+extern const UWord16 huff_ltab11[17][17];
+extern const UWord16 huff_ltabscf[121];
+extern const UWord16 huff_ctab1[3][3][3][3];
+extern const UWord16 huff_ctab2[3][3][3][3];
+extern const UWord16 huff_ctab3[3][3][3][3];
+extern const UWord16 huff_ctab4[3][3][3][3];
+extern const UWord16 huff_ctab5[9][9];
+extern const UWord16 huff_ctab6[9][9];
+extern const UWord16 huff_ctab7[8][8];
+extern const UWord16 huff_ctab8[8][8];
+extern const UWord16 huff_ctab9[13][13];
+extern const UWord16 huff_ctab10[13][13];
+extern const UWord16 huff_ctab11[17][17];
+extern const UWord32 huff_ctabscf[121];
+
+
+
+/*
+  misc
+*/
+extern const int sampRateTab[NUM_SAMPLE_RATES];

+extern const int BandwithCoefTab[8][NUM_SAMPLE_RATES];

+extern const int rates[8];

+extern const UWord8 sfBandTotalShort[NUM_SAMPLE_RATES];

+extern const UWord8 sfBandTotalLong[NUM_SAMPLE_RATES];

+extern const int sfBandTabShortOffset[NUM_SAMPLE_RATES];

+extern const short sfBandTabShort[76];

+extern const int sfBandTabLongOffset[NUM_SAMPLE_RATES];

+extern const short sfBandTabLong[325];

+
+extern const Word32 m_log2_table[INT_BITS];
+
+/*
+  TNS
+*/
+extern const Word32 tnsCoeff3[8];

+extern const Word32 tnsCoeff3Borders[8];

+extern const Word32 tnsCoeff4[16];

+extern const Word32 tnsCoeff4Borders[16];

+extern const Word32 invSBF[24];

+extern const Word16 sideInfoTabLong[MAX_SFB_LONG + 1];

+extern const Word16 sideInfoTabShort[MAX_SFB_SHORT + 1];
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/aacenc_core.h b/media/libstagefright/codecs/aacenc/inc/aacenc_core.h
new file mode 100644
index 0000000..faa1d20
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/aacenc_core.h
@@ -0,0 +1,117 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		aacenc_core.h

+

+	Content:	aac encoder interface functions

+

+*******************************************************************************/
+
+#ifndef _aacenc_core_h_
+#define _aacenc_core_h_
+
+

+#include "typedef.h"
+#include "config.h"

+#include "bitenc.h"

+

+#include "psy_configuration.h"

+#include "psy_main.h"

+#include "qc_main.h"

+#include "psy_main.h"

+/*-------------------------- defines --------------------------------------*/
+
+
+/*-------------------- structure definitions ------------------------------*/
+typedef  struct {
+  Word32   sampleRate;            /* audio file sample rate */
+  Word32   bitRate;               /* encoder bit rate in bits/sec */
+  Word16   nChannelsIn;           /* number of channels on input (1,2) */
+  Word16   nChannelsOut;          /* number of channels on output (1,2) */
+  Word16   bandWidth;             /* targeted audio bandwidth in Hz */

+  Word16   adtsUsed;			  /* whether write adts header */
+} AACENC_CONFIG;
+

+

+typedef struct {

+	

+  AACENC_CONFIG config;     /* Word16 size: 8 */

+

+  ELEMENT_INFO elInfo;      /* Word16 size: 4 */

+

+  QC_STATE qcKernel;        /* Word16 size: 6 + 5(PADDING) + 7(ELEMENT_BITS) + 54(ADJ_THR_STATE) = 72 */

+  QC_OUT   qcOut;           /* Word16 size: MAX_CHANNELS*920(QC_OUT_CHANNEL) + 5(QC_OUT_ELEMENT) + 7 = 932 / 1852 */

+

+  PSY_OUT    psyOut;        /* Word16 size: MAX_CHANNELS*186 + 2 = 188 / 374 */

+  PSY_KERNEL psyKernel;     /* Word16 size:  2587 / 4491 */

+

+  struct BITSTREAMENCODER_INIT bseInit; /* Word16 size: 6 */

+  struct BIT_BUF  bitStream;            /* Word16 size: 8 */

+  HANDLE_BIT_BUF  hBitStream;

+  int			  initOK;

+

+  short			*intbuf;

+  short			*encbuf;

+  short			*inbuf;

+  int			enclen;

+  int			inlen;

+  int			intlen;

+  int			uselength;

+

+  void			*hCheck;

+  VO_MEM_OPERATOR *voMemop;

+  VO_MEM_OPERATOR voMemoprator;

+

+}AAC_ENCODER; /* Word16 size: 3809 / 6851 */

+

+/*-----------------------------------------------------------------------------
+
+functionname: AacInitDefaultConfig
+description:  gives reasonable default configuration
+returns:      ---
+
+------------------------------------------------------------------------------*/
+void AacInitDefaultConfig(AACENC_CONFIG *config);
+
+/*---------------------------------------------------------------------------
+
+functionname:AacEncOpen
+description: allocate and initialize a new encoder instance
+returns:     AACENC_OK if success
+
+---------------------------------------------------------------------------*/
+
+Word16  AacEncOpen (AAC_ENCODER				*hAacEnc,       /* pointer to an encoder handle, initialized on return */
+                    const  AACENC_CONFIG     config);        /* pre-initialized config struct */
+
+Word16 AacEncEncode(AAC_ENCODER		   *hAacEnc,
+                    Word16             *timeSignal,
+                    const UWord8       *ancBytes,      /*!< pointer to ancillary data bytes */
+                    Word16             *numAncBytes,   /*!< number of ancillary Data Bytes, send as fill element  */
+                    UWord8             *outBytes,      /*!< pointer to output buffer            */
+                    Word32             *numOutBytes    /*!< number of bytes in output buffer */
+                    );
+
+/*---------------------------------------------------------------------------
+
+functionname:AacEncClose
+description: deallocate an encoder instance
+
+---------------------------------------------------------------------------*/
+
+void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP); /* an encoder handle */
+
+#endif /* _aacenc_h_ */
diff --git a/media/libstagefright/codecs/aacenc/inc/adj_thr.h b/media/libstagefright/codecs/aacenc/inc/adj_thr.h
new file mode 100644
index 0000000..4057cbe
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/adj_thr.h
@@ -0,0 +1,57 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		adj_thr.h

+

+	Content:	Threshold compensation function 

+

+*******************************************************************************/
+
+#ifndef __ADJ_THR_H
+#define __ADJ_THR_H
+
+#include "adj_thr_data.h"
+#include "qc_data.h"
+#include "interface.h"
+
+Word16 bits2pe(const Word16 bits);
+
+Word32 AdjThrNew(ADJ_THR_STATE** phAdjThr,
+                 Word32 nElements);
+
+void AdjThrDelete(ADJ_THR_STATE *hAdjThr);
+
+void AdjThrInit(ADJ_THR_STATE *hAdjThr,
+                const Word32 peMean,
+                Word32 chBitrate);
+
+void AdjustThresholds(ADJ_THR_STATE *adjThrState,
+                      ATS_ELEMENT* AdjThrStateElement,
+                      PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+                      PSY_OUT_ELEMENT *psyOutElement,
+                      Word16 *chBitDistribution,
+                      Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+                      Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],                      
+                      QC_OUT_ELEMENT* qcOE,
+					  ELEMENT_BITS* elBits,
+					  const Word16 nChannels,
+                      const Word16 maxBitFac);
+
+void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement,
+                  const Word16 dynBitsUsed);
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h b/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h
new file mode 100644
index 0000000..25dd437
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h
@@ -0,0 +1,69 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		adj_thr_data.h

+

+	Content:	Threshold compensation parameter 

+

+*******************************************************************************/
+
+#ifndef __ADJ_THR_DATA_H
+#define __ADJ_THR_DATA_H
+
+#include "typedef.h"

+#include "psy_const.h"
+#include "line_pe.h"
+
+typedef struct {
+   Word16 clipSaveLow, clipSaveHigh;
+   Word16 minBitSave, maxBitSave;
+   Word16 clipSpendLow, clipSpendHigh;
+   Word16 minBitSpend, maxBitSpend;
+} BRES_PARAM;
+
+typedef struct {
+   UWord8 modifyMinSnr;
+   Word16 startSfbL, startSfbS;
+} AH_PARAM;
+
+typedef struct {
+  Word32 maxRed;
+  Word32 startRatio, maxRatio;
+  Word32 redRatioFac;
+  Word32 redOffs;
+} MINSNR_ADAPT_PARAM;
+
+typedef struct {
+  /* parameters for bitreservoir control */
+  Word16 peMin, peMax;
+  /* constant offset to pe               */
+  Word16  peOffset;
+  /* avoid hole parameters               */
+  AH_PARAM ahParam;
+  /* paramters for adaptation of minSnr */
+  MINSNR_ADAPT_PARAM minSnrAdaptParam;
+  /* values for correction of pe */
+  Word16 peLast;
+  Word16 dynBitsLast;
+  Word16 peCorrectionFactor;
+} ATS_ELEMENT;
+
+typedef struct {
+  BRES_PARAM   bresParamLong, bresParamShort; /* Word16 size: 2*8 */
+  ATS_ELEMENT  adjThrStateElem;               /* Word16 size: 19 */
+} ADJ_THR_STATE;
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/band_nrg.h b/media/libstagefright/codecs/aacenc/inc/band_nrg.h
new file mode 100644
index 0000000..68509da
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/band_nrg.h
@@ -0,0 +1,46 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		band_nrg.h

+

+	Content:	Band/Line energy calculations functions

+

+*******************************************************************************/
+
+
+#ifndef _BAND_NRG_H
+#define _BAND_NRG_H
+
+#include "typedef.h"
+
+
+void CalcBandEnergy(const Word32 *mdctSpectrum,
+                    const Word16 *bandOffset,
+                    const Word16  numBands,
+                    Word32       *bandEnergy,
+                    Word32       *bandEnergySum);
+
+
+void CalcBandEnergyMS(const Word32 *mdctSpectrumLeft,
+                      const Word32 *mdctSpectrumRight,
+                      const Word16 *bandOffset,
+                      const Word16  numBands,
+                      Word32       *bandEnergyMid,
+                      Word32       *bandEnergyMidSum,
+                      Word32       *bandEnergySide,
+                      Word32       *bandEnergySideSum);
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/bit_cnt.h b/media/libstagefright/codecs/aacenc/inc/bit_cnt.h
new file mode 100644
index 0000000..808319e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/bit_cnt.h
@@ -0,0 +1,106 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		bit_cnt.h

+

+	Content:	Huffman Bitcounter & coder structure and functions

+

+*******************************************************************************/
+
+#ifndef __BITCOUNT_H
+#define __BITCOUNT_H
+
+#include "bitbuffer.h"

+#include "basic_op.h"
+#define INVALID_BITCOUNT (MAX_16/4)
+
+/*
+  code book number table
+*/
+
+enum codeBookNo{
+  CODE_BOOK_ZERO_NO=               0,
+  CODE_BOOK_1_NO=                  1,
+  CODE_BOOK_2_NO=                  2,
+  CODE_BOOK_3_NO=                  3,
+  CODE_BOOK_4_NO=                  4,
+  CODE_BOOK_5_NO=                  5,
+  CODE_BOOK_6_NO=                  6,
+  CODE_BOOK_7_NO=                  7,
+  CODE_BOOK_8_NO=                  8,
+  CODE_BOOK_9_NO=                  9,
+  CODE_BOOK_10_NO=                10,
+  CODE_BOOK_ESC_NO=               11,
+  CODE_BOOK_RES_NO=               12,
+  CODE_BOOK_PNS_NO=               13
+};
+
+/*
+  code book index table
+*/
+
+enum codeBookNdx{
+  CODE_BOOK_ZERO_NDX=0,
+  CODE_BOOK_1_NDX,
+  CODE_BOOK_2_NDX,
+  CODE_BOOK_3_NDX,
+  CODE_BOOK_4_NDX,
+  CODE_BOOK_5_NDX,
+  CODE_BOOK_6_NDX,
+  CODE_BOOK_7_NDX,
+  CODE_BOOK_8_NDX,
+  CODE_BOOK_9_NDX,
+  CODE_BOOK_10_NDX,
+  CODE_BOOK_ESC_NDX,
+  CODE_BOOK_RES_NDX,
+  CODE_BOOK_PNS_NDX,
+  NUMBER_OF_CODE_BOOKS
+};
+
+/*
+  code book lav table
+*/
+
+enum codeBookLav{
+  CODE_BOOK_ZERO_LAV=0,
+  CODE_BOOK_1_LAV=1,
+  CODE_BOOK_2_LAV=1,
+  CODE_BOOK_3_LAV=2,
+  CODE_BOOK_4_LAV=2,
+  CODE_BOOK_5_LAV=4,
+  CODE_BOOK_6_LAV=4,
+  CODE_BOOK_7_LAV=7,
+  CODE_BOOK_8_LAV=7,
+  CODE_BOOK_9_LAV=12,
+  CODE_BOOK_10_LAV=12,
+  CODE_BOOK_ESC_LAV=16,
+  CODE_BOOK_SCF_LAV=60,
+  CODE_BOOK_PNS_LAV=60
+};
+
+Word16 bitCount(const Word16 *aQuantSpectrum,
+                const Word16  noOfSpecLines,
+                Word16        maxVal,
+                Word16       *bitCountLut);
+
+Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF hBitstream);
+
+Word16 bitCountScalefactorDelta(Word16 delta);
+Word16 codeScalefactorDelta(Word16 scalefactor, HANDLE_BIT_BUF hBitstream);
+
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/bitbuffer.h b/media/libstagefright/codecs/aacenc/inc/bitbuffer.h
new file mode 100644
index 0000000..cb850c9
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/bitbuffer.h
@@ -0,0 +1,89 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		bitbuffer.h

+

+	Content:	Bit Buffer Management structure and functions

+

+*******************************************************************************/
+
+#ifndef BITBUFFER_H
+#define BITBUFFER_H
+
+#include "typedef.h"
+
+
+enum direction
+{
+  forwardDirection,
+  backwardDirection
+};
+
+
+/*!
+   The pointer 'pReadNext' points to the next available word, where bits can be read from. The pointer
+   'pWriteNext' points to the next available word, where bits can be written to. The pointer pBitBufBase
+   points to the start of the bitstream buffer and the pointer pBitBufEnd points to the end of the bitstream
+   buffer. The two pointers are used as lower-bound respectively upper-bound address for the modulo addressing
+   mode.
+
+   The element cntBits contains the currently available bits in the bit buffer. It will be incremented when
+   bits are written to the bitstream buffer and decremented when bits are read from the bitstream buffer.
+*/
+struct BIT_BUF
+{
+  UWord8 *pBitBufBase;          /*!< pointer points to first position in bitstream buffer */
+  UWord8 *pBitBufEnd;           /*!< pointer points to last position in bitstream buffer */
+
+  UWord8 *pWriteNext;           /*!< pointer points to next available word in bitstream buffer to write */
+
+  UWord32 cache;
+
+  Word16  wBitPos;              /*!< 31<=wBitPos<=0*/
+  Word16  cntBits;              /*!< number of available bits in the bitstream buffer
+                                     write bits to bitstream buffer  => increment cntBits
+                                     read bits from bitstream buffer => decrement cntBits */
+  Word16  size;                 /*!< size of bitbuffer in bits */
+  Word16  isValid;              /*!< indicates whether the instance has been initialized */
+}; /* size Word16: 8 */
+
+/*! Define pointer to bit buffer structure */
+typedef struct BIT_BUF *HANDLE_BIT_BUF;
+
+
+HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf,
+                               UWord8 *pBitBufBase,
+                               Word16  bitBufSize);
+
+
+void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf);
+
+
+Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf);
+
+
+Word16 WriteBits(HANDLE_BIT_BUF hBitBuf,
+                 Word32 writeValue,
+                 Word16 noBitsToWrite);
+
+void ResetBitBuf(HANDLE_BIT_BUF hBitBuf,
+                 UWord8 *pBitBufBase,
+                 Word16  bitBufSize);
+
+#define GetNrBitsAvailable(hBitBuf) ( (hBitBuf)->cntBits)
+#define GetNrBitsRead(hBitBuf)       ((hBitBuf)->size-(hBitBuf)->cntBits)
+
+#endif /* BITBUFFER_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/bitenc.h b/media/libstagefright/codecs/aacenc/inc/bitenc.h
new file mode 100644
index 0000000..1151057
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/bitenc.h
@@ -0,0 +1,50 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		bitenc.h

+

+	Content:	Bitstream encoder structure and functions

+

+*******************************************************************************/
+
+#ifndef _BITENC_H
+#define _BITENC_H
+
+#include "qc_data.h"
+#include "tns.h"
+#include "channel_map.h"
+#include "interface.h"  
+
+struct BITSTREAMENCODER_INIT
+{
+  Word16 nChannels;
+  Word32 bitrate;
+  Word32 sampleRate;
+  Word16 profile;
+};
+
+
+
+Word16 WriteBitstream (HANDLE_BIT_BUF hBitstream,
+                       ELEMENT_INFO elInfo,
+                       QC_OUT *qcOut,
+                       PSY_OUT *psyOut,
+                       Word16 *globUsedBits,

+                       const UWord8 *ancBytes,

+					   Word16 samplerate
+                       );
+
+#endif /* _BITENC_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/block_switch.h b/media/libstagefright/codecs/aacenc/inc/block_switch.h
new file mode 100644
index 0000000..3e35819
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/block_switch.h
@@ -0,0 +1,72 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		block_switch.h

+

+	Content:	Block switching structure and functions

+

+*******************************************************************************/
+
+#ifndef _BLOCK_SWITCH_H
+#define _BLOCK_SWITCH_H
+
+#include "typedef.h"
+
+
+/****************** Defines ******************************/
+#define BLOCK_SWITCHING_IIR_LEN 2                                           /* Length of HighPass-FIR-Filter for Attack-Detection */
+#define BLOCK_SWITCH_WINDOWS TRANS_FAC                                      /* number of windows for energy calculation */
+#define BLOCK_SWITCH_WINDOW_LEN FRAME_LEN_SHORT                             /* minimal granularity of energy calculation */
+
+
+
+/****************** Structures ***************************/
+typedef struct{
+  Word32 invAttackRatio;
+  Word16 windowSequence;
+  Word16 nextwindowSequence;
+  Flag attack;
+  Flag lastattack;
+  Word16 attackIndex;
+  Word16 lastAttackIndex;
+  Word16 noOfGroups;
+  Word16 groupLen[TRANS_FAC];
+  Word32 windowNrg[2][BLOCK_SWITCH_WINDOWS];     /* time signal energy in Subwindows (last and current) */
+  Word32 windowNrgF[2][BLOCK_SWITCH_WINDOWS];    /* filtered time signal energy in segments (last and current) */
+  Word32 iirStates[BLOCK_SWITCHING_IIR_LEN];     /* filter delay-line */
+  Word32 maxWindowNrg;                           /* max energy in subwindows */
+  Word32 accWindowNrg;                           /* recursively accumulated windowNrgF */
+}BLOCK_SWITCHING_CONTROL;
+
+
+
+
+
+Word16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+                          const Word32 bitRate, const Word16 nChannels);
+
+Word16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+                      Word16 *timeSignal,
+					  Word32  sampleRate,
+                      Word16 chIncrement);
+
+Word16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
+                          BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
+                          const Word16 noOfChannels);
+
+
+
+#endif  /* #ifndef _BLOCK_SWITCH_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/channel_map.h b/media/libstagefright/codecs/aacenc/inc/channel_map.h
new file mode 100644
index 0000000..e3aa8dc
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/channel_map.h
@@ -0,0 +1,37 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		channel_map.h

+

+	Content:	channel mapping functions

+

+*******************************************************************************/
+
+#ifndef _CHANNEL_MAP_H
+#define _CHANNEL_MAP_H
+
+#include "psy_const.h"
+#include "qc_data.h"
+
+Word16 InitElementInfo (Word16 nChannels, ELEMENT_INFO* elInfo);
+
+Word16 InitElementBits(ELEMENT_BITS *elementBits,
+                       ELEMENT_INFO elInfo,
+                       Word32 bitrateTot,
+                       Word16 averageBitsTot,
+                       Word16 staticBitsTot);
+
+#endif /* CHANNEL_MAP_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/config.h b/media/libstagefright/codecs/aacenc/inc/config.h
new file mode 100644
index 0000000..6211c8f
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/config.h
@@ -0,0 +1,36 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		config.h

+

+	Content:	aac encoder parameter

+

+*******************************************************************************/

+

+#ifndef _AACENC_CONFIG_H_

+#define _AACENC_CONFIG_H_

+

+#define MAX_CHANNELS        2

+

+#define AACENC_BLOCKSIZE    1024   /*! encoder only takes BLOCKSIZE samples at a time */

+#define AACENC_TRANS_FAC    8      /*! encoder short long ratio */

+

+

+#define MAXBITS_COEF		6144
+#define MINBITS_COEF		744

+

+

+#endif
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/inc/dyn_bits.h b/media/libstagefright/codecs/aacenc/inc/dyn_bits.h
new file mode 100644
index 0000000..0468fa2
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/dyn_bits.h
@@ -0,0 +1,82 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		dyn_bits.h

+

+	Content:	Noiseless coder module structure and functions

+

+*******************************************************************************/
+
+#ifndef __DYN_BITS_H
+#define __DYN_BITS_H
+
+#include "psy_const.h"
+#include "tns.h"
+#include "bit_cnt.h"
+
+
+
+#define MAX_SECTIONS          MAX_GROUPED_SFB
+#define SECT_ESC_VAL_LONG    31
+#define SECT_ESC_VAL_SHORT    7
+#define CODE_BOOK_BITS        4
+#define SECT_BITS_LONG        5
+#define SECT_BITS_SHORT       3
+
+typedef struct
+{
+  Word16 codeBook;
+  Word16 sfbStart;
+  Word16 sfbCnt;
+  Word16 sectionBits;
+}
+SECTION_INFO;
+
+
+
+
+typedef struct
+{
+  Word16 blockType;
+  Word16 noOfGroups;
+  Word16 sfbCnt;
+  Word16 maxSfbPerGroup;
+  Word16 sfbPerGroup;
+  Word16 noOfSections;
+  SECTION_INFO sectionInfo[MAX_SECTIONS];
+  Word16 sideInfoBits;             /* sectioning bits       */
+  Word16 huffmanBits;              /* huffman    coded bits */
+  Word16 scalefacBits;             /* scalefac   coded bits */
+  Word16 firstScf;                 /* first scf to be coded */
+  Word16 bitLookUp[MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1)];
+  Word16 mergeGainLookUp[MAX_SFB_LONG];
+}
+SECTION_DATA; /*  Word16 size: 10 + 60(MAX_SECTIONS)*4(SECTION_INFO) + 51(MAX_SFB_LONG)*12(CODE_BOOK_ESC_NDX+1) + 51(MAX_SFB_LONG) = 913 */
+
+
+Word16 BCInit(void);
+
+Word16 dynBitCount(const Word16 *quantSpectrum,
+                   const UWord16 *maxValueInSfb,
+                   const Word16 *scalefac,
+                   const Word16 blockType,
+                   const Word16 sfbCnt,
+                   const Word16 maxSfbPerGroup,
+                   const Word16 sfbPerGroup,
+                   const Word16 *sfbOffset,
+                   SECTION_DATA *sectionData);
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/grp_data.h b/media/libstagefright/codecs/aacenc/inc/grp_data.h
new file mode 100644
index 0000000..9666577
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/grp_data.h
@@ -0,0 +1,44 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		grp_data.h

+

+	Content:	Short block grouping function

+

+*******************************************************************************/
+
+#ifndef __GRP_DATA_H__
+#define __GRP_DATA_H__
+#include "psy_data.h"
+#include "typedefs.h"
+
+void
+groupShortData(Word32        *mdctSpectrum,
+               Word32        *tmpSpectrum,
+               SFB_THRESHOLD *sfbThreshold,
+               SFB_ENERGY    *sfbEnergy,
+               SFB_ENERGY    *sfbEnergyMS,
+               SFB_ENERGY    *sfbSpreadedEnergy,
+               const Word16   sfbCnt,
+               const Word16  *sfbOffset,
+               const Word16  *sfbMinSnr,
+               Word16        *groupedSfbOffset,
+               Word16        *maxSfbPerGroup,
+               Word16        *groupedSfbMinSnr,
+               const Word16   noOfGroups,
+               const Word16  *groupLen);
+
+#endif /* _INTERFACE_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/interface.h b/media/libstagefright/codecs/aacenc/inc/interface.h
new file mode 100644
index 0000000..b84334a
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/interface.h
@@ -0,0 +1,106 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		interface.h

+

+	Content:	psychoaccoustic/quantizer structures and interface

+

+*******************************************************************************/
+
+#ifndef _INTERFACE_H
+#define _INTERFACE_H
+
+#include "config.h"

+#include "psy_const.h"
+#include "psy_data.h"
+#include "typedefs.h"
+
+
+enum
+{
+  MS_NONE = 0,
+  MS_SOME = 1,
+  MS_ALL  = 2
+};
+
+enum
+{
+  MS_ON = 1
+};
+
+struct TOOLSINFO {
+  Word16 msDigest;
+  Word16 msMask[MAX_GROUPED_SFB];
+};
+
+
+typedef struct {
+  Word16  sfbCnt;
+  Word16  sfbPerGroup;
+  Word16  maxSfbPerGroup;
+  Word16  windowSequence;
+  Word16  windowShape;
+  Word16  groupingMask;
+  Word16  sfbOffsets[MAX_GROUPED_SFB+1];
+  Word16  mdctScale; 
+  Word32 *sfbEnergy; 
+  Word32 *sfbSpreadedEnergy;
+  Word32 *sfbThreshold;       
+  Word32 *mdctSpectrum;        
+  Word32  sfbEnSumLR;
+  Word32  sfbEnSumMS;
+  Word32 sfbDist[MAX_GROUPED_SFB];
+  Word32 sfbDistNew[MAX_GROUPED_SFB];
+  Word16  sfbMinSnr[MAX_GROUPED_SFB];
+  Word16 minSfMaxQuant[MAX_GROUPED_SFB];
+  Word16 minScfCalculated[MAX_GROUPED_SFB];
+  Word16 prevScfLast[MAX_GROUPED_SFB];
+  Word16 prevScfNext[MAX_GROUPED_SFB];
+  Word16 deltaPeLast[MAX_GROUPED_SFB];
+  TNS_INFO tnsInfo;
+} PSY_OUT_CHANNEL; /* Word16 size: 14 + 60(MAX_GROUPED_SFB) + 112(TNS_INFO) = 186 */
+
+typedef struct {
+  struct TOOLSINFO toolsInfo;
+  Word16 groupedSfbOffset[MAX_CHANNELS][MAX_GROUPED_SFB+1];  /* plus one for last dummy offset ! */
+  Word16 groupedSfbMinSnr[MAX_CHANNELS][MAX_GROUPED_SFB];
+} PSY_OUT_ELEMENT;
+
+typedef struct {
+  /* information shared by both channels  */
+  PSY_OUT_ELEMENT  psyOutElement;
+  /* information specific to each channel */
+  PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS];
+}PSY_OUT;
+
+void BuildInterface(Word32                 *mdctSpectrum,
+                    const Word16            mdctScale,
+                    SFB_THRESHOLD          *sfbThreshold,
+                    SFB_ENERGY             *sfbEnergy,
+                    SFB_ENERGY             *sfbSpreadedEnergy,
+                    const SFB_ENERGY_SUM    sfbEnergySumLR,
+                    const SFB_ENERGY_SUM    sfbEnergySumMS,
+                    const Word16            windowSequence,
+                    const Word16            windowShape,
+                    const Word16            sfbCnt,
+                    const Word16           *sfbOffset,
+                    const Word16            maxSfbPerGroup,
+                    const Word16           *groupedSfbMinSnr,
+                    const Word16            noOfGroups,
+                    const Word16           *groupLen,
+                    PSY_OUT_CHANNEL        *psyOutCh);
+
+#endif /* _INTERFACE_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/line_pe.h b/media/libstagefright/codecs/aacenc/inc/line_pe.h
new file mode 100644
index 0000000..fed938b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/line_pe.h
@@ -0,0 +1,75 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		line_pe.h

+

+	Content:	Perceptual entropie module structure and functions

+

+*******************************************************************************/
+
+#ifndef __LINE_PE_H
+#define __LINE_PE_H
+
+
+#include "psy_const.h" 
+#include "interface.h" 
+
+
+typedef struct {
+   Word16 sfbLdEnergy[MAX_GROUPED_SFB];     /* 4*log(sfbEnergy)/log(2) */
+   Word16 sfbNLines4[MAX_GROUPED_SFB];      /* 4*number of relevant lines in sfb */
+   Word16 sfbPe[MAX_GROUPED_SFB];           /* pe for each sfb */
+   Word16 sfbConstPart[MAX_GROUPED_SFB];    /* constant part for each sfb */
+   Word16 sfbNActiveLines[MAX_GROUPED_SFB]; /* number of active lines in sfb */
+   Word16 pe;                               /* sum of sfbPe */
+   Word16 constPart;                        /* sum of sfbConstPart */
+   Word16 nActiveLines;                     /* sum of sfbNActiveLines */
+} PE_CHANNEL_DATA; /* size Word16: 303 */
+
+
+typedef struct {
+   PE_CHANNEL_DATA peChannelData[MAX_CHANNELS];
+   Word16 pe;
+   Word16 constPart;
+   Word16 nActiveLines;
+   Word16 offset;
+   Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB];
+   Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB];
+   Word32 sfbPeFactors[MAX_CHANNELS][MAX_GROUPED_SFB];
+} PE_DATA; /* size Word16: 303 + 4 + 120 + 240 = 667 */
+
+
+
+
+void prepareSfbPe(PE_DATA *peData,
+                  PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
+                  Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+                  Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+                  const Word16 nChannels,
+                  const Word16 peOffset);
+
+
+
+
+
+void calcSfbPe(PE_DATA *peData,
+               PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+               const Word16 nChannels);
+
+
+
+
+#endif 
diff --git a/media/libstagefright/codecs/aacenc/inc/memalign.h b/media/libstagefright/codecs/aacenc/inc/memalign.h
new file mode 100644
index 0000000..3b302a7
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/memalign.h
@@ -0,0 +1,35 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		memalign.h

+

+	Content:	Memory alloc alignments functions

+

+*******************************************************************************/

+

+#ifndef __VO_AACENC_MEM_ALIGN_H__

+#define __VO_AACENC_MEM_ALIGN_H__

+

+#include "voMem.h"

+#include "typedef.h"

+

+extern void *mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID);

+extern void mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID);

+

+#endif	/* __VO_MEM_ALIGN_H__ */

+

+

+

diff --git a/media/libstagefright/codecs/aacenc/inc/ms_stereo.h b/media/libstagefright/codecs/aacenc/inc/ms_stereo.h
new file mode 100644
index 0000000..6d43dec
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/ms_stereo.h
@@ -0,0 +1,45 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		ms_stereo.h

+

+	Content:	Declaration MS stereo processing structure and functions

+

+*******************************************************************************/
+
+#ifndef __MS_STEREO_H__
+#define __MS_STEREO_H__
+#include "typedef.h"
+
+void MsStereoProcessing(Word32       *sfbEnergyLeft,
+                        Word32       *sfbEnergyRight,
+                        const Word32 *sfbEnergyMid,
+                        const Word32 *sfbEnergySide,
+                        Word32       *mdctSpectrumLeft,
+                        Word32       *mdctSpectrumRight,
+                        Word32       *sfbThresholdLeft,
+                        Word32       *sfbThresholdRight,
+                        Word32       *sfbSpreadedEnLeft,
+                        Word32       *sfbSpreadedEnRight,
+                        Word16       *msDigest,
+                        Word16       *msMask,
+                        const Word16  sfbCnt,
+                        const Word16  sfbPerGroup,
+                        const Word16  maxSfbPerGroup,
+                        const Word16 *sfbOffset);
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h b/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h
new file mode 100644
index 0000000..35f36e8
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h
@@ -0,0 +1,42 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		pre_echo_control.h

+

+	Content:	Pre echo control functions

+

+*******************************************************************************/
+
+#ifndef __PRE_ECHO_CONTROL_H
+#define __PRE_ECHO_CONTROL_H
+
+#include "typedefs.h"
+
+void InitPreEchoControl(Word32 *pbThresholdnm1,
+                        Word16  numPb,
+                        Word32 *pbThresholdQuiet);
+
+
+void PreEchoControl(Word32 *pbThresholdNm1,
+                    Word16  numPb,
+                    Word32  maxAllowedIncreaseFactor,
+                    Word16  minRemainingThresholdFactor,
+                    Word32 *pbThreshold,
+                    Word16  mdctScale,
+                    Word16  mdctScalenm1);
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacenc/inc/psy_configuration.h b/media/libstagefright/codecs/aacenc/inc/psy_configuration.h
new file mode 100644
index 0000000..53cf25b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/psy_configuration.h
@@ -0,0 +1,107 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		psy_configuration.h

+

+	Content:	Psychoaccoustic configuration structure and functions

+

+*******************************************************************************/
+
+#ifndef _PSY_CONFIGURATION_H
+#define _PSY_CONFIGURATION_H
+

+#include "typedefs.h"
+#include "psy_const.h"
+#include "tns.h"
+
+typedef struct{
+
+  Word16 sfbCnt;
+  Word16 sfbActive;   /* number of sf bands containing energy after lowpass */
+  Word16 *sfbOffset;
+
+  Word32 sfbThresholdQuiet[MAX_SFB_LONG];
+
+  Word16 maxAllowedIncreaseFactor;   /* preecho control */
+  Word16 minRemainingThresholdFactor;
+
+  Word16 lowpassLine;

+  Word16 sampRateIdx;
+  Word32 clipEnergy;                 /* for level dependend tmn */
+
+  Word16 ratio;
+  Word16 sfbMaskLowFactor[MAX_SFB_LONG];
+  Word16 sfbMaskHighFactor[MAX_SFB_LONG];
+
+  Word16 sfbMaskLowFactorSprEn[MAX_SFB_LONG];
+  Word16 sfbMaskHighFactorSprEn[MAX_SFB_LONG];
+
+
+  Word16 sfbMinSnr[MAX_SFB_LONG];       /* minimum snr (formerly known as bmax) */
+
+  TNS_CONFIG tnsConf;
+
+}PSY_CONFIGURATION_LONG; /*Word16 size: 8 + 52 + 102 + 51 + 51 + 51 + 51 + 47 = 515 */
+
+
+typedef struct{
+
+  Word16 sfbCnt;
+  Word16 sfbActive;   /* number of sf bands containing energy after lowpass */
+  Word16 *sfbOffset;
+
+  Word32 sfbThresholdQuiet[MAX_SFB_SHORT];
+
+  Word16 maxAllowedIncreaseFactor;   /* preecho control */
+  Word16 minRemainingThresholdFactor;
+
+  Word16 lowpassLine;

+  Word16 sampRateIdx;
+  Word32 clipEnergy;                 /* for level dependend tmn */
+
+  Word16 ratio;
+  Word16 sfbMaskLowFactor[MAX_SFB_SHORT];
+  Word16 sfbMaskHighFactor[MAX_SFB_SHORT];
+
+  Word16 sfbMaskLowFactorSprEn[MAX_SFB_SHORT];
+  Word16 sfbMaskHighFactorSprEn[MAX_SFB_SHORT];
+
+
+  Word16 sfbMinSnr[MAX_SFB_SHORT];       /* minimum snr (formerly known as bmax) */
+
+  TNS_CONFIG tnsConf;
+
+}PSY_CONFIGURATION_SHORT; /*Word16 size: 8 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 47 = 167 */
+

+

+/* Returns the sample rate index */

+Word32 GetSRIndex(Word32 sampleRate);

+
+
+Word16 InitPsyConfigurationLong(Word32 bitrate,
+                                Word32 samplerate,
+                                Word16 bandwidth,
+                                PSY_CONFIGURATION_LONG *psyConf);
+
+Word16 InitPsyConfigurationShort(Word32 bitrate,
+                                 Word32 samplerate,
+                                 Word16 bandwidth,
+                                 PSY_CONFIGURATION_SHORT *psyConf);
+
+#endif /* _PSY_CONFIGURATION_H */
+
+
+
diff --git a/media/libstagefright/codecs/aacenc/inc/psy_const.h b/media/libstagefright/codecs/aacenc/inc/psy_const.h
new file mode 100644
index 0000000..5455ab1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/psy_const.h
@@ -0,0 +1,80 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		psy_const.h

+

+	Content:	Global psychoacoustic constants structures

+

+*******************************************************************************/
+
+#ifndef _PSYCONST_H
+#define _PSYCONST_H
+
+#include "config.h"

+
+#define TRUE  1
+#define FALSE 0
+
+#define FRAME_LEN_LONG    AACENC_BLOCKSIZE
+#define TRANS_FAC         8
+#define FRAME_LEN_SHORT   (FRAME_LEN_LONG/TRANS_FAC)

+

+
+
+/* Block types */
+enum
+{
+  LONG_WINDOW = 0,
+  START_WINDOW,
+  SHORT_WINDOW,
+  STOP_WINDOW
+};
+
+/* Window shapes */
+enum
+{
+  SINE_WINDOW = 0,
+  KBD_WINDOW  = 1
+};
+
+/*
+  MS stuff
+*/
+enum
+{
+  SI_MS_MASK_NONE = 0,
+  SI_MS_MASK_SOME = 1,
+  SI_MS_MASK_ALL  = 2
+};
+
+#define MAX_NO_OF_GROUPS 4
+#define MAX_SFB_SHORT   15  /* 15 for a memory optimized implementation, maybe 16 for convenient debugging */
+#define MAX_SFB_LONG    51  /* 51 for a memory optimized implementation, maybe 64 for convenient debugging */
+#define MAX_SFB         (MAX_SFB_SHORT > MAX_SFB_LONG ? MAX_SFB_SHORT : MAX_SFB_LONG)   /* = MAX_SFB_LONG */
+#define MAX_GROUPED_SFB (MAX_NO_OF_GROUPS*MAX_SFB_SHORT > MAX_SFB_LONG ? \
+                         MAX_NO_OF_GROUPS*MAX_SFB_SHORT : MAX_SFB_LONG)
+
+#define BLOCK_SWITCHING_OFFSET		   (1*1024+3*128+64+128)
+#define BLOCK_SWITCHING_DATA_SIZE          FRAME_LEN_LONG
+										    
+#define TRANSFORM_OFFSET_LONG    0
+#define TRANSFORM_OFFSET_SHORT   448
+
+#define LOG_NORM_PCM          -15
+

+#define NUM_SAMPLE_RATES	12
+
+#endif /* _PSYCONST_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/psy_data.h b/media/libstagefright/codecs/aacenc/inc/psy_data.h
new file mode 100644
index 0000000..1412d53
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/psy_data.h
@@ -0,0 +1,66 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		psy_data.h

+

+	Content:	Psychoacoustic data and structures

+

+*******************************************************************************/
+
+#ifndef _PSY_DATA_H
+#define _PSY_DATA_H
+
+#include "block_switch.h"
+#include "tns.h"
+
+/*
+  the structs can be implemented as unions
+*/
+
+typedef struct{
+  Word32 sfbLong[MAX_GROUPED_SFB];
+  Word32 sfbShort[TRANS_FAC][MAX_SFB_SHORT];
+}SFB_THRESHOLD; /* Word16 size: 260 */
+
+typedef struct{
+  Word32 sfbLong[MAX_GROUPED_SFB];
+  Word32 sfbShort[TRANS_FAC][MAX_SFB_SHORT];
+}SFB_ENERGY; /* Word16 size: 260 */
+
+typedef struct{
+  Word32 sfbLong;
+  Word32 sfbShort[TRANS_FAC];
+}SFB_ENERGY_SUM; /* Word16 size: 18 */
+
+
+typedef struct{
+  BLOCK_SWITCHING_CONTROL   blockSwitchingControl;          /* block switching */
+  Word16                    *mdctDelayBuffer;               /* mdct delay buffer [BLOCK_SWITCHING_OFFSET]*/
+  Word32                    sfbThresholdnm1[MAX_SFB];       /* PreEchoControl */
+  Word16                    mdctScalenm1;                   /* scale of last block's mdct (PreEchoControl) */
+
+  SFB_THRESHOLD             sfbThreshold;                   /* adapt           */
+  SFB_ENERGY                sfbEnergy;                      /* sfb Energy      */
+  SFB_ENERGY                sfbEnergyMS;
+  SFB_ENERGY_SUM            sfbEnergySum;
+  SFB_ENERGY_SUM            sfbEnergySumMS;
+  SFB_ENERGY                sfbSpreadedEnergy;
+
+  Word32                    *mdctSpectrum;                  /* mdct spectrum [FRAME_LEN_LONG] */
+  Word16                    mdctScale;                      /* scale of mdct   */
+}PSY_DATA; /* Word16 size: 4 + 87 + 102 + 360 + 360 + 360 + 18 + 18 + 360 = 1669 */
+
+#endif /* _PSY_DATA_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/psy_main.h b/media/libstagefright/codecs/aacenc/inc/psy_main.h
new file mode 100644
index 0000000..ab0b8b1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/psy_main.h
@@ -0,0 +1,69 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		psy_main.h

+

+	Content:	Psychoacoustic major function block

+

+*******************************************************************************/
+
+#ifndef _PSYMAIN_H
+#define _PSYMAIN_H
+
+#include "psy_configuration.h"
+#include "qc_data.h"
+#include "memalign.h"
+
+/*
+  psy kernel
+*/
+typedef struct  {
+  PSY_CONFIGURATION_LONG  psyConfLong;           /* Word16 size: 515 */
+  PSY_CONFIGURATION_SHORT psyConfShort;          /* Word16 size: 167 */
+  PSY_DATA                psyData[MAX_CHANNELS]; /* Word16 size: MAX_CHANNELS*1669*/
+  TNS_DATA                tnsData[MAX_CHANNELS]; /* Word16 size: MAX_CHANNELS*235 */
+  Word32*                 pScratchTns;

+  Word16				  sampleRateIdx;
+}PSY_KERNEL; /* Word16 size: 2587 / 4491 */
+
+
+Word16 PsyNew( PSY_KERNEL  *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP);
+Word16 PsyDelete( PSY_KERNEL  *hPsy, VO_MEM_OPERATOR *pMemOP);
+
+Word16 PsyOutNew( PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP);
+Word16 PsyOutDelete( PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP);
+
+Word16 psyMainInit( PSY_KERNEL *hPsy,
+                    Word32 sampleRate,
+                    Word32 bitRate,
+                    Word16 channels,
+                    Word16 tnsMask,
+                    Word16 bandwidth);
+
+
+Word16 psyMain(Word16                   nChannels,   /*!< total number of channels */              
+               ELEMENT_INFO             *elemInfo,
+               Word16                   *timeSignal, /*!< interleaved time signal */ 
+               PSY_DATA                 psyData[MAX_CHANNELS],
+               TNS_DATA                 tnsData[MAX_CHANNELS],
+               PSY_CONFIGURATION_LONG*  psyConfLong,
+               PSY_CONFIGURATION_SHORT* psyConfShort,
+               PSY_OUT_CHANNEL          psyOutChannel[MAX_CHANNELS],
+               PSY_OUT_ELEMENT          *psyOutElement,
+               Word32                   *pScratchTns,
+			   Word32					sampleRate);
+
+#endif /* _PSYMAIN_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/qc_data.h b/media/libstagefright/codecs/aacenc/inc/qc_data.h
new file mode 100644
index 0000000..81d4051
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/qc_data.h
@@ -0,0 +1,143 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		qc_data.h

+

+	Content:	Quantizing & coding structures

+

+*******************************************************************************/
+
+#ifndef _QC_DATA_H
+#define _QC_DATA_H
+
+#include "psy_const.h"
+#include "dyn_bits.h"
+#include "adj_thr_data.h"
+
+
+#define MAX_MODES 10
+
+typedef enum {
+  MODE_INVALID = 0,
+  MODE_1,        /* mono      */
+  MODE_1_1,      /* dual mono */
+  MODE_2         /* stereo    */
+} ENCODER_MODE;
+
+typedef enum {
+  ID_SCE=0,     /* Single Channel Element   */
+  ID_CPE=1,     /* Channel Pair Element     */
+  ID_CCE=2,     /* Coupling Channel Element */
+  ID_LFE=3,     /* LFE Channel Element      */
+  ID_DSE=4,     /* current one DSE element for ancillary is supported */
+  ID_PCE=5,
+  ID_FIL=6,
+  ID_END=7
+}ELEMENT_TYPE;
+
+typedef struct {
+  ELEMENT_TYPE elType;
+  Word16 instanceTag;
+  Word16 nChannelsInEl;
+  Word16 ChannelIndex[MAX_CHANNELS];
+} ELEMENT_INFO;
+
+typedef struct {
+  Word32 paddingRest;
+} PADDING;
+
+
+/* Quantizing & coding stage */
+
+struct QC_INIT{
+  ELEMENT_INFO *elInfo;
+  Word16 maxBits;     /* maximum number of bits in reservoir  */
+  Word16 averageBits; /* average number of bits we should use */
+  Word16 bitRes;
+  Word16 meanPe;
+  Word32 chBitrate;
+  Word16 maxBitFac;
+  Word32 bitrate;
+
+  PADDING padding;
+};
+
+typedef struct
+{
+  Word16          *quantSpec;       /* [FRAME_LEN_LONG];                            */
+  UWord16         *maxValueInSfb;   /* [MAX_GROUPED_SFB];                           */
+  Word16          *scf;             /* [MAX_GROUPED_SFB];                           */
+  Word16          globalGain;
+  Word16          mdctScale;
+  Word16          groupingMask;
+  SECTION_DATA    sectionData;
+  Word16          windowShape;
+} QC_OUT_CHANNEL;
+
+typedef struct
+{
+  Word16		  adtsUsed;

+  Word16          staticBitsUsed; /* for verification purposes */
+  Word16          dynBitsUsed;    /* for verification purposes */
+  Word16          pe;
+  Word16          ancBitsUsed;
+  Word16          fillBits;
+} QC_OUT_ELEMENT;
+
+typedef struct
+{
+  QC_OUT_CHANNEL  qcChannel[MAX_CHANNELS];
+  QC_OUT_ELEMENT  qcElement;
+  Word16          totStaticBitsUsed; /* for verification purposes */
+  Word16          totDynBitsUsed;    /* for verification purposes */
+  Word16          totAncBitsUsed;    /* for verification purposes */
+  Word16          totFillBits;
+  Word16          alignBits;
+  Word16          bitResTot;
+  Word16          averageBitsTot;
+} QC_OUT;
+
+typedef struct {
+  Word32 chBitrate;
+  Word16 averageBits;               /* brutto -> look ancillary.h */
+  Word16 maxBits;
+  Word16 bitResLevel;
+  Word16 maxBitResBits;
+  Word16 relativeBits;            /* Bits relative to total Bits scaled down by 2 */
+} ELEMENT_BITS;
+
+typedef struct
+{
+  /* this is basically struct QC_INIT */
+  Word16 averageBitsTot;
+  Word16 maxBitsTot;
+  Word16 globStatBits;
+  Word16 nChannels;
+  Word16 bitResTot;
+
+  Word16 maxBitFac;
+
+  PADDING   padding;
+
+  ELEMENT_BITS  elementBits;
+  ADJ_THR_STATE adjThr;
+
+  Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB];
+  Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB];
+  Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB];
+} QC_STATE;
+
+#endif /* _QC_DATA_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/qc_main.h b/media/libstagefright/codecs/aacenc/inc/qc_main.h
new file mode 100644
index 0000000..e1138b2
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/qc_main.h
@@ -0,0 +1,64 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		qc_main.h

+

+	Content:	Quantizing & coding functions

+

+*******************************************************************************/
+
+#ifndef _QC_MAIN_H
+#define _QC_MAIN_H
+
+#include "qc_data.h"
+#include "interface.h"
+#include "memalign.h"
+
+/* Quantizing & coding stage */
+
+Word16 QCOutNew(QC_OUT *hQC, Word16 nChannels, VO_MEM_OPERATOR *pMemOP);
+
+void QCOutDelete(QC_OUT *hQC, VO_MEM_OPERATOR *pMemOP);
+
+Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP);
+
+Word16 QCInit(QC_STATE *hQC, 
+              struct QC_INIT *init);
+
+void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP);
+
+
+Word16 QCMain(QC_STATE *hQC,
+              ELEMENT_BITS* elBits,
+              ATS_ELEMENT* adjThrStateElement,
+              PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], /* may be modified in-place */
+              PSY_OUT_ELEMENT* psyOutElement,
+              QC_OUT_CHANNEL  qcOutChannel[MAX_CHANNELS],   /* out                      */
+              QC_OUT_ELEMENT* qcOutElement,
+              Word16 nChannels,
+			  Word16 ancillaryDataBytes);     /* returns error code       */
+
+void updateBitres(QC_STATE* qcKernel,
+                  QC_OUT* qcOut);
+
+Word16 FinalizeBitConsumption(QC_STATE *hQC,
+                              QC_OUT* qcOut);
+
+Word16 AdjustBitrate(QC_STATE *hQC,
+                     Word32 bitRate,
+                     Word32 sampleRate);
+
+#endif /* _QC_MAIN_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/quantize.h b/media/libstagefright/codecs/aacenc/inc/quantize.h
new file mode 100644
index 0000000..88a95e1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/quantize.h
@@ -0,0 +1,42 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		quantize.h

+

+	Content:	Quantization functions

+

+*******************************************************************************/
+
+#ifndef _QUANTIZE_H_
+#define _QUANTIZE_H_
+#include "typedefs.h"
+
+/* quantizing */
+
+#define MAX_QUANT 8191
+
+void QuantizeSpectrum(Word16 sfbCnt, 
+                      Word16 maxSfbPerGroup,
+                      Word16 sfbPerGroup,
+                      Word16 *sfbOffset, Word32 *mdctSpectrum,
+                      Word16 globalGain, Word16 *scalefactors,
+                      Word16 *quantizedSpectrum);
+
+Word32 calcSfbDist(const Word32 *spec,
+                   Word16  sfbWidth,
+                   Word16  gain);
+
+#endif /* _QUANTIZE_H_ */
diff --git a/media/libstagefright/codecs/aacenc/inc/sf_estim.h b/media/libstagefright/codecs/aacenc/inc/sf_estim.h
new file mode 100644
index 0000000..b25ec3c
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/sf_estim.h
@@ -0,0 +1,46 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		sf_estim.h

+

+	Content:	Scale factor estimation functions

+

+*******************************************************************************/
+
+#ifndef __SF_ESTIM_H__
+#define __SF_ESTIM_H__
+/*
+   Scale factor estimation 
+ */
+#include "psy_const.h"
+#include "interface.h"
+#include "qc_data.h"
+
+void
+CalcFormFactor(Word16          logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
+               Word16          sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+               Word16          logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+               PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+               const Word16    nChannels);
+
+void
+EstimateScaleFactors(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+                     QC_OUT_CHANNEL  qcOutChannel[MAX_CHANNELS],
+                     Word16          logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+                     Word16          logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
+                     Word16          sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+                     const Word16    nChannels);
+#endif
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/inc/spreading.h b/media/libstagefright/codecs/aacenc/inc/spreading.h
new file mode 100644
index 0000000..29cf63d
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/spreading.h
@@ -0,0 +1,33 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		spreading.h

+

+	Content:	Spreading of energy functions

+

+*******************************************************************************/
+
+#ifndef _SPREADING_H
+#define _SPREADING_H
+#include "typedefs.h"
+

+
+void SpreadingMax(const Word16 pbCnt,
+                  const Word16 *maskLowFactor,
+                  const Word16 *maskHighFactor,
+                  Word32       *pbSpreadedEnergy);
+
+#endif /* #ifndef _SPREADING_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/stat_bits.h b/media/libstagefright/codecs/aacenc/inc/stat_bits.h
new file mode 100644
index 0000000..6e90b9c
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/stat_bits.h
@@ -0,0 +1,34 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		stat_bits.h

+

+	Content:	Static bit counter functions

+

+*******************************************************************************/
+
+#ifndef __STAT_BITS_H
+#define __STAT_BITS_H
+
+#include "psy_const.h"
+#include "interface.h"
+
+Word16 countStaticBitdemand(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+                            PSY_OUT_ELEMENT *psyOutElement,
+                            Word16 nChannels, 

+							Word16 adtsUsed);
+
+#endif /* __STAT_BITS_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/tns.h b/media/libstagefright/codecs/aacenc/inc/tns.h
new file mode 100644
index 0000000..9ffcce9
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/tns.h
@@ -0,0 +1,108 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		tns.h

+

+	Content:	TNS structures

+

+*******************************************************************************/
+
+#ifndef _TNS_H
+#define _TNS_H
+

+#include "typedef.h"
+#include "psy_const.h"
+
+
+
+#define TNS_MAX_ORDER 12
+#define TNS_MAX_ORDER_SHORT 5
+
+#define FILTER_DIRECTION    0
+
+typedef struct{ /*stuff that is tabulated dependent on bitrate etc. */
+  Word16     threshOn;                /* min. prediction gain for using tns TABUL * 100*/
+  Word32     lpcStartFreq;            /* lowest freq for lpc TABUL*/
+  Word32     lpcStopFreq;             /* TABUL */
+  Word32     tnsTimeResolution;
+}TNS_CONFIG_TABULATED;
+
+
+typedef struct {   /*assigned at InitTime*/
+  Word16 tnsActive;
+  Word16 tnsMaxSfb;
+
+  Word16 maxOrder;                /* max. order of tns filter */
+  Word16 tnsStartFreq;            /* lowest freq. for tns filtering */
+  Word16 coefRes;
+
+  TNS_CONFIG_TABULATED confTab;
+
+  Word32 acfWindow[TNS_MAX_ORDER+1];
+
+  Word16 tnsStartBand;
+  Word16 tnsStartLine;
+
+  Word16 tnsStopBand;
+  Word16 tnsStopLine;
+
+  Word16 lpcStartBand;
+  Word16 lpcStartLine;
+
+  Word16 lpcStopBand;
+  Word16 lpcStopLine;
+
+  Word16 tnsRatioPatchLowestCb;
+  Word16 tnsModifyBeginCb;
+
+  Word16 threshold; /* min. prediction gain for using tns TABUL * 100 */
+
+}TNS_CONFIG;
+
+
+typedef struct {
+  Word16 tnsActive;
+  Word32 parcor[TNS_MAX_ORDER];
+  Word16 predictionGain;
+} TNS_SUBBLOCK_INFO; /* Word16 size: 26 */
+
+typedef struct{
+  TNS_SUBBLOCK_INFO subBlockInfo[TRANS_FAC];
+} TNS_DATA_SHORT;
+
+typedef struct{
+  TNS_SUBBLOCK_INFO subBlockInfo;
+} TNS_DATA_LONG;
+
+typedef struct{
+  TNS_DATA_LONG tnsLong;
+  TNS_DATA_SHORT tnsShort;
+}TNS_DATA_RAW;
+
+typedef struct{
+  Word16 numOfSubblocks;
+  TNS_DATA_RAW dataRaw;
+}TNS_DATA; /* Word16 size: 1 + 8*26 + 26 = 235 */
+
+typedef struct{
+  Word16 tnsActive[TRANS_FAC];
+  Word16 coefRes[TRANS_FAC];
+  Word16 length[TRANS_FAC];
+  Word16 order[TRANS_FAC];
+  Word16 coef[TRANS_FAC*TNS_MAX_ORDER_SHORT];
+}TNS_INFO; /* Word16 size: 72 */
+
+#endif /* _TNS_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/tns_func.h b/media/libstagefright/codecs/aacenc/inc/tns_func.h
new file mode 100644
index 0000000..58b75b6
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/tns_func.h
@@ -0,0 +1,75 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		tns_func.h

+

+	Content:	TNS functions

+

+*******************************************************************************/
+
+/*
+   Temporal noise shaping
+ */
+#ifndef _TNS_FUNC_H
+#define _TNS_FUNC_H

+#include "typedef.h"
+#include "psy_configuration.h"
+
+Word16 InitTnsConfigurationLong(Word32 bitrate,
+                                Word32 samplerate,
+                                Word16 channels,
+                                TNS_CONFIG *tnsConfig,
+                                PSY_CONFIGURATION_LONG *psyConfig,
+                                Word16 active);
+
+Word16 InitTnsConfigurationShort(Word32 bitrate,
+                                 Word32 samplerate,
+                                 Word16 channels,
+                                 TNS_CONFIG *tnsConfig,
+                                 PSY_CONFIGURATION_SHORT *psyConfig,
+                                 Word16 active);
+
+Word32 TnsDetect(TNS_DATA* tnsData,
+                 TNS_CONFIG tC,
+                 Word32* pScratchTns,
+                 const Word16 sfbOffset[],
+                 Word32* spectrum,
+                 Word16 subBlockNumber,
+                 Word16 blockType,
+                 Word32 * sfbEnergy);
+
+void TnsSync(TNS_DATA *tnsDataDest,
+             const TNS_DATA *tnsDataSrc,
+             const TNS_CONFIG tC,
+             const Word16 subBlockNumber,
+             const Word16 blockType);
+
+Word16 TnsEncode(TNS_INFO* tnsInfo,
+                 TNS_DATA* tnsData,
+                 Word16 numOfSfb,
+                 TNS_CONFIG tC,
+                 Word16 lowPassLine,
+                 Word32* spectrum,
+                 Word16 subBlockNumber,
+                 Word16 blockType);
+
+void ApplyTnsMultTableToRatios(Word16 startCb,
+                               Word16 stopCb,
+                               TNS_SUBBLOCK_INFO subInfo,
+                               Word32 *thresholds);
+
+
+#endif /* _TNS_FUNC_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/tns_param.h b/media/libstagefright/codecs/aacenc/inc/tns_param.h
new file mode 100644
index 0000000..26266ac
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/tns_param.h
@@ -0,0 +1,52 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		tns_param.h

+

+	Content:	TNS parameters

+

+*******************************************************************************/
+
+/*
+   TNS parameters
+ */
+#ifndef _TNS_PARAM_H
+#define _TNS_PARAM_H
+
+#include "tns.h"
+
+typedef struct{
+  Word32 samplingRate;
+  Word16 maxBandLong;
+  Word16 maxBandShort;
+}TNS_MAX_TAB_ENTRY;
+
+typedef struct{
+    Word32 bitRateFrom;
+    Word32 bitRateTo;
+    const TNS_CONFIG_TABULATED *paramMono_Long;  /* contains TNS parameters */
+    const TNS_CONFIG_TABULATED *paramMono_Short;
+    const TNS_CONFIG_TABULATED *paramStereo_Long;
+    const TNS_CONFIG_TABULATED *paramStereo_Short;
+}TNS_INFO_TAB;
+
+
+void GetTnsParam(TNS_CONFIG_TABULATED *tnsConfigTab, 
+                 Word32 bitRate, Word16 channels, Word16 blockType);
+
+void GetTnsMaxBands(Word32 samplingRate, Word16 blockType, Word16* tnsMaxSfb);
+
+#endif /* _TNS_PARAM_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/transform.h b/media/libstagefright/codecs/aacenc/inc/transform.h
new file mode 100644
index 0000000..2666914
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/transform.h
@@ -0,0 +1,36 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		transform.h

+

+	Content:	MDCT Transform functions

+

+*******************************************************************************/
+
+#ifndef  __TRANSFORM_H__
+#define __TRANSFORM_H__
+
+#include "typedef.h"
+                  
+void Transform_Real(Word16 *mdctDelayBuffer,
+                    Word16 *timeSignal,
+                    Word16 chIncrement,     /*! channel increment */
+                    Word32 *realOut,
+                    Word16 *mdctScale,
+                    Word16 windowSequence
+                    );
+
+#endif
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/patent_disclaimer.txt b/media/libstagefright/codecs/aacenc/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/patent_disclaimer.txt
@@ -0,0 +1,9 @@
+
+THIS IS NOT A GRANT OF PATENT RIGHTS.
+
+Google makes no representation or warranty that the codecs for which
+source code is made available hereunder are unencumbered by
+third-party patents.  Those intending to use this source code in
+hardware or software products are advised that implementations of
+these codecs, including in open source software or shareware, may
+require patent licenses from the relevant patent holders.
diff --git a/media/libstagefright/codecs/aacenc/src/aac_rom.c b/media/libstagefright/codecs/aacenc/src/aac_rom.c
new file mode 100644
index 0000000..2ce0352
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/aac_rom.c
@@ -0,0 +1,2363 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		aac_rom.c

+

+	Content:	constant tables

+

+*******************************************************************************/
+
+#include "aac_rom.h"

+

+#if defined (ARMV5E) && !defined (ARMV7Neon)

+

+/* 

+ *  Q30 for 128 and 1024 

+ *

+ * for (i = 0; i < num/4; i++) {

+ *   angle = (i + 0.125) * M_PI / num;

+ *   x = cos(angle) * (1 << 30);

+ *   x = sin(angle) * (1 << 30);

+ * 

+ *   angle = (num/2 - 1 - i + 0.125) * M_PI / num;

+ *   x = cos(angle) * (1 << 30);

+ *   x = sin(angle) * (1 << 30);

+ * }

+ */

+const int cossintab[128 + 1024] = {

+	/* 128 */

+	0x3fffec43, 0x003243f1, 0x015fd4d2, 0x3ffc38d1, 0x3ff9c13a, 0x01c454f5, 0x02f1b755, 0x3feea776, 

+	0x3fe9b8a9, 0x03562038, 0x0483259d, 0x3fd73a4a, 0x3fcfd50b, 0x04e767c5, 0x0613e1c5, 0x3fb5f4ea, 

+	0x3fac1a5b, 0x0677edbb, 0x07a3adff, 0x3f8adc77, 0x3f7e8e1e, 0x08077457, 0x09324ca7, 0x3f55f796, 

+	0x3f473759, 0x0995bdfd, 0x0abf8043, 0x3f174e70, 0x3f061e95, 0x0b228d42, 0x0c4b0b94, 0x3eceeaad, 

+	0x3ebb4ddb, 0x0cada4f5, 0x0dd4b19a, 0x3e7cd778, 0x3e66d0b4, 0x0e36c82a, 0x0f5c35a3, 0x3e212179, 

+	0x3e08b42a, 0x0fbdba40, 0x10e15b4e, 0x3dbbd6d4, 0x3da106bd, 0x11423ef0, 0x1263e699, 0x3d4d0728, 

+	0x3d2fd86c, 0x12c41a4f, 0x13e39be9, 0x3cd4c38b, 0x3cb53aaa, 0x144310dd, 0x15604013, 0x3c531e88, 

+	0x3c314060, 0x15bee78c, 0x16d99864, 0x3bc82c1f, 0x3ba3fde7, 0x173763c9, 0x184f6aab, 0x3b3401bb, 

+	0x3b0d8909, 0x18ac4b87, 0x19c17d44, 0x3a96b636, 0x3a6df8f8, 0x1a1d6544, 0x1b2f971e, 0x39f061d2, 

+	0x39c5664f, 0x1b8a7815, 0x1c997fc4, 0x39411e33, 0x3913eb0e, 0x1cf34baf, 0x1dfeff67, 0x38890663, 

+	0x3859a292, 0x1e57a86d, 0x1f5fdee6, 0x37c836c2, 0x3796a996, 0x1fb7575c, 0x20bbe7d8, 0x36fecd0e, 

+	0x36cb1e2a, 0x21122240, 0x2212e492, 0x362ce855, 0x35f71fb1, 0x2267d3a0, 0x2364a02e, 0x3552a8f4, 

+	0x351acedd, 0x23b836ca, 0x24b0e699, 0x34703095, 0x34364da6, 0x250317df, 0x25f78497, 0x3385a222, 

+	0x3349bf48, 0x264843d9, 0x273847c8, 0x329321c7, 0x32554840, 0x27878893, 0x2872feb6, 0x3198d4ea, 

+	0x31590e3e, 0x28c0b4d2, 0x29a778db, 0x3096e223, 0x30553828, 0x29f3984c, 0x2ad586a3, 0x2f8d713a, 

+	0x2f49ee0f, 0x2b2003ac, 0x2bfcf97c, 0x2e7cab1c, 0x2e37592c, 0x2c45c8a0, 0x2d1da3d5, 0x2d64b9da, 

+	/* 1024 */

+	0x3fffffb1, 0x0006487f, 0x002bfb74, 0x3ffff0e3, 0x3fffe705, 0x00388c6e, 0x005e3f4c, 0x3fffba9b, 

+	0x3fffa6de, 0x006ad03b, 0x009082ea, 0x3fff5cd8, 0x3fff3f3c, 0x009d13c5, 0x00c2c62f, 0x3ffed79b, 

+	0x3ffeb021, 0x00cf56ef, 0x00f508fc, 0x3ffe2ae5, 0x3ffdf98c, 0x01019998, 0x01274b31, 0x3ffd56b5, 

+	0x3ffd1b7e, 0x0133dba3, 0x01598cb1, 0x3ffc5b0c, 0x3ffc15f7, 0x01661cf0, 0x018bcd5b, 0x3ffb37ec, 

+	0x3ffae8f9, 0x01985d60, 0x01be0d11, 0x3ff9ed53, 0x3ff99483, 0x01ca9cd4, 0x01f04bb4, 0x3ff87b44, 

+	0x3ff81896, 0x01fcdb2e, 0x02228924, 0x3ff6e1bf, 0x3ff67534, 0x022f184d, 0x0254c544, 0x3ff520c5, 

+	0x3ff4aa5d, 0x02615414, 0x0286fff3, 0x3ff33858, 0x3ff2b813, 0x02938e62, 0x02b93914, 0x3ff12878, 

+	0x3ff09e56, 0x02c5c71a, 0x02eb7086, 0x3feef126, 0x3fee5d28, 0x02f7fe1c, 0x031da62b, 0x3fec9265, 

+	0x3febf48b, 0x032a3349, 0x034fd9e5, 0x3fea0c35, 0x3fe96480, 0x035c6682, 0x03820b93, 0x3fe75e98, 

+	0x3fe6ad08, 0x038e97a9, 0x03b43b17, 0x3fe48990, 0x3fe3ce26, 0x03c0c69e, 0x03e66852, 0x3fe18d1f, 

+	0x3fe0c7da, 0x03f2f342, 0x04189326, 0x3fde6945, 0x3fdd9a27, 0x04251d77, 0x044abb73, 0x3fdb1e06, 

+	0x3fda450f, 0x0457451d, 0x047ce11a, 0x3fd7ab64, 0x3fd6c894, 0x04896a16, 0x04af03fc, 0x3fd4115f, 

+	0x3fd324b7, 0x04bb8c42, 0x04e123fa, 0x3fd04ffc, 0x3fcf597c, 0x04edab83, 0x051340f6, 0x3fcc673b, 

+	0x3fcb66e4, 0x051fc7b9, 0x05455ad1, 0x3fc8571f, 0x3fc74cf3, 0x0551e0c7, 0x0577716b, 0x3fc41fac, 

+	0x3fc30baa, 0x0583f68c, 0x05a984a6, 0x3fbfc0e3, 0x3fbea30c, 0x05b608eb, 0x05db9463, 0x3fbb3ac7, 

+	0x3fba131b, 0x05e817c3, 0x060da083, 0x3fb68d5b, 0x3fb55bdc, 0x061a22f7, 0x063fa8e7, 0x3fb1b8a2, 

+	0x3fb07d50, 0x064c2a67, 0x0671ad71, 0x3facbc9f, 0x3fab777b, 0x067e2df5, 0x06a3ae00, 0x3fa79954, 

+	0x3fa64a5f, 0x06b02d81, 0x06d5aa77, 0x3fa24ec6, 0x3fa0f600, 0x06e228ee, 0x0707a2b7, 0x3f9cdcf7, 

+	0x3f9b7a62, 0x0714201b, 0x073996a1, 0x3f9743eb, 0x3f95d787, 0x074612eb, 0x076b8616, 0x3f9183a5, 

+	0x3f900d72, 0x0778013d, 0x079d70f7, 0x3f8b9c28, 0x3f8a1c29, 0x07a9eaf5, 0x07cf5726, 0x3f858d79, 

+	0x3f8403ae, 0x07dbcff2, 0x08013883, 0x3f7f579b, 0x3f7dc405, 0x080db016, 0x083314f1, 0x3f78fa92, 

+	0x3f775d31, 0x083f8b43, 0x0864ec4f, 0x3f727661, 0x3f70cf38, 0x08716159, 0x0896be80, 0x3f6bcb0e, 

+	0x3f6a1a1c, 0x08a3323a, 0x08c88b65, 0x3f64f89b, 0x3f633de2, 0x08d4fdc6, 0x08fa52de, 0x3f5dff0e, 

+	0x3f5c3a8f, 0x0906c3e0, 0x092c14ce, 0x3f56de6a, 0x3f551026, 0x09388469, 0x095dd116, 0x3f4f96b4, 

+	0x3f4dbeac, 0x096a3f42, 0x098f8796, 0x3f4827f0, 0x3f464626, 0x099bf44c, 0x09c13831, 0x3f409223, 

+	0x3f3ea697, 0x09cda368, 0x09f2e2c7, 0x3f38d552, 0x3f36e006, 0x09ff4c78, 0x0a24873a, 0x3f30f181, 

+	0x3f2ef276, 0x0a30ef5e, 0x0a56256c, 0x3f28e6b6, 0x3f26ddec, 0x0a628bfa, 0x0a87bd3d, 0x3f20b4f5, 

+	0x3f1ea26e, 0x0a94222f, 0x0ab94e8f, 0x3f185c43, 0x3f164001, 0x0ac5b1dc, 0x0aead944, 0x3f0fdca5, 

+	0x3f0db6a9, 0x0af73ae5, 0x0b1c5d3d, 0x3f073621, 0x3f05066d, 0x0b28bd2a, 0x0b4dda5c, 0x3efe68bc, 

+	0x3efc2f50, 0x0b5a388d, 0x0b7f5081, 0x3ef5747b, 0x3ef3315a, 0x0b8bacf0, 0x0bb0bf8f, 0x3eec5965, 

+	0x3eea0c8e, 0x0bbd1a33, 0x0be22766, 0x3ee3177e, 0x3ee0c0f4, 0x0bee8038, 0x0c1387e9, 0x3ed9aecc, 

+	0x3ed74e91, 0x0c1fdee1, 0x0c44e0f9, 0x3ed01f55, 0x3ecdb56a, 0x0c513610, 0x0c763278, 0x3ec66920, 

+	0x3ec3f585, 0x0c8285a5, 0x0ca77c47, 0x3ebc8c31, 0x3eba0ee9, 0x0cb3cd84, 0x0cd8be47, 0x3eb2888f, 

+	0x3eb0019c, 0x0ce50d8c, 0x0d09f85b, 0x3ea85e41, 0x3ea5cda3, 0x0d1645a0, 0x0d3b2a64, 0x3e9e0d4c, 

+	0x3e9b7306, 0x0d4775a1, 0x0d6c5443, 0x3e9395b7, 0x3e90f1ca, 0x0d789d71, 0x0d9d75db, 0x3e88f788, 

+	0x3e8649f5, 0x0da9bcf2, 0x0dce8f0d, 0x3e7e32c6, 0x3e7b7b90, 0x0ddad406, 0x0dff9fba, 0x3e734778, 

+	0x3e70869f, 0x0e0be28e, 0x0e30a7c5, 0x3e6835a4, 0x3e656b2b, 0x0e3ce86b, 0x0e61a70f, 0x3e5cfd51, 

+	0x3e5a2939, 0x0e6de580, 0x0e929d7a, 0x3e519e86, 0x3e4ec0d1, 0x0e9ed9af, 0x0ec38ae8, 0x3e46194a, 

+	0x3e4331fa, 0x0ecfc4d9, 0x0ef46f3b, 0x3e3a6da4, 0x3e377cbb, 0x0f00a6df, 0x0f254a53, 0x3e2e9b9c, 

+	0x3e2ba11b, 0x0f317fa5, 0x0f561c15, 0x3e22a338, 0x3e1f9f21, 0x0f624f0c, 0x0f86e460, 0x3e168480, 

+	0x3e1376d5, 0x0f9314f5, 0x0fb7a317, 0x3e0a3f7b, 0x3e07283f, 0x0fc3d143, 0x0fe8581d, 0x3dfdd432, 

+	0x3dfab365, 0x0ff483d7, 0x10190352, 0x3df142ab, 0x3dee1851, 0x10252c94, 0x1049a49a, 0x3de48aef, 

+	0x3de15708, 0x1055cb5b, 0x107a3bd5, 0x3dd7ad05, 0x3dd46f94, 0x1086600e, 0x10aac8e6, 0x3dcaa8f5, 

+	0x3dc761fc, 0x10b6ea90, 0x10db4baf, 0x3dbd7ec7, 0x3dba2e48, 0x10e76ac3, 0x110bc413, 0x3db02e84, 

+	0x3dacd481, 0x1117e088, 0x113c31f3, 0x3da2b834, 0x3d9f54af, 0x11484bc2, 0x116c9531, 0x3d951bde, 

+	0x3d91aed9, 0x1178ac53, 0x119cedaf, 0x3d87598c, 0x3d83e309, 0x11a9021d, 0x11cd3b50, 0x3d797145, 

+	0x3d75f147, 0x11d94d02, 0x11fd7df6, 0x3d6b6313, 0x3d67d99b, 0x12098ce5, 0x122db583, 0x3d5d2efe, 

+	0x3d599c0e, 0x1239c1a7, 0x125de1da, 0x3d4ed50f, 0x3d4b38aa, 0x1269eb2b, 0x128e02dc, 0x3d40554e, 

+	0x3d3caf76, 0x129a0954, 0x12be186c, 0x3d31afc5, 0x3d2e007c, 0x12ca1c03, 0x12ee226c, 0x3d22e47c, 

+	0x3d1f2bc5, 0x12fa231b, 0x131e20c0, 0x3d13f37e, 0x3d10315a, 0x132a1e7e, 0x134e1348, 0x3d04dcd2, 

+	0x3d011145, 0x135a0e0e, 0x137df9e7, 0x3cf5a082, 0x3cf1cb8e, 0x1389f1af, 0x13add481, 0x3ce63e98, 

+	0x3ce2603f, 0x13b9c943, 0x13dda2f7, 0x3cd6b71e, 0x3cd2cf62, 0x13e994ab, 0x140d652c, 0x3cc70a1c, 

+	0x3cc318ff, 0x141953cb, 0x143d1b02, 0x3cb7379c, 0x3cb33d22, 0x14490685, 0x146cc45c, 0x3ca73fa9, 

+	0x3ca33bd3, 0x1478acbc, 0x149c611d, 0x3c97224c, 0x3c93151d, 0x14a84652, 0x14cbf127, 0x3c86df8e, 

+	0x3c82c909, 0x14d7d32a, 0x14fb745e, 0x3c76777b, 0x3c7257a2, 0x15075327, 0x152aeaa3, 0x3c65ea1c, 

+	0x3c61c0f1, 0x1536c62b, 0x155a53d9, 0x3c55377b, 0x3c510501, 0x15662c18, 0x1589afe3, 0x3c445fa2, 

+	0x3c4023dd, 0x159584d3, 0x15b8fea4, 0x3c33629d, 0x3c2f1d8e, 0x15c4d03e, 0x15e83fff, 0x3c224075, 

+	0x3c1df21f, 0x15f40e3a, 0x161773d6, 0x3c10f935, 0x3c0ca19b, 0x16233eac, 0x16469a0d, 0x3bff8ce8, 

+	0x3bfb2c0c, 0x16526176, 0x1675b286, 0x3bedfb99, 0x3be9917e, 0x1681767c, 0x16a4bd25, 0x3bdc4552, 

+	0x3bd7d1fa, 0x16b07d9f, 0x16d3b9cc, 0x3bca6a1d, 0x3bc5ed8d, 0x16df76c3, 0x1702a85e, 0x3bb86a08, 

+	0x3bb3e440, 0x170e61cc, 0x173188be, 0x3ba6451b, 0x3ba1b620, 0x173d3e9b, 0x17605ad0, 0x3b93fb63, 

+	0x3b8f6337, 0x176c0d15, 0x178f1e76, 0x3b818ceb, 0x3b7ceb90, 0x179acd1c, 0x17bdd394, 0x3b6ef9be, 

+	0x3b6a4f38, 0x17c97e93, 0x17ec7a0d, 0x3b5c41e8, 0x3b578e39, 0x17f8215e, 0x181b11c4, 0x3b496574, 

+	0x3b44a8a0, 0x1826b561, 0x18499a9d, 0x3b36646e, 0x3b319e77, 0x18553a7d, 0x1878147a, 0x3b233ee1, 

+	0x3b1e6fca, 0x1883b097, 0x18a67f3f, 0x3b0ff4d9, 0x3b0b1ca6, 0x18b21791, 0x18d4dad0, 0x3afc8663, 

+	0x3af7a516, 0x18e06f50, 0x1903270f, 0x3ae8f38b, 0x3ae40926, 0x190eb7b7, 0x193163e1, 0x3ad53c5b, 

+	0x3ad048e3, 0x193cf0a9, 0x195f9128, 0x3ac160e1, 0x3abc6458, 0x196b1a09, 0x198daec8, 0x3aad6129, 

+	0x3aa85b92, 0x199933bb, 0x19bbbca6, 0x3a993d3e, 0x3a942e9d, 0x19c73da3, 0x19e9baa3, 0x3a84f52f, 

+	0x3a7fdd86, 0x19f537a4, 0x1a17a8a5, 0x3a708906, 0x3a6b6859, 0x1a2321a2, 0x1a45868e, 0x3a5bf8d1, 

+	0x3a56cf23, 0x1a50fb81, 0x1a735442, 0x3a47449c, 0x3a4211f0, 0x1a7ec524, 0x1aa111a6, 0x3a326c74, 

+	0x3a2d30cd, 0x1aac7e6f, 0x1acebe9d, 0x3a1d7066, 0x3a182bc8, 0x1ada2746, 0x1afc5b0a, 0x3a08507f, 

+	0x3a0302ed, 0x1b07bf8c, 0x1b29e6d2, 0x39f30ccc, 0x39edb649, 0x1b354727, 0x1b5761d8, 0x39dda55a, 

+	0x39d845e9, 0x1b62bdf8, 0x1b84cc01, 0x39c81a36, 0x39c2b1da, 0x1b9023e5, 0x1bb22530, 0x39b26b6d, 

+	0x39acfa2b, 0x1bbd78d2, 0x1bdf6d4a, 0x399c990d, 0x39971ee7, 0x1beabca1, 0x1c0ca432, 0x3986a324, 

+	0x3981201e, 0x1c17ef39, 0x1c39c9cd, 0x397089bf, 0x396afddc, 0x1c45107c, 0x1c66ddfe, 0x395a4ceb, 

+	0x3954b82e, 0x1c72204f, 0x1c93e0ab, 0x3943ecb6, 0x393e4f23, 0x1c9f1e96, 0x1cc0d1b6, 0x392d692f, 

+	0x3927c2c9, 0x1ccc0b35, 0x1cedb106, 0x3916c262, 0x3911132d, 0x1cf8e611, 0x1d1a7e7d, 0x38fff85e, 

+	0x38fa405e, 0x1d25af0d, 0x1d473a00, 0x38e90b31, 0x38e34a69, 0x1d52660f, 0x1d73e374, 0x38d1fae9, 

+	0x38cc315d, 0x1d7f0afb, 0x1da07abc, 0x38bac795, 0x38b4f547, 0x1dab9db5, 0x1dccffbf, 0x38a37142, 

+	0x389d9637, 0x1dd81e21, 0x1df9725f, 0x388bf7ff, 0x3886143b, 0x1e048c24, 0x1e25d282, 0x38745bdb, 

+	0x386e6f60, 0x1e30e7a4, 0x1e52200c, 0x385c9ce3, 0x3856a7b6, 0x1e5d3084, 0x1e7e5ae2, 0x3844bb28, 

+	0x383ebd4c, 0x1e8966a8, 0x1eaa82e9, 0x382cb6b7, 0x3826b030, 0x1eb589f7, 0x1ed69805, 0x38148f9f, 

+	0x380e8071, 0x1ee19a54, 0x1f029a1c, 0x37fc45ef, 0x37f62e1d, 0x1f0d97a5, 0x1f2e8911, 0x37e3d9b7, 

+	0x37ddb945, 0x1f3981ce, 0x1f5a64cb, 0x37cb4b04, 0x37c521f6, 0x1f6558b5, 0x1f862d2d, 0x37b299e7, 

+	0x37ac6841, 0x1f911c3d, 0x1fb1e21d, 0x3799c66f, 0x37938c34, 0x1fbccc4d, 0x1fdd8381, 0x3780d0aa, 

+	0x377a8ddf, 0x1fe868c8, 0x2009113c, 0x3767b8a9, 0x37616d51, 0x2013f196, 0x20348b35, 0x374e7e7b, 

+	0x37482a9a, 0x203f6699, 0x205ff14f, 0x3735222f, 0x372ec5c9, 0x206ac7b8, 0x208b4372, 0x371ba3d4, 

+	0x37153eee, 0x209614d9, 0x20b68181, 0x3702037c, 0x36fb9618, 0x20c14ddf, 0x20e1ab63, 0x36e84135, 

+	0x36e1cb58, 0x20ec72b1, 0x210cc0fc, 0x36ce5d10, 0x36c7debd, 0x21178334, 0x2137c232, 0x36b4571b, 

+	0x36add058, 0x21427f4d, 0x2162aeea, 0x369a2f69, 0x3693a038, 0x216d66e2, 0x218d870b, 0x367fe608, 

+	0x36794e6e, 0x219839d8, 0x21b84a79, 0x36657b08, 0x365edb09, 0x21c2f815, 0x21e2f91a, 0x364aee7b, 

+	0x3644461b, 0x21eda17f, 0x220d92d4, 0x36304070, 0x36298fb4, 0x221835fb, 0x2238178d, 0x361570f8, 

+	0x360eb7e3, 0x2242b56f, 0x22628729, 0x35fa8023, 0x35f3beba, 0x226d1fc1, 0x228ce191, 0x35df6e03, 

+	0x35d8a449, 0x229774d7, 0x22b726a8, 0x35c43aa7, 0x35bd68a1, 0x22c1b496, 0x22e15655, 0x35a8e621, 

+	0x35a20bd3, 0x22ebdee5, 0x230b707e, 0x358d7081, 0x35868def, 0x2315f3a8, 0x23357509, 0x3571d9d9, 

+	0x356aef08, 0x233ff2c8, 0x235f63dc, 0x35562239, 0x354f2f2c, 0x2369dc29, 0x23893cdd, 0x353a49b2, 

+	0x35334e6f, 0x2393afb2, 0x23b2fff3, 0x351e5056, 0x35174ce0, 0x23bd6d48, 0x23dcad03, 0x35023636, 

+	0x34fb2a92, 0x23e714d3, 0x240643f4, 0x34e5fb63, 0x34dee795, 0x2410a639, 0x242fc4ad, 0x34c99fef, 

+	0x34c283fb, 0x243a215f, 0x24592f13, 0x34ad23eb, 0x34a5ffd5, 0x2463862c, 0x2482830d, 0x34908768, 

+	0x34895b36, 0x248cd487, 0x24abc082, 0x3473ca79, 0x346c962f, 0x24b60c57, 0x24d4e757, 0x3456ed2f, 

+	0x344fb0d1, 0x24df2d81, 0x24fdf775, 0x3439ef9c, 0x3432ab2e, 0x250837ed, 0x2526f0c1, 0x341cd1d2, 

+	0x34158559, 0x25312b81, 0x254fd323, 0x33ff93e2, 0x33f83f62, 0x255a0823, 0x25789e80, 0x33e235df, 

+	0x33dad95e, 0x2582cdbc, 0x25a152c0, 0x33c4b7db, 0x33bd535c, 0x25ab7c30, 0x25c9efca, 0x33a719e8, 

+	0x339fad70, 0x25d41369, 0x25f27584, 0x33895c18, 0x3381e7ac, 0x25fc934b, 0x261ae3d6, 0x336b7e7e, 

+	0x33640223, 0x2624fbbf, 0x26433aa7, 0x334d812d, 0x3345fce6, 0x264d4cac, 0x266b79dd, 0x332f6435, 

+	0x3327d808, 0x267585f8, 0x2693a161, 0x331127ab, 0x3309939c, 0x269da78b, 0x26bbb119, 0x32f2cba1, 

+	0x32eb2fb5, 0x26c5b14c, 0x26e3a8ec, 0x32d45029, 0x32ccac64, 0x26eda322, 0x270b88c2, 0x32b5b557, 

+	0x32ae09be, 0x27157cf5, 0x27335082, 0x3296fb3d, 0x328f47d5, 0x273d3eac, 0x275b0014, 0x327821ee, 

+	0x327066bc, 0x2764e82f, 0x27829760, 0x3259297d, 0x32516686, 0x278c7965, 0x27aa164c, 0x323a11fe, 

+	0x32324746, 0x27b3f235, 0x27d17cc1, 0x321adb83, 0x3213090f, 0x27db5288, 0x27f8caa5, 0x31fb8620, 

+	0x31f3abf5, 0x28029a45, 0x281fffe2, 0x31dc11e8, 0x31d4300b, 0x2829c954, 0x28471c5e, 0x31bc7eee, 

+	0x31b49564, 0x2850df9d, 0x286e2002, 0x319ccd46, 0x3194dc14, 0x2877dd07, 0x28950ab6, 0x317cfd04, 

+	0x3175042e, 0x289ec17a, 0x28bbdc61, 0x315d0e3b, 0x31550dc6, 0x28c58cdf, 0x28e294eb, 0x313d00ff, 

+	0x3134f8f1, 0x28ec3f1e, 0x2909343e, 0x311cd564, 0x3114c5c0, 0x2912d81f, 0x292fba40, 0x30fc8b7d, 

+	0x30f47449, 0x293957c9, 0x295626da, 0x30dc235e, 0x30d404a0, 0x295fbe06, 0x297c79f5, 0x30bb9d1c, 

+	0x30b376d8, 0x29860abd, 0x29a2b378, 0x309af8ca, 0x3092cb05, 0x29ac3dd7, 0x29c8d34d, 0x307a367c, 

+	0x3072013c, 0x29d2573c, 0x29eed95b, 0x30595648, 0x30511991, 0x29f856d5, 0x2a14c58b, 0x30385840, 

+	0x30301418, 0x2a1e3c8a, 0x2a3a97c7, 0x30173c7a, 0x300ef0e5, 0x2a440844, 0x2a604ff5, 0x2ff6030a, 

+	0x2fedb00d, 0x2a69b9ec, 0x2a85ee00, 0x2fd4ac04, 0x2fcc51a5, 0x2a8f516b, 0x2aab71d0, 0x2fb3377c, 

+	0x2faad5c1, 0x2ab4cea9, 0x2ad0db4e, 0x2f91a589, 0x2f893c75, 0x2ada318e, 0x2af62a63, 0x2f6ff63d, 

+	0x2f6785d7, 0x2aff7a05, 0x2b1b5ef8, 0x2f4e29af, 0x2f45b1fb, 0x2b24a7f6, 0x2b4078f5, 0x2f2c3ff2, 

+	0x2f23c0f6, 0x2b49bb4a, 0x2b657844, 0x2f0a391d, 0x2f01b2de, 0x2b6eb3ea, 0x2b8a5cce, 0x2ee81543, 

+	0x2edf87c6, 0x2b9391c0, 0x2baf267d, 0x2ec5d479, 0x2ebd3fc4, 0x2bb854b4, 0x2bd3d53a, 0x2ea376d6, 

+	0x2e9adaee, 0x2bdcfcb0, 0x2bf868ed, 0x2e80fc6e, 0x2e785958, 0x2c01899e, 0x2c1ce181, 0x2e5e6556, 

+	0x2e55bb17, 0x2c25fb66, 0x2c413edf, 0x2e3bb1a4, 0x2e330042, 0x2c4a51f3, 0x2c6580f1, 0x2e18e16d, 

+	0x2e1028ed, 0x2c6e8d2e, 0x2c89a79f, 0x2df5f4c7, 0x2ded352f, 0x2c92ad01, 0x2cadb2d5, 0x2dd2ebc7, 

+	0x2dca251c, 0x2cb6b155, 0x2cd1a27b, 0x2dafc683, 0x2da6f8ca, 0x2cda9a14, 0x2cf5767c, 0x2d8c8510, 

+	0x2d83b04f, 0x2cfe6728, 0x2d192ec1, 0x2d692784, 0x2d604bc0, 0x2d22187a, 0x2d3ccb34, 0x2d45adf6

+};

+

+

+const int twidTab512[(8*6 + 32*6 + 128*6)/2] = {

+	0x40000000, 0x40000000, 0x40000000, 0x3b20187d, 

+	0x3ec50c7c, 0x3536238e, 0x2d412d41, 0x3b20187d, 

+	0x187d3b20, 0x187d3b20, 0x3536238e, 0xf3843ec5, 

+	0x00004000, 0x2d412d41, 0xd2bf2d41, 0xe7833b20, 

+	0x238e3536, 0xc13b0c7c, 0xd2bf2d41, 0x187d3b20, 

+	0xc4e0e783, 0xc4e0187d, 0x0c7c3ec5, 0xdc72caca, 

+

+	0x40000000, 0x40000000, 0x40000000, 0x3fb10645, 

+	0x3fec0323, 0x3f4e0964, 0x3ec50c7c, 0x3fb10645, 

+	0x3d3e1294, 0x3d3e1294, 0x3f4e0964, 0x39da1b5d, 

+	0x3b20187d, 0x3ec50c7c, 0x3536238e, 0x38711e2b, 

+	0x3e140f8c, 0x2f6b2afa, 0x3536238e, 0x3d3e1294, 

+	0x28993179, 0x31792899, 0x3c42158f, 0x20e736e5, 

+	0x2d412d41, 0x3b20187d, 0x187d3b20, 0x28993179, 

+	0x39da1b5d, 0x0f8c3e14, 0x238e3536, 0x38711e2b, 

+	0x06453fb1, 0x1e2b3871, 0x36e520e7, 0xfcdd3fec, 

+	0x187d3b20, 0x3536238e, 0xf3843ec5, 0x12943d3e, 

+	0x3367261f, 0xea713c42, 0x0c7c3ec5, 0x31792899, 

+	0xe1d53871, 0x06453fb1, 0x2f6b2afa, 0xd9e13367, 

+	0x00004000, 0x2d412d41, 0xd2bf2d41, 0xf9bb3fb1, 

+	0x2afa2f6b, 0xcc99261f, 0xf3843ec5, 0x28993179, 

+	0xc78f1e2b, 0xed6c3d3e, 0x261f3367, 0xc3be158f, 

+	0xe7833b20, 0x238e3536, 0xc13b0c7c, 0xe1d53871, 

+	0x20e736e5, 0xc0140323, 0xdc723536, 0x1e2b3871, 

+	0xc04ff9bb, 0xd7673179, 0x1b5d39da, 0xc1ecf074, 

+	0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xce872899, 

+	0x158f3c42, 0xc91bdf19, 0xcaca238e, 0x12943d3e, 

+	0xce87d767, 0xc78f1e2b, 0x0f8c3e14, 0xd506d095, 

+	0xc4e0187d, 0x0c7c3ec5, 0xdc72caca, 0xc2c21294, 

+	0x09643f4e, 0xe4a3c626, 0xc13b0c7c, 0x06453fb1, 

+	0xed6cc2c2, 0xc04f0645, 0x03233fec, 0xf69cc0b2, 

+

+	0x40000000, 0x40000000, 0x40000000, 0x3ffb0192, 

+	0x3ffe00c9, 0x3ff4025b, 0x3fec0323, 0x3ffb0192, 

+	0x3fd304b5, 0x3fd304b5, 0x3ff4025b, 0x3f9c070d, 

+	0x3fb10645, 0x3fec0323, 0x3f4e0964, 0x3f8407d5, 

+	0x3fe103ec, 0x3eeb0bb6, 0x3f4e0964, 0x3fd304b5, 

+	0x3e710e05, 0x3f0e0af1, 0x3fc3057d, 0x3de2104f, 

+	0x3ec50c7c, 0x3fb10645, 0x3d3e1294, 0x3e710e05, 

+	0x3f9c070d, 0x3c8414d1, 0x3e140f8c, 0x3f8407d5, 

+	0x3bb61708, 0x3dae1111, 0x3f6a089c, 0x3ad21937, 

+	0x3d3e1294, 0x3f4e0964, 0x39da1b5d, 0x3cc51413, 

+	0x3f2f0a2a, 0x38cf1d79, 0x3c42158f, 0x3f0e0af1, 

+	0x37af1f8b, 0x3bb61708, 0x3eeb0bb6, 0x367c2192, 

+	0x3b20187d, 0x3ec50c7c, 0x3536238e, 0x3a8219ef, 

+	0x3e9c0d41, 0x33de257d, 0x39da1b5d, 0x3e710e05, 

+	0x3274275f, 0x392a1cc6, 0x3e440ec9, 0x30f82934, 

+	0x38711e2b, 0x3e140f8c, 0x2f6b2afa, 0x37af1f8b, 

+	0x3de2104f, 0x2dce2cb2, 0x36e520e7, 0x3dae1111, 

+	0x2c212e5a, 0x3612223d, 0x3d7711d3, 0x2a652ff1, 

+	0x3536238e, 0x3d3e1294, 0x28993179, 0x345324da, 

+	0x3d021354, 0x26c032ee, 0x3367261f, 0x3cc51413, 

+	0x24da3453, 0x3274275f, 0x3c8414d1, 0x22e635a5, 

+	0x31792899, 0x3c42158f, 0x20e736e5, 0x307629cd, 

+	0x3bfd164c, 0x1edc3811, 0x2f6b2afa, 0x3bb61708, 

+	0x1cc6392a, 0x2e5a2c21, 0x3b6c17c3, 0x1aa63a2f, 

+	0x2d412d41, 0x3b20187d, 0x187d3b20, 0x2c212e5a, 

+	0x3ad21937, 0x164c3bfd, 0x2afa2f6b, 0x3a8219ef, 

+	0x14133cc5, 0x29cd3076, 0x3a2f1aa6, 0x11d33d77, 

+	0x28993179, 0x39da1b5d, 0x0f8c3e14, 0x275f3274, 

+	0x39831c12, 0x0d413e9c, 0x261f3367, 0x392a1cc6, 

+	0x0af13f0e, 0x24da3453, 0x38cf1d79, 0x089c3f6a, 

+	0x238e3536, 0x38711e2b, 0x06453fb1, 0x223d3612, 

+	0x38111edc, 0x03ec3fe1, 0x20e736e5, 0x37af1f8b, 

+	0x01923ffb, 0x1f8b37af, 0x374b2039, 0xff373ffe, 

+	0x1e2b3871, 0x36e520e7, 0xfcdd3fec, 0x1cc6392a, 

+	0x367c2192, 0xfa833fc3, 0x1b5d39da, 0x3612223d, 

+	0xf82b3f84, 0x19ef3a82, 0x35a522e6, 0xf5d63f2f, 

+	0x187d3b20, 0x3536238e, 0xf3843ec5, 0x17083bb6, 

+	0x34c62434, 0xf1373e44, 0x158f3c42, 0x345324da, 

+	0xeeef3dae, 0x14133cc5, 0x33de257d, 0xecac3d02, 

+	0x12943d3e, 0x3367261f, 0xea713c42, 0x11113dae, 

+	0x32ee26c0, 0xe83d3b6c, 0x0f8c3e14, 0x3274275f, 

+	0xe6113a82, 0x0e053e71, 0x31f727fd, 0xe3ee3983, 

+	0x0c7c3ec5, 0x31792899, 0xe1d53871, 0x0af13f0e, 

+	0x30f82934, 0xdfc7374b, 0x09643f4e, 0x307629cd, 

+	0xddc33612, 0x07d53f84, 0x2ff12a65, 0xdbcc34c6, 

+	0x06453fb1, 0x2f6b2afa, 0xd9e13367, 0x04b53fd3, 

+	0x2ee32b8e, 0xd80331f7, 0x03233fec, 0x2e5a2c21, 

+	0xd6333076, 0x01923ffb, 0x2dce2cb2, 0xd4722ee3, 

+	0x00004000, 0x2d412d41, 0xd2bf2d41, 0xfe6e3ffb, 

+	0x2cb22dce, 0xd11d2b8e, 0xfcdd3fec, 0x2c212e5a, 

+	0xcf8a29cd, 0xfb4b3fd3, 0x2b8e2ee3, 0xce0927fd, 

+	0xf9bb3fb1, 0x2afa2f6b, 0xcc99261f, 0xf82b3f84, 

+	0x2a652ff1, 0xcb3a2434, 0xf69c3f4e, 0x29cd3076, 

+	0xc9ee223d, 0xf50f3f0e, 0x293430f8, 0xc8b52039, 

+	0xf3843ec5, 0x28993179, 0xc78f1e2b, 0xf1fb3e71, 

+	0x27fd31f7, 0xc67d1c12, 0xf0743e14, 0x275f3274, 

+	0xc57e19ef, 0xeeef3dae, 0x26c032ee, 0xc49417c3, 

+	0xed6c3d3e, 0x261f3367, 0xc3be158f, 0xebed3cc5, 

+	0x257d33de, 0xc2fe1354, 0xea713c42, 0x24da3453, 

+	0xc2521111, 0xe8f83bb6, 0x243434c6, 0xc1bc0ec9, 

+	0xe7833b20, 0x238e3536, 0xc13b0c7c, 0xe6113a82, 

+	0x22e635a5, 0xc0d10a2a, 0xe4a339da, 0x223d3612, 

+	0xc07c07d5, 0xe33a392a, 0x2192367c, 0xc03d057d, 

+	0xe1d53871, 0x20e736e5, 0xc0140323, 0xe07537af, 

+	0x2039374b, 0xc00200c9, 0xdf1936e5, 0x1f8b37af, 

+	0xc005fe6e, 0xddc33612, 0x1edc3811, 0xc01ffc14, 

+	0xdc723536, 0x1e2b3871, 0xc04ff9bb, 0xdb263453, 

+	0x1d7938cf, 0xc096f764, 0xd9e13367, 0x1cc6392a, 

+	0xc0f2f50f, 0xd8a13274, 0x1c123983, 0xc164f2bf, 

+	0xd7673179, 0x1b5d39da, 0xc1ecf074, 0xd6333076, 

+	0x1aa63a2f, 0xc289ee2d, 0xd5062f6b, 0x19ef3a82, 

+	0xc33bebed, 0xd3df2e5a, 0x19373ad2, 0xc403e9b4, 

+	0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xd1a62c21, 

+	0x17c33b6c, 0xc5d1e55a, 0xd0952afa, 0x17083bb6, 

+	0xc6d6e33a, 0xcf8a29cd, 0x164c3bfd, 0xc7efe124, 

+	0xce872899, 0x158f3c42, 0xc91bdf19, 0xcd8c275f, 

+	0x14d13c84, 0xca5bdd1a, 0xcc99261f, 0x14133cc5, 

+	0xcbaddb26, 0xcbad24da, 0x13543d02, 0xcd12d940, 

+	0xcaca238e, 0x12943d3e, 0xce87d767, 0xc9ee223d, 

+	0x11d33d77, 0xd00fd59b, 0xc91b20e7, 0x11113dae, 

+	0xd1a6d3df, 0xc8511f8b, 0x104f3de2, 0xd34ed232, 

+	0xc78f1e2b, 0x0f8c3e14, 0xd506d095, 0xc6d61cc6, 

+	0x0ec93e44, 0xd6cccf08, 0xc6261b5d, 0x0e053e71, 

+	0xd8a1cd8c, 0xc57e19ef, 0x0d413e9c, 0xda83cc22, 

+	0xc4e0187d, 0x0c7c3ec5, 0xdc72caca, 0xc44a1708, 

+	0x0bb63eeb, 0xde6ec984, 0xc3be158f, 0x0af13f0e, 

+	0xe075c851, 0xc33b1413, 0x0a2a3f2f, 0xe287c731, 

+	0xc2c21294, 0x09643f4e, 0xe4a3c626, 0xc2521111, 

+	0x089c3f6a, 0xe6c9c52e, 0xc1ec0f8c, 0x07d53f84, 

+	0xe8f8c44a, 0xc18f0e05, 0x070d3f9c, 0xeb2fc37c, 

+	0xc13b0c7c, 0x06453fb1, 0xed6cc2c2, 0xc0f20af1, 

+	0x057d3fc3, 0xefb1c21e, 0xc0b20964, 0x04b53fd3, 

+	0xf1fbc18f, 0xc07c07d5, 0x03ec3fe1, 0xf44ac115, 

+	0xc04f0645, 0x03233fec, 0xf69cc0b2, 0xc02d04b5, 

+	0x025b3ff4, 0xf8f3c064, 0xc0140323, 0x01923ffb, 

+	0xfb4bc02d, 0xc0050192, 0x00c93ffe, 0xfda5c00c	

+};

+

+const int twidTab64[(4*6 + 16*6)/2] = {

+	0x40000000, 0x40000000, 0x40000000, 0x2d412d41, 

+	0x3b20187d, 0x187d3b20, 0x00004000, 0x2d412d41, 

+	0xd2bf2d41, 0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 

+

+	0x40000000, 0x40000000, 0x40000000, 0x3ec50c7c, 

+	0x3fb10645, 0x3d3e1294, 0x3b20187d, 0x3ec50c7c, 

+	0x3536238e, 0x3536238e, 0x3d3e1294, 0x28993179, 

+	0x2d412d41, 0x3b20187d, 0x187d3b20, 0x238e3536, 

+	0x38711e2b, 0x06453fb1, 0x187d3b20, 0x3536238e, 

+	0xf3843ec5, 0x0c7c3ec5, 0x31792899, 0xe1d53871, 

+	0x00004000, 0x2d412d41, 0xd2bf2d41, 0xf3843ec5, 

+	0x28993179, 0xc78f1e2b, 0xe7833b20, 0x238e3536, 

+	0xc13b0c7c, 0xdc723536, 0x1e2b3871, 0xc04ff9bb, 

+	0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xcaca238e, 

+	0x12943d3e, 0xce87d767, 0xc4e0187d, 0x0c7c3ec5, 

+	0xdc72caca, 0xc13b0c7c, 0x06453fb1, 0xed6cc2c2 

+};

+

+#elif defined ARMV7Neon

+/* 

+ *  Q29 for 128 and 1024 

+ *

+ * for (i = 0; i < num/4; i++) {

+ *   angle = (i + 0.125) * M_PI / num;

+ *   x = cos(angle) * (1 << 29);

+ *   x = sin(angle) * (1 << 29);

+ * 

+ *   angle = (num/2 - 1 - i + 0.125) * M_PI / num;

+ *   x = cos(angle) * (1 << 29);

+ *   x = sin(angle) * (1 << 29);

+ * }

+ */

+const int cossintab[128 + 1024] = {

+	/* 128 */

+	0x1ffff621, 0x001921f9, 0x00afea69, 0x1ffe1c68, 0x1ffce09d, 0x00e22a7a, 0x0178dbaa, 0x1ff753bb, 
+	0x1ff4dc55, 0x01ab101c, 0x024192cf, 0x1feb9d25, 0x1fe7ea85, 0x0273b3e2, 0x0309f0e2, 0x1fdafa75, 
+	0x1fd60d2e, 0x033bf6dd, 0x03d1d700, 0x1fc56e3b, 0x1fbf470f, 0x0403ba2b, 0x04992653, 0x1faafbcb, 
+	0x1fa39bac, 0x04cadefe, 0x055fc022, 0x1f8ba738, 0x1f830f4a, 0x059146a1, 0x062585ca, 0x1f677557, 
+	0x1f5da6ed, 0x0656d27a, 0x06ea58cd, 0x1f3e6bbc, 0x1f33685a, 0x071b6415, 0x07ae1ad2, 0x1f1090bd, 
+	0x1f045a15, 0x07dedd20, 0x0870ada7, 0x1eddeb6a, 0x1ed0835f, 0x08a11f78, 0x0931f34d, 0x1ea68394, 
+	0x1e97ec36, 0x09620d27, 0x09f1cdf5, 0x1e6a61c5, 0x1e5a9d55, 0x0a21886e, 0x0ab02009, 0x1e298f44, 
+	0x1e18a030, 0x0adf73c6, 0x0b6ccc32, 0x1de4160f, 0x1dd1fef4, 0x0b9bb1e5, 0x0c27b555, 0x1d9a00de, 
+	0x1d86c484, 0x0c5625c3, 0x0ce0bea2, 0x1d4b5b1b, 0x1d36fc7c, 0x0d0eb2a2, 0x0d97cb8f, 0x1cf830e9, 
+	0x1ce2b328, 0x0dc53c0a, 0x0e4cbfe2, 0x1ca08f1a, 0x1c89f587, 0x0e79a5d7, 0x0eff7fb3, 0x1c448331, 
+	0x1c2cd149, 0x0f2bd437, 0x0fafef73, 0x1be41b61, 0x1bcb54cb, 0x0fdbabae, 0x105df3ec, 0x1b7f6687, 
+	0x1b658f15, 0x10891120, 0x11097249, 0x1b16742a, 0x1afb8fd9, 0x1133e9d0, 0x11b25017, 0x1aa9547a, 
+	0x1a8d676e, 0x11dc1b65, 0x1258734d, 0x1a38184a, 0x1a1b26d3, 0x12818bef, 0x12fbc24b, 0x19c2d111, 
+	0x19a4dfa4, 0x132421ec, 0x139c23e4, 0x194990e4, 0x192aa420, 0x13c3c44a, 0x14397f5b, 0x18cc6a75, 
+	0x18ac871f, 0x14605a69, 0x14d3bc6d, 0x184b7112, 0x182a9c14, 0x14f9cc26, 0x156ac352, 0x17c6b89d, 
+	0x17a4f708, 0x159001d6, 0x15fe7cbe, 0x173e558e, 0x171bac96, 0x1622e450, 0x168ed1eb, 0x16b25ced,

+	/* 1024 */

+	0x1fffffd9, 0x0003243f, 0x0015fdba, 0x1ffff872, 0x1ffff382, 0x001c4637, 0x002f1fa6, 0x1fffdd4d, 

+	0x1fffd36f, 0x0035681d, 0x00484175, 0x1fffae6c, 0x1fff9f9e, 0x004e89e3, 0x00616318, 0x1fff6bce, 

+	0x1fff5811, 0x0067ab77, 0x007a847e, 0x1fff1572, 0x1ffefcc6, 0x0080cccc, 0x0093a599, 0x1ffeab5b, 

+	0x1ffe8dbf, 0x0099edd2, 0x00acc658, 0x1ffe2d86, 0x1ffe0afc, 0x00b30e78, 0x00c5e6ad, 0x1ffd9bf6, 

+	0x1ffd747c, 0x00cc2eb0, 0x00df0688, 0x1ffcf6aa, 0x1ffcca41, 0x00e54e6a, 0x00f825da, 0x1ffc3da2, 

+	0x1ffc0c4b, 0x00fe6d97, 0x01114492, 0x1ffb70e0, 0x1ffb3a9a, 0x01178c27, 0x012a62a2, 0x1ffa9063, 

+	0x1ffa552e, 0x0130aa0a, 0x01437ffa, 0x1ff99c2c, 0x1ff95c09, 0x0149c731, 0x015c9c8a, 0x1ff8943c, 

+	0x1ff84f2b, 0x0162e38d, 0x0175b843, 0x1ff77893, 0x1ff72e94, 0x017bff0e, 0x018ed316, 0x1ff64932, 

+	0x1ff5fa46, 0x019519a5, 0x01a7ecf2, 0x1ff5061b, 0x1ff4b240, 0x01ae3341, 0x01c105c9, 0x1ff3af4c, 

+	0x1ff35684, 0x01c74bd5, 0x01da1d8c, 0x1ff244c8, 0x1ff1e713, 0x01e0634f, 0x01f33429, 0x1ff0c68f, 

+	0x1ff063ed, 0x01f979a1, 0x020c4993, 0x1fef34a3, 0x1feecd14, 0x02128ebb, 0x02255db9, 0x1fed8f03, 

+	0x1fed2287, 0x022ba28f, 0x023e708d, 0x1febd5b2, 0x1feb644a, 0x0244b50b, 0x025781fe, 0x1fea08b0, 

+	0x1fe9925c, 0x025dc621, 0x027091fd, 0x1fe827fe, 0x1fe7acbe, 0x0276d5c1, 0x0289a07b, 0x1fe6339d, 

+	0x1fe5b372, 0x028fe3dd, 0x02a2ad69, 0x1fe42b90, 0x1fe3a679, 0x02a8f063, 0x02bbb8b6, 0x1fe20fd6, 

+	0x1fe185d5, 0x02c1fb46, 0x02d4c253, 0x1fdfe071, 0x1fdf5186, 0x02db0475, 0x02edca32, 0x1fdd9d64, 

+	0x1fdd098e, 0x02f40be2, 0x0306d042, 0x1fdb46ae, 0x1fdaadee, 0x030d117c, 0x031fd474, 0x1fd8dc51, 

+	0x1fd83ea8, 0x03261534, 0x0338d6b8, 0x1fd65e4f, 0x1fd5bbbd, 0x033f16fb, 0x0351d700, 0x1fd3ccaa, 

+	0x1fd32530, 0x035816c1, 0x036ad53c, 0x1fd12763, 0x1fd07b00, 0x03711477, 0x0383d15c, 0x1fce6e7c, 

+	0x1fcdbd31, 0x038a100e, 0x039ccb51, 0x1fcba1f5, 0x1fcaebc3, 0x03a30975, 0x03b5c30b, 0x1fc8c1d2, 

+	0x1fc806b9, 0x03bc009f, 0x03ceb87c, 0x1fc5ce14, 0x1fc50e14, 0x03d4f57a, 0x03e7ab93, 0x1fc2c6bd, 

+	0x1fc201d7, 0x03ede7f9, 0x04009c42, 0x1fbfabcd, 0x1fbee202, 0x0406d80b, 0x04198a78, 0x1fbc7d49, 

+	0x1fbbae99, 0x041fc5a1, 0x04327628, 0x1fb93b31, 0x1fb8679c, 0x0438b0ac, 0x044b5f40, 0x1fb5e587, 

+	0x1fb50d0e, 0x0451991d, 0x046445b2, 0x1fb27c4e, 0x1fb19ef1, 0x046a7ee3, 0x047d296f, 0x1faeff87, 

+	0x1fae1d47, 0x048361f0, 0x04960a67, 0x1fab6f35, 0x1faa8813, 0x049c4235, 0x04aee88b, 0x1fa7cb5a, 

+	0x1fa6df56, 0x04b51fa1, 0x04c7c3cb, 0x1fa413f8, 0x1fa32313, 0x04cdfa26, 0x04e09c18, 0x1fa04912, 

+	0x1f9f534c, 0x04e6d1b4, 0x04f97163, 0x1f9c6aa9, 0x1f9b7003, 0x04ffa63c, 0x0512439d, 0x1f9878c1, 

+	0x1f97793b, 0x051877af, 0x052b12b6, 0x1f94735b, 0x1f936ef6, 0x053145fd, 0x0543de9e, 0x1f905a7a, 

+	0x1f8f5137, 0x054a1117, 0x055ca748, 0x1f8c2e21, 0x1f8b2000, 0x0562d8ee, 0x05756ca2, 0x1f87ee52, 

+	0x1f86db55, 0x057b9d73, 0x058e2e9f, 0x1f839b10, 0x1f828336, 0x05945e95, 0x05a6ed2e, 0x1f7f345e, 

+	0x1f7e17a8, 0x05ad1c47, 0x05bfa840, 0x1f7aba3e, 0x1f7998ad, 0x05c5d678, 0x05d85fc7, 0x1f762cb2, 

+	0x1f750647, 0x05de8d19, 0x05f113b3, 0x1f718bbf, 0x1f70607a, 0x05f7401c, 0x0609c3f5, 0x1f6cd766, 

+	0x1f6ba748, 0x060fef71, 0x0622707d, 0x1f680fab, 0x1f66dab5, 0x06289b08, 0x063b193c, 0x1f633490, 

+	0x1f61fac3, 0x064142d3, 0x0653be23, 0x1f5e4619, 0x1f5d0775, 0x0659e6c2, 0x066c5f24, 0x1f594448, 

+	0x1f5800ce, 0x067286c6, 0x0684fc2e, 0x1f542f21, 0x1f52e6d2, 0x068b22d0, 0x069d9532, 0x1f4f06a6, 

+	0x1f4db983, 0x06a3bad0, 0x06b62a22, 0x1f49cadc, 0x1f4878e5, 0x06bc4eb9, 0x06cebaee, 0x1f447bc4, 

+	0x1f4324fb, 0x06d4de79, 0x06e74786, 0x1f3f1963, 0x1f3dbdc8, 0x06ed6a03, 0x06ffcfdd, 0x1f39a3bc, 

+	0x1f384350, 0x0705f147, 0x071853e3, 0x1f341ad2, 0x1f32b595, 0x071e7436, 0x0730d388, 0x1f2e7ea9, 

+	0x1f2d149d, 0x0736f2c0, 0x07494ebd, 0x1f28cf43, 0x1f276069, 0x074f6cd7, 0x0761c574, 0x1f230ca5, 

+	0x1f2198fd, 0x0767e26c, 0x077a379d, 0x1f1d36d2, 0x1f1bbe5d, 0x07805370, 0x0792a52a, 0x1f174dce, 

+	0x1f15d08d, 0x0798bfd3, 0x07ab0e0a, 0x1f11519c, 0x1f0fcf91, 0x07b12786, 0x07c37230, 0x1f0b4240, 

+	0x1f09bb6b, 0x07c98a7a, 0x07dbd18c, 0x1f051fbe, 0x1f03941f, 0x07e1e8a1, 0x07f42c0e, 0x1efeea19, 

+	0x1efd59b3, 0x07fa41eb, 0x080c81a9, 0x1ef8a155, 0x1ef70c28, 0x0812964a, 0x0824d24d, 0x1ef24577, 

+	0x1ef0ab84, 0x082ae5ad, 0x083d1dea, 0x1eebd682, 0x1eea37ca, 0x08433007, 0x08556473, 0x1ee5547a, 

+	0x1ee3b0fe, 0x085b7548, 0x086da5d8, 0x1edebf64, 0x1edd1724, 0x0873b562, 0x0885e209, 0x1ed81742, 

+	0x1ed66a41, 0x088bf044, 0x089e18f9, 0x1ed15c1a, 0x1ecfaa57, 0x08a425e1, 0x08b64a98, 0x1eca8def, 

+	0x1ec8d76c, 0x08bc562a, 0x08ce76d8, 0x1ec3acc6, 0x1ec1f184, 0x08d4810f, 0x08e69da8, 0x1ebcb8a3, 

+	0x1ebaf8a3, 0x08eca681, 0x08febefb, 0x1eb5b18a, 0x1eb3eccd, 0x0904c673, 0x0916dac2, 0x1eae977f, 

+	0x1eacce07, 0x091ce0d4, 0x092ef0ed, 0x1ea76a87, 0x1ea59c55, 0x0934f596, 0x0947016e, 0x1ea02aa7, 

+	0x1e9e57bb, 0x094d04aa, 0x095f0c36, 0x1e98d7e2, 0x1e97003e, 0x09650e01, 0x09771136, 0x1e91723e, 

+	0x1e8f95e3, 0x097d118d, 0x098f1060, 0x1e89f9bf, 0x1e8818ad, 0x09950f3f, 0x09a709a4, 0x1e826e69, 

+	0x1e8088a2, 0x09ad0707, 0x09befcf4, 0x1e7ad041, 0x1e78e5c7, 0x09c4f8d8, 0x09d6ea40, 0x1e731f4c, 

+	0x1e71301f, 0x09dce4a1, 0x09eed17b, 0x1e6b5b8f, 0x1e6967b1, 0x09f4ca56, 0x0a06b296, 0x1e63850e, 

+	0x1e618c80, 0x0a0ca9e6, 0x0a1e8d81, 0x1e5b9bce, 0x1e599e91, 0x0a248343, 0x0a36622e, 0x1e539fd4, 

+	0x1e519dea, 0x0a3c565e, 0x0a4e308f, 0x1e4b9126, 0x1e498a8e, 0x0a542329, 0x0a65f894, 0x1e436fc7, 

+	0x1e416485, 0x0a6be995, 0x0a7dba2f, 0x1e3b3bbd, 0x1e392bd1, 0x0a83a993, 0x0a957551, 0x1e32f50e, 

+	0x1e30e079, 0x0a9b6315, 0x0aad29ec, 0x1e2a9bbd, 0x1e288281, 0x0ab3160c, 0x0ac4d7f1, 0x1e222fd1, 

+	0x1e2011ee, 0x0acac26a, 0x0adc7f52, 0x1e19b14f, 0x1e178ec7, 0x0ae2681f, 0x0af41fff, 0x1e11203b, 

+	0x1e0ef910, 0x0afa071d, 0x0b0bb9eb, 0x1e087c9b, 0x1e0650ce, 0x0b119f56, 0x0b234d07, 0x1dffc674, 

+	0x1dfd9606, 0x0b2930bb, 0x0b3ad943, 0x1df6fdcc, 0x1df4c8bf, 0x0b40bb3e, 0x0b525e92, 0x1dee22a9, 

+	0x1debe8fd, 0x0b583ecf, 0x0b69dce6, 0x1de5350f, 0x1de2f6c6, 0x0b6fbb62, 0x0b81542f, 0x1ddc3504, 

+	0x1dd9f220, 0x0b8730e6, 0x0b98c45f, 0x1dd3228e, 0x1dd0db10, 0x0b9e9f4d, 0x0bb02d68, 0x1dc9fdb2, 

+	0x1dc7b19b, 0x0bb6068a, 0x0bc78f3b, 0x1dc0c676, 0x1dbe75c8, 0x0bcd668e, 0x0bdee9ca, 0x1db77cdf, 

+	0x1db5279c, 0x0be4bf4a, 0x0bf63d07, 0x1dae20f4, 0x1dabc71d, 0x0bfc10af, 0x0c0d88e2, 0x1da4b2ba, 

+	0x1da25450, 0x0c135ab0, 0x0c24cd4e, 0x1d9b3237, 0x1d98cf3b, 0x0c2a9d3e, 0x0c3c0a3d, 0x1d919f70, 

+	0x1d8f37e5, 0x0c41d84b, 0x0c533fa0, 0x1d87fa6d, 0x1d858e53, 0x0c590bc9, 0x0c6a6d68, 0x1d7e4332, 

+	0x1d7bd28b, 0x0c7037a8, 0x0c819388, 0x1d7479c5, 0x1d720493, 0x0c875bdb, 0x0c98b1f0, 0x1d6a9e2e, 

+	0x1d682472, 0x0c9e7854, 0x0cafc894, 0x1d60b070, 0x1d5e322c, 0x0cb58d04, 0x0cc6d764, 0x1d56b094, 

+	0x1d542dc9, 0x0ccc99de, 0x0cddde53, 0x1d4c9e9f, 0x1d4a174f, 0x0ce39ed2, 0x0cf4dd52, 0x1d427a97, 

+	0x1d3feec3, 0x0cfa9bd2, 0x0d0bd452, 0x1d384483, 0x1d35b42d, 0x0d1190d1, 0x0d22c347, 0x1d2dfc68, 

+	0x1d2b6791, 0x0d287dc1, 0x0d39aa21, 0x1d23a24e, 0x1d2108f8, 0x0d3f6292, 0x0d5088d3, 0x1d19363a, 

+	0x1d169867, 0x0d563f38, 0x0d675f4e, 0x1d0eb833, 0x1d0c15e4, 0x0d6d13a3, 0x0d7e2d85, 0x1d04283f, 

+	0x1d018176, 0x0d83dfc6, 0x0d94f369, 0x1cf98666, 0x1cf6db24, 0x0d9aa393, 0x0dabb0ec, 0x1ceed2ad, 

+	0x1cec22f4, 0x0db15efc, 0x0dc26600, 0x1ce40d1b, 0x1ce158ed, 0x0dc811f3, 0x0dd91298, 0x1cd935b7, 

+	0x1cd67d15, 0x0ddebc69, 0x0defb6a5, 0x1cce4c87, 0x1ccb8f74, 0x0df55e51, 0x0e065219, 0x1cc35192, 

+	0x1cc0900f, 0x0e0bf79c, 0x0e1ce4e6, 0x1cb844df, 0x1cb57eee, 0x0e22883e, 0x0e336eff, 0x1cad2675, 

+	0x1caa5c17, 0x0e391027, 0x0e49f055, 0x1ca1f65b, 0x1c9f2792, 0x0e4f8f4b, 0x0e6068db, 0x1c96b497, 

+	0x1c93e165, 0x0e66059a, 0x0e76d883, 0x1c8b6131, 0x1c888997, 0x0e7c7308, 0x0e8d3f3e, 0x1c7ffc2f, 

+	0x1c7d202f, 0x0e92d787, 0x0ea39d00, 0x1c748599, 0x1c71a535, 0x0ea93308, 0x0eb9f1ba, 0x1c68fd75, 

+	0x1c6618ae, 0x0ebf857d, 0x0ed03d5e, 0x1c5d63ca, 0x1c5a7aa4, 0x0ed5ceda, 0x0ee67fdf, 0x1c51b8a1, 

+	0x1c4ecb1c, 0x0eec0f10, 0x0efcb92f, 0x1c45fc00, 0x1c430a1d, 0x0f024612, 0x0f12e941, 0x1c3a2ded, 

+	0x1c3737b0, 0x0f1873d2, 0x0f291006, 0x1c2e4e72, 0x1c2b53db, 0x0f2e9842, 0x0f3f2d71, 0x1c225d94, 

+	0x1c1f5ea6, 0x0f44b354, 0x0f554175, 0x1c165b5b, 0x1c135818, 0x0f5ac4fc, 0x0f6b4c03, 0x1c0a47cf, 

+	0x1c074038, 0x0f70cd2a, 0x0f814d0e, 0x1bfe22f8, 0x1bfb170f, 0x0f86cbd3, 0x0f974489, 0x1bf1ecdb, 

+	0x1beedca2, 0x0f9cc0e7, 0x0fad3265, 0x1be5a582, 0x1be290fb, 0x0fb2ac5a, 0x0fc31697, 0x1bd94cf4, 

+	0x1bd63421, 0x0fc88e1e, 0x0fd8f10f, 0x1bcce337, 0x1bc9c61a, 0x0fde6626, 0x0feec1c0, 0x1bc06855, 

+	0x1bbd46f0, 0x0ff43464, 0x1004889e, 0x1bb3dc55, 0x1bb0b6a9, 0x1009f8cb, 0x101a459a, 0x1ba73f3d, 

+	0x1ba4154d, 0x101fb34d, 0x102ff8a8, 0x1b9a9117, 0x1b9762e4, 0x103563dc, 0x1045a1b9, 0x1b8dd1ea, 

+	0x1b8a9f77, 0x104b0a6c, 0x105b40c1, 0x1b8101be, 0x1b7dcb0c, 0x1060a6ef, 0x1070d5b1, 0x1b74209b, 

+	0x1b70e5ac, 0x10763958, 0x1086607e, 0x1b672e88, 0x1b63ef5f, 0x108bc19a, 0x109be119, 0x1b5a2b8e, 

+	0x1b56e82c, 0x10a13fa6, 0x10b15775, 0x1b4d17b4, 0x1b49d01c, 0x10b6b371, 0x10c6c385, 0x1b3ff304, 

+	0x1b3ca737, 0x10cc1cec, 0x10dc253c, 0x1b32bd84, 0x1b2f6d85, 0x10e17c0b, 0x10f17c8d, 0x1b25773d, 

+	0x1b22230e, 0x10f6d0c0, 0x1106c96a, 0x1b182038, 0x1b14c7da, 0x110c1afe, 0x111c0bc6, 0x1b0ab87c, 

+	0x1b075bf1, 0x11215ab8, 0x11314395, 0x1afd4012, 0x1af9df5d, 0x11368fe1, 0x114670c8, 0x1aefb702, 

+	0x1aec5225, 0x114bba6b, 0x115b9354, 0x1ae21d54, 0x1adeb451, 0x1160da4b, 0x1170ab2a, 0x1ad47311, 

+	0x1ad105e9, 0x1175ef72, 0x1185b83f, 0x1ac6b841, 0x1ac346f8, 0x118af9d4, 0x119aba84, 0x1ab8ecec, 

+	0x1ab57784, 0x119ff964, 0x11afb1ee, 0x1aab111c, 0x1aa79796, 0x11b4ee14, 0x11c49e6f, 0x1a9d24d9, 

+	0x1a99a737, 0x11c9d7d9, 0x11d97ff9, 0x1a8f282b, 0x1a8ba670, 0x11deb6a4, 0x11ee5682, 0x1a811b1b, 

+	0x1a7d9549, 0x11f38a6a, 0x120321fa, 0x1a72fdb2, 0x1a6f73ca, 0x1208531c, 0x1217e256, 0x1a64cff8, 

+	0x1a6141fd, 0x121d10af, 0x122c9789, 0x1a5691f5, 0x1a52ffeb, 0x1231c316, 0x12414186, 0x1a4843b4, 

+	0x1a44ad9b, 0x12466a44, 0x1255e041, 0x1a39e53d, 0x1a364b17, 0x125b062b, 0x126a73ac, 0x1a2b7698, 

+	0x1a27d868, 0x126f96c1, 0x127efbbb, 0x1a1cf7ce, 0x1a195597, 0x12841bf6, 0x12937861, 0x1a0e68e9, 

+	0x1a0ac2ac, 0x129895c0, 0x12a7e991, 0x19ffc9f1, 0x19fc1fb1, 0x12ad0412, 0x12bc4f40, 0x19f11af0, 

+	0x19ed6caf, 0x12c166de, 0x12d0a960, 0x19e25bee, 0x19dea9ae, 0x12d5be18, 0x12e4f7e5, 0x19d38cf4, 

+	0x19cfd6b8, 0x12ea09b4, 0x12f93ac2, 0x19c4ae0c, 0x19c0f3d6, 0x12fe49a6, 0x130d71eb, 0x19b5bf3f, 

+	0x19b20111, 0x13127de0, 0x13219d53, 0x19a6c096, 0x19a2fe73, 0x1326a656, 0x1335bcef, 0x1997b21b, 

+	0x1993ec04, 0x133ac2fc, 0x1349d0b0, 0x198893d6, 0x1984c9ce, 0x134ed3c5, 0x135dd88c, 0x197965d0, 

+	0x197597da, 0x1362d8a6, 0x1371d476, 0x196a2815, 0x19665632, 0x1376d191, 0x1385c461, 0x195adaab, 

+	0x195704df, 0x138abe7b, 0x1399a841, 0x194b7d9e, 0x1947a3eb, 0x139e9f56, 0x13ad800a, 0x193c10f7, 

+	0x1938335e, 0x13b27417, 0x13c14bb0, 0x192c94bf, 0x1928b343, 0x13c63cb2, 0x13d50b26, 0x191d08ff, 

+	0x191923a3, 0x13d9f91b, 0x13e8be60, 0x190d6dc1, 0x19098488, 0x13eda944, 0x13fc6553, 0x18fdc310, 

+	0x18f9d5fa, 0x14014d23, 0x140ffff1, 0x18ee08f4, 0x18ea1805, 0x1414e4aa, 0x14238e2f, 0x18de3f77, 

+	0x18da4ab2, 0x14286fce, 0x14371001, 0x18ce66a3, 0x18ca6e0a, 0x143bee83, 0x144a855b, 0x18be7e82, 

+	0x18ba8217, 0x144f60bd, 0x145dee30, 0x18ae871e, 0x18aa86e3, 0x1462c670, 0x14714a76, 0x189e8080, 

+	0x189a7c78, 0x14761f8f, 0x14849a1f, 0x188e6ab2, 0x188a62e0, 0x14896c0f, 0x1497dd20, 0x187e45be, 

+	0x187a3a25, 0x149cabe4, 0x14ab136d, 0x186e11af, 0x186a0250, 0x14afdf03, 0x14be3cfa, 0x185dce8e, 

+	0x1859bb6c, 0x14c3055e, 0x14d159bc, 0x184d7c65, 0x18496583, 0x14d61eeb, 0x14e469a6, 0x183d1b3e, 

+	0x1839009e, 0x14e92b9e, 0x14f76cad, 0x182cab24, 0x18288cc8, 0x14fc2b6a, 0x150a62c6, 0x181c2c20, 

+	0x18180a0c, 0x150f1e45, 0x151d4be3, 0x180b9e3d, 0x18077873, 0x15220422, 0x153027fb, 0x17fb0185, 

+	0x17f6d807, 0x1534dcf6, 0x1542f700, 0x17ea5602, 0x17e628d3, 0x1547a8b5, 0x1555b8e8, 0x17d99bbe, 

+	0x17d56ae0, 0x155a6754, 0x15686da7, 0x17c8d2c4, 0x17c49e3b, 0x156d18c7, 0x157b1532, 0x17b7fb1f, 

+	0x17b3c2ec, 0x157fbd03, 0x158daf7c, 0x17a714d7, 0x17a2d8fe, 0x159253fb, 0x15a03c7a, 0x17961ff9, 

+	0x1791e07b, 0x15a4dda5, 0x15b2bc22, 0x17851c8e, 0x1780d96f, 0x15b759f5, 0x15c52e67, 0x17740aa1, 

+	0x176fc3e3, 0x15c9c8e0, 0x15d7933f, 0x1762ea3d, 0x175e9fe2, 0x15dc2a5a, 0x15e9ea9d, 0x1751bb6b, 

+	0x174d6d77, 0x15ee7e58, 0x15fc3477, 0x17407e37, 0x173c2cac, 0x1600c4cf, 0x160e70c1, 0x172f32ab, 

+	0x172add8c, 0x1612fdb3, 0x16209f70, 0x171dd8d2, 0x17198021, 0x162528fa, 0x1632c078, 0x170c70b7, 

+	0x17081477, 0x16374697, 0x1644d3d0, 0x16fafa64, 0x16f69a97, 0x16495680, 0x1656d96a, 0x16e975e4, 

+	0x16e5128e, 0x165b58aa, 0x1668d13e, 0x16d7e341, 0x16d37c65, 0x166d4d0a, 0x167abb3e, 0x16c64288, 

+	0x16c1d827, 0x167f3394, 0x168c9760, 0x16b493c2, 0x16b025e0, 0x16910c3d, 0x169e659a, 0x16a2d6fb

+};

+

+const int twidTab512[8*6 + 32*6 + 128*6] = {

+	0x20000000, 0x00000000, 0x1d906bcf, 0x0c3ef153, 0x16a09e66, 0x16a09e66, 0x0c3ef153, 0x1d906bcf, 
+	0x20000000, 0x00000000, 0x1f6297d0, 0x063e2e0f, 0x1d906bcf, 0x0c3ef153, 0x1a9b6629, 0x11c73b3a, 
+	0x20000000, 0x00000000, 0x1a9b6629, 0x11c73b3a, 0x0c3ef153, 0x1d906bcf, 0xf9c1d1f1, 0x1f6297d0, 
+	0x00000000, 0x20000000, 0xf3c10ead, 0x1d906bcf, 0xe95f619a, 0x16a09e66, 0xe26f9431, 0x0c3ef153, 
+	0x16a09e66, 0x16a09e66, 0x11c73b3a, 0x1a9b6629, 0x0c3ef153, 0x1d906bcf, 0x063e2e0f, 0x1f6297d0, 
+	0xe95f619a, 0x16a09e66, 0xe09d6830, 0x063e2e0f, 0xe26f9431, 0xf3c10ead, 0xee38c4c6, 0xe56499d7, 
+
+	0x20000000, 0x00000000, 0x1fd88da4, 0x0322f4d8, 0x1f6297d0, 0x063e2e0f, 0x1e9f4157, 0x094a0317, 
+	0x20000000, 0x00000000, 0x1ff621e3, 0x0191f65f, 0x1fd88da4, 0x0322f4d8, 0x1fa7557f, 0x04b2041c, 
+	0x20000000, 0x00000000, 0x1fa7557f, 0x04b2041c, 0x1e9f4157, 0x094a0317, 0x1ced7af4, 0x0dae8805, 
+	0x1d906bcf, 0x0c3ef153, 0x1c38b2f2, 0x0f15ae9c, 0x1a9b6629, 0x11c73b3a, 0x18bc806b, 0x144cf325, 
+	0x1f6297d0, 0x063e2e0f, 0x1f0a7efc, 0x07c67e5f, 0x1e9f4157, 0x094a0317, 0x1e212105, 0x0ac7cd3b, 
+	0x1a9b6629, 0x11c73b3a, 0x17b5df22, 0x157d6935, 0x144cf325, 0x18bc806b, 0x10738799, 0x1b728345, 
+	0x16a09e66, 0x16a09e66, 0x144cf325, 0x18bc806b, 0x11c73b3a, 0x1a9b6629, 0x0f15ae9c, 0x1c38b2f2, 
+	0x1d906bcf, 0x0c3ef153, 0x1ced7af4, 0x0dae8805, 0x1c38b2f2, 0x0f15ae9c, 0x1b728345, 0x10738799, 
+	0x0c3ef153, 0x1d906bcf, 0x07c67e5f, 0x1f0a7efc, 0x0322f4d8, 0x1fd88da4, 0xfe6e09a1, 0x1ff621e3, 
+	0x0c3ef153, 0x1d906bcf, 0x094a0317, 0x1e9f4157, 0x063e2e0f, 0x1f6297d0, 0x0322f4d8, 0x1fd88da4, 
+	0x1a9b6629, 0x11c73b3a, 0x19b3e048, 0x130ff7fd, 0x18bc806b, 0x144cf325, 0x17b5df22, 0x157d6935, 
+	0xf9c1d1f1, 0x1f6297d0, 0xf53832c5, 0x1e212105, 0xf0ea5164, 0x1c38b2f2, 0xecf00803, 0x19b3e048, 
+	0x00000000, 0x20000000, 0xfcdd0b28, 0x1fd88da4, 0xf9c1d1f1, 0x1f6297d0, 0xf6b5fce9, 0x1e9f4157, 
+	0x16a09e66, 0x16a09e66, 0x157d6935, 0x17b5df22, 0x144cf325, 0x18bc806b, 0x130ff7fd, 0x19b3e048, 
+	0xe95f619a, 0x16a09e66, 0xe64c1fb8, 0x130ff7fd, 0xe3c74d0e, 0x0f15ae9c, 0xe1dedefb, 0x0ac7cd3b, 
+	0xf3c10ead, 0x1d906bcf, 0xf0ea5164, 0x1c38b2f2, 0xee38c4c6, 0x1a9b6629, 0xebb30cdb, 0x18bc806b, 
+	0x11c73b3a, 0x1a9b6629, 0x10738799, 0x1b728345, 0x0f15ae9c, 0x1c38b2f2, 0x0dae8805, 0x1ced7af4, 
+	0xe09d6830, 0x063e2e0f, 0xe009de1d, 0x0191f65f, 0xe027725c, 0xfcdd0b28, 0xe0f58104, 0xf83981a1, 
+	0xe95f619a, 0x16a09e66, 0xe7437f95, 0x144cf325, 0xe56499d7, 0x11c73b3a, 0xe3c74d0e, 0x0f15ae9c, 
+	0x0c3ef153, 0x1d906bcf, 0x0ac7cd3b, 0x1e212105, 0x094a0317, 0x1e9f4157, 0x07c67e5f, 0x1f0a7efc, 
+	0xe26f9431, 0xf3c10ead, 0xe48d7cbb, 0xef8c7867, 0xe7437f95, 0xebb30cdb, 0xea8296cb, 0xe84a20de, 
+	0xe26f9431, 0x0c3ef153, 0xe160bea9, 0x094a0317, 0xe09d6830, 0x063e2e0f, 0xe027725c, 0x0322f4d8, 
+	0x063e2e0f, 0x1f6297d0, 0x04b2041c, 0x1fa7557f, 0x0322f4d8, 0x1fd88da4, 0x0191f65f, 0x1ff621e3, 
+	0xee38c4c6, 0xe56499d7, 0xf25177fb, 0xe312850c, 0xf6b5fce9, 0xe160bea9, 0xfb4dfbe4, 0xe058aa81, 
+
+	0x20000000, 0x00000000, 0x1ffd8861, 0x00c90ab0, 0x1ff621e3, 0x0191f65f, 0x1fe9cdad, 0x025aa412, 
+	0x20000000, 0x00000000, 0x1fff6217, 0x00648748, 0x1ffd8861, 0x00c90ab0, 0x1ffa72f0, 0x012d8657, 
+	0x20000000, 0x00000000, 0x1ffa72f0, 0x012d8657, 0x1fe9cdad, 0x025aa412, 0x1fce15fd, 0x0386f0b9, 
+	0x1fd88da4, 0x0322f4d8, 0x1fc26471, 0x03eac9cb, 0x1fa7557f, 0x04b2041c, 0x1f8764fa, 0x05788511, 
+	0x1ff621e3, 0x0191f65f, 0x1ff09566, 0x01f656e8, 0x1fe9cdad, 0x025aa412, 0x1fe1cafd, 0x02beda01, 
+	0x1fa7557f, 0x04b2041c, 0x1f7599a4, 0x05db7678, 0x1f38f3ac, 0x0702e09b, 0x1ef178a4, 0x0827dc07, 
+	0x1f6297d0, 0x063e2e0f, 0x1f38f3ac, 0x0702e09b, 0x1f0a7efc, 0x07c67e5f, 0x1ed740e7, 0x0888e931, 
+	0x1fd88da4, 0x0322f4d8, 0x1fce15fd, 0x0386f0b9, 0x1fc26471, 0x03eac9cb, 0x1fb57972, 0x044e7c34, 
+	0x1e9f4157, 0x094a0317, 0x1e426a4b, 0x0a68f121, 0x1ddb13b7, 0x0b844298, 0x1d696174, 0x0c9b9532, 
+	0x1e9f4157, 0x094a0317, 0x1e6288ec, 0x0a09ae4a, 0x1e212105, 0x0ac7cd3b, 0x1ddb13b7, 0x0b844298, 
+	0x1fa7557f, 0x04b2041c, 0x1f97f925, 0x05155dac, 0x1f8764fa, 0x05788511, 0x1f7599a4, 0x05db7678, 
+	0x1ced7af4, 0x0dae8805, 0x1c678b35, 0x0ebcbbae, 0x1bd7c0ac, 0x0fc5d26e, 0x1b3e4d3f, 0x10c9704d, 
+	0x1d906bcf, 0x0c3ef153, 0x1d4134d1, 0x0cf7bca2, 0x1ced7af4, 0x0dae8805, 0x1c954b21, 0x0e63374d, 
+	0x1f6297d0, 0x063e2e0f, 0x1f4e603b, 0x06a0a809, 0x1f38f3ac, 0x0702e09b, 0x1f2252f7, 0x0764d3f9, 
+	0x1a9b6629, 0x11c73b3a, 0x19ef43ef, 0x12bedb26, 0x193a224a, 0x13affa29, 0x187c4010, 0x149a449c, 
+	0x1c38b2f2, 0x0f15ae9c, 0x1bd7c0ac, 0x0fc5d26e, 0x1b728345, 0x10738799, 0x1b090a58, 0x111eb354, 
+	0x1f0a7efc, 0x07c67e5f, 0x1ef178a4, 0x0827dc07, 0x1ed740e7, 0x0888e931, 0x1ebbd8c9, 0x08e9a220, 
+	0x17b5df22, 0x157d6935, 0x16e74455, 0x16591926, 0x1610b755, 0x172d0838, 0x15328293, 0x17f8ece3, 
+	0x1a9b6629, 0x11c73b3a, 0x1a29a7a0, 0x126d054d, 0x19b3e048, 0x130ff7fd, 0x193a224a, 0x13affa29, 
+	0x1e9f4157, 0x094a0317, 0x1e817bab, 0x09aa0861, 0x1e6288ec, 0x0a09ae4a, 0x1e426a4b, 0x0a68f121, 
+	0x144cf325, 0x18bc806b, 0x136058b1, 0x19777ef5, 0x126d054d, 0x1a29a7a0, 0x11734d64, 0x1ad2bc9e, 
+	0x18bc806b, 0x144cf325, 0x183b0e0c, 0x14e6cabc, 0x17b5df22, 0x157d6935, 0x172d0838, 0x1610b755, 
+	0x1e212105, 0x0ac7cd3b, 0x1dfeae62, 0x0b263eef, 0x1ddb13b7, 0x0b844298, 0x1db65262, 0x0be1d499, 
+	0x10738799, 0x1b728345, 0x0f6e0ca9, 0x1c08c426, 0x0e63374d, 0x1c954b21, 0x0d536416, 0x1d17e774, 
+	0x16a09e66, 0x16a09e66, 0x1610b755, 0x172d0838, 0x157d6935, 0x17b5df22, 0x14e6cabc, 0x183b0e0c, 
+	0x1d906bcf, 0x0c3ef153, 0x1d696174, 0x0c9b9532, 0x1d4134d1, 0x0cf7bca2, 0x1d17e774, 0x0d536416, 
+	0x0c3ef153, 0x1d906bcf, 0x0b263eef, 0x1dfeae62, 0x0a09ae4a, 0x1e6288ec, 0x08e9a220, 0x1ebbd8c9, 
+	0x144cf325, 0x18bc806b, 0x13affa29, 0x193a224a, 0x130ff7fd, 0x19b3e048, 0x126d054d, 0x1a29a7a0, 
+	0x1ced7af4, 0x0dae8805, 0x1cc1f0f4, 0x0e0924ec, 0x1c954b21, 0x0e63374d, 0x1c678b35, 0x0ebcbbae, 
+	0x07c67e5f, 0x1f0a7efc, 0x06a0a809, 0x1f4e603b, 0x05788511, 0x1f8764fa, 0x044e7c34, 0x1fb57972, 
+	0x11c73b3a, 0x1a9b6629, 0x111eb354, 0x1b090a58, 0x10738799, 0x1b728345, 0x0fc5d26e, 0x1bd7c0ac, 
+	0x1c38b2f2, 0x0f15ae9c, 0x1c08c426, 0x0f6e0ca9, 0x1bd7c0ac, 0x0fc5d26e, 0x1ba5aa67, 0x101cfc87, 
+	0x0322f4d8, 0x1fd88da4, 0x01f656e8, 0x1ff09566, 0x00c90ab0, 0x1ffd8861, 0xff9b78b8, 0x1fff6217, 
+	0x0f15ae9c, 0x1c38b2f2, 0x0e63374d, 0x1c954b21, 0x0dae8805, 0x1ced7af4, 0x0cf7bca2, 0x1d4134d1, 
+	0x1b728345, 0x10738799, 0x1b3e4d3f, 0x10c9704d, 0x1b090a58, 0x111eb354, 0x1ad2bc9e, 0x11734d64, 
+	0xfe6e09a1, 0x1ff621e3, 0xfd4125ff, 0x1fe1cafd, 0xfc153635, 0x1fc26471, 0xfaeaa254, 0x1f97f925, 
+	0x0c3ef153, 0x1d906bcf, 0x0b844298, 0x1ddb13b7, 0x0ac7cd3b, 0x1e212105, 0x0a09ae4a, 0x1e6288ec, 
+	0x1a9b6629, 0x11c73b3a, 0x1a63091b, 0x121a7999, 0x1a29a7a0, 0x126d054d, 0x19ef43ef, 0x12bedb26, 
+	0xf9c1d1f1, 0x1f6297d0, 0xf89b2c07, 0x1f2252f7, 0xf77716cf, 0x1ed740e7, 0xf655f79f, 0x1e817bab, 
+	0x094a0317, 0x1e9f4157, 0x0888e931, 0x1ed740e7, 0x07c67e5f, 0x1f0a7efc, 0x0702e09b, 0x1f38f3ac, 
+	0x19b3e048, 0x130ff7fd, 0x19777ef5, 0x136058b1, 0x193a224a, 0x13affa29, 0x18fbcca4, 0x13fed953, 
+	0xf53832c5, 0x1e212105, 0xf41e2b67, 0x1db65262, 0xf308435e, 0x1d4134d1, 0xf1f6db14, 0x1cc1f0f4, 
+	0x063e2e0f, 0x1f6297d0, 0x05788511, 0x1f8764fa, 0x04b2041c, 0x1fa7557f, 0x03eac9cb, 0x1fc26471, 
+	0x18bc806b, 0x144cf325, 0x187c4010, 0x149a449c, 0x183b0e0c, 0x14e6cabc, 0x17f8ece3, 0x15328293, 
+	0xf0ea5164, 0x1c38b2f2, 0xefe30379, 0x1ba5aa67, 0xeee14cac, 0x1b090a58, 0xede58667, 0x1a63091b, 
+	0x0322f4d8, 0x1fd88da4, 0x025aa412, 0x1fe9cdad, 0x0191f65f, 0x1ff621e3, 0x00c90ab0, 0x1ffd8861, 
+	0x17b5df22, 0x157d6935, 0x1771e75f, 0x15c77bbe, 0x172d0838, 0x1610b755, 0x16e74455, 0x16591926, 
+	0xecf00803, 0x19b3e048, 0xec0126ad, 0x18fbcca4, 0xeb193544, 0x183b0e0c, 0xea388442, 0x1771e75f, 
+	0x00000000, 0x20000000, 0xff36f550, 0x1ffd8861, 0xfe6e09a1, 0x1ff621e3, 0xfda55bee, 0x1fe9cdad, 
+	0x16a09e66, 0x16a09e66, 0x16591926, 0x16e74455, 0x1610b755, 0x172d0838, 0x15c77bbe, 0x1771e75f, 
+	0xe95f619a, 0x16a09e66, 0xe88e18a1, 0x15c77bbe, 0xe7c4f1f4, 0x14e6cabc, 0xe704335c, 0x13fed953, 
+	0xfcdd0b28, 0x1fd88da4, 0xfc153635, 0x1fc26471, 0xfb4dfbe4, 0x1fa7557f, 0xfa877aef, 0x1f8764fa, 
+	0x157d6935, 0x17b5df22, 0x15328293, 0x17f8ece3, 0x14e6cabc, 0x183b0e0c, 0x149a449c, 0x187c4010, 
+	0xe64c1fb8, 0x130ff7fd, 0xe59cf6e5, 0x121a7999, 0xe4f6f5a8, 0x111eb354, 0xe45a5599, 0x101cfc87, 
+	0xf9c1d1f1, 0x1f6297d0, 0xf8fd1f65, 0x1f38f3ac, 0xf83981a1, 0x1f0a7efc, 0xf77716cf, 0x1ed740e7, 
+	0x144cf325, 0x18bc806b, 0x13fed953, 0x18fbcca4, 0x13affa29, 0x193a224a, 0x136058b1, 0x19777ef5, 
+	0xe3c74d0e, 0x0f15ae9c, 0xe33e0f0c, 0x0e0924ec, 0xe2becb2f, 0x0cf7bca2, 0xe249ad9e, 0x0be1d499, 
+	0xf6b5fce9, 0x1e9f4157, 0xf5f651b6, 0x1e6288ec, 0xf53832c5, 0x1e212105, 0xf47bbd68, 0x1ddb13b7, 
+	0x130ff7fd, 0x19b3e048, 0x12bedb26, 0x19ef43ef, 0x126d054d, 0x1a29a7a0, 0x121a7999, 0x1a63091b, 
+	0xe1dedefb, 0x0ac7cd3b, 0xe17e8455, 0x09aa0861, 0xe128bf19, 0x0888e931, 0xe0ddad09, 0x0764d3f9, 
+	0xf3c10ead, 0x1d906bcf, 0xf308435e, 0x1d4134d1, 0xf25177fb, 0x1ced7af4, 0xf19cc8b3, 0x1c954b21, 
+	0x11c73b3a, 0x1a9b6629, 0x11734d64, 0x1ad2bc9e, 0x111eb354, 0x1b090a58, 0x10c9704d, 0x1b3e4d3f, 
+	0xe09d6830, 0x063e2e0f, 0xe06806db, 0x05155dac, 0xe03d9b8f, 0x03eac9cb, 0xe01e3503, 0x02beda01, 
+	0xf0ea5164, 0x1c38b2f2, 0xf03a2d92, 0x1bd7c0ac, 0xef8c7867, 0x1b728345, 0xeee14cac, 0x1b090a58, 
+	0x10738799, 0x1b728345, 0x101cfc87, 0x1ba5aa67, 0x0fc5d26e, 0x1bd7c0ac, 0x0f6e0ca9, 0x1c08c426, 
+	0xe009de1d, 0x0191f65f, 0xe0009de9, 0x00648748, 0xe002779f, 0xff36f550, 0xe00f6a9a, 0xfe09a918, 
+	0xee38c4c6, 0x1a9b6629, 0xed92fab3, 0x1a29a7a0, 0xecf00803, 0x19b3e048, 0xec5005d7, 0x193a224a, 
+	0x0f15ae9c, 0x1c38b2f2, 0x0ebcbbae, 0x1c678b35, 0x0e63374d, 0x1c954b21, 0x0e0924ec, 0x1cc1f0f4, 
+	0xe027725c, 0xfcdd0b28, 0xe04a868e, 0xfbb183cc, 0xe0789b06, 0xfa877aef, 0xe0b19fc5, 0xf95f57f7, 
+	0xebb30cdb, 0x18bc806b, 0xeb193544, 0x183b0e0c, 0xea8296cb, 0x17b5df22, 0xe9ef48ab, 0x172d0838, 
+	0x0dae8805, 0x1ced7af4, 0x0d536416, 0x1d17e774, 0x0cf7bca2, 0x1d4134d1, 0x0c9b9532, 0x1d696174, 
+	0xe0f58104, 0xf83981a1, 0xe1442737, 0xf7165de0, 0xe19d7714, 0xf5f651b6, 0xe201519e, 0xf4d9c111, 
+	0xe95f619a, 0x16a09e66, 0xe8d2f7c8, 0x1610b755, 0xe84a20de, 0x157d6935, 0xe7c4f1f4, 0x14e6cabc, 
+	0x0c3ef153, 0x1d906bcf, 0x0be1d499, 0x1db65262, 0x0b844298, 0x1ddb13b7, 0x0b263eef, 0x1dfeae62, 
+	0xe26f9431, 0xf3c10ead, 0xe2e8188c, 0xf2ac9bea, 0xe36ab4df, 0xf19cc8b3, 0xe3f73bda, 0xf091f357, 
+	0xe7437f95, 0x144cf325, 0xe6c5ddb6, 0x13affa29, 0xe64c1fb8, 0x130ff7fd, 0xe5d65860, 0x126d054d, 
+	0x0ac7cd3b, 0x1e212105, 0x0a68f121, 0x1e426a4b, 0x0a09ae4a, 0x1e6288ec, 0x09aa0861, 0x1e817bab, 
+	0xe48d7cbb, 0xef8c7867, 0xe52d4362, 0xee8cb29c, 0xe5d65860, 0xed92fab3, 0xe688810b, 0xec9fa74f, 
+	0xe56499d7, 0x11c73b3a, 0xe4f6f5a8, 0x111eb354, 0xe48d7cbb, 0x10738799, 0xe4283f54, 0x0fc5d26e, 
+	0x094a0317, 0x1e9f4157, 0x08e9a220, 0x1ebbd8c9, 0x0888e931, 0x1ed740e7, 0x0827dc07, 0x1ef178a4, 
+	0xe7437f95, 0xebb30cdb, 0xe807131d, 0xeacd7d6d, 0xe8d2f7c8, 0xe9ef48ab, 0xe9a6e6da, 0xe918bbab, 
+	0xe3c74d0e, 0x0f15ae9c, 0xe36ab4df, 0x0e63374d, 0xe312850c, 0x0dae8805, 0xe2becb2f, 0x0cf7bca2, 
+	0x07c67e5f, 0x1f0a7efc, 0x0764d3f9, 0x1f2252f7, 0x0702e09b, 0x1f38f3ac, 0x06a0a809, 0x1f4e603b, 
+	0xea8296cb, 0xe84a20de, 0xeb65bb64, 0xe783bff0, 0xec5005d7, 0xe6c5ddb6, 0xed4124da, 0xe610bc11, 
+	0xe26f9431, 0x0c3ef153, 0xe224ec49, 0x0b844298, 0xe1dedefb, 0x0ac7cd3b, 0xe19d7714, 0x0a09ae4a, 
+	0x063e2e0f, 0x1f6297d0, 0x05db7678, 0x1f7599a4, 0x05788511, 0x1f8764fa, 0x05155dac, 0x1f97f925, 
+	0xee38c4c6, 0xe56499d7, 0xef368fb3, 0xe4c1b2c1, 0xf03a2d92, 0xe4283f54, 0xf1434452, 0xe39874cb, 
+	0xe160bea9, 0x094a0317, 0xe128bf19, 0x0888e931, 0xe0f58104, 0x07c67e5f, 0xe0c70c54, 0x0702e09b, 
+	0x04b2041c, 0x1fa7557f, 0x044e7c34, 0x1fb57972, 0x03eac9cb, 0x1fc26471, 0x0386f0b9, 0x1fce15fd, 
+	0xf25177fb, 0xe312850c, 0xf3646ace, 0xe2969e8c, 0xf47bbd68, 0xe224ec49, 0xf5970edf, 0xe1bd95b5, 
+	0xe09d6830, 0x063e2e0f, 0xe0789b06, 0x05788511, 0xe058aa81, 0x04b2041c, 0xe03d9b8f, 0x03eac9cb, 
+	0x0322f4d8, 0x1fd88da4, 0x02beda01, 0x1fe1cafd, 0x025aa412, 0x1fe9cdad, 0x01f656e8, 0x1ff09566, 
+	0xf6b5fce9, 0xe160bea9, 0xf7d823f9, 0xe10e875c, 0xf8fd1f65, 0xe0c70c54, 0xfa248988, 0xe08a665c, 
+	0xe027725c, 0x0322f4d8, 0xe0163253, 0x025aa412, 0xe009de1d, 0x0191f65f, 0xe002779f, 0x00c90ab0, 
+	0x0191f65f, 0x1ff621e3, 0x012d8657, 0x1ffa72f0, 0x00c90ab0, 0x1ffd8861, 0x00648748, 0x1fff6217, 
+	0xfb4dfbe4, 0xe058aa81, 0xfc790f47, 0xe031ea03, 0xfda55bee, 0xe0163253, 0xfed279a9, 0xe0058d10

+};

+

+const int twidTab64[4*6 + 16*6] = {

+	0x20000000, 0x00000000, 0x16a09e66, 0x16a09e66, 0x00000000, 0x20000000, 0xe95f619a, 0x16a09e66, 
+	0x20000000, 0x00000000, 0x1d906bcf, 0x0c3ef153, 0x16a09e66, 0x16a09e66, 0x0c3ef153, 0x1d906bcf, 
+	0x20000000, 0x00000000, 0x0c3ef153, 0x1d906bcf, 0xe95f619a, 0x16a09e66, 0xe26f9431, 0xf3c10ead, 
+
+	0x20000000, 0x00000000, 0x1f6297d0, 0x063e2e0f, 0x1d906bcf, 0x0c3ef153, 0x1a9b6629, 0x11c73b3a, 
+	0x20000000, 0x00000000, 0x1fd88da4, 0x0322f4d8, 0x1f6297d0, 0x063e2e0f, 0x1e9f4157, 0x094a0317, 
+	0x20000000, 0x00000000, 0x1e9f4157, 0x094a0317, 0x1a9b6629, 0x11c73b3a, 0x144cf325, 0x18bc806b, 
+	0x16a09e66, 0x16a09e66, 0x11c73b3a, 0x1a9b6629, 0x0c3ef153, 0x1d906bcf, 0x063e2e0f, 0x1f6297d0, 
+	0x1d906bcf, 0x0c3ef153, 0x1c38b2f2, 0x0f15ae9c, 0x1a9b6629, 0x11c73b3a, 0x18bc806b, 0x144cf325, 
+	0x0c3ef153, 0x1d906bcf, 0x0322f4d8, 0x1fd88da4, 0xf9c1d1f1, 0x1f6297d0, 0xf0ea5164, 0x1c38b2f2, 
+	0x00000000, 0x20000000, 0xf9c1d1f1, 0x1f6297d0, 0xf3c10ead, 0x1d906bcf, 0xee38c4c6, 0x1a9b6629, 
+	0x16a09e66, 0x16a09e66, 0x144cf325, 0x18bc806b, 0x11c73b3a, 0x1a9b6629, 0x0f15ae9c, 0x1c38b2f2, 
+	0xe95f619a, 0x16a09e66, 0xe3c74d0e, 0x0f15ae9c, 0xe09d6830, 0x063e2e0f, 0xe027725c, 0xfcdd0b28, 
+	0xe95f619a, 0x16a09e66, 0xe56499d7, 0x11c73b3a, 0xe26f9431, 0x0c3ef153, 0xe09d6830, 0x063e2e0f, 
+	0x0c3ef153, 0x1d906bcf, 0x094a0317, 0x1e9f4157, 0x063e2e0f, 0x1f6297d0, 0x0322f4d8, 0x1fd88da4, 
+	0xe26f9431, 0xf3c10ead, 0xe7437f95, 0xebb30cdb, 0xee38c4c6, 0xe56499d7, 0xf6b5fce9, 0xe160bea9

+};

+

+#else
+
+/* 

+ *  Q30 for 128 and 1024 

+ *

+ * for (i = 0; i < num/4; i++) {

+ *   angle = (i + 0.125) * M_PI / num;

+ *   x = cos(angle) * (1 << 30);

+ *   x = sin(angle) * (1 << 30);

+ * 

+ *   angle = (num/2 - 1 - i + 0.125) * M_PI / num;

+ *   x = cos(angle) * (1 << 30);

+ *   x = sin(angle) * (1 << 30);

+ * }

+ */

+const int cossintab[128 + 1024] = {

+	/* 128 */

+	0x3fffec43, 0x003243f1, 0x015fd4d2, 0x3ffc38d1, 0x3ff9c13a, 0x01c454f5, 0x02f1b755, 0x3feea776, 

+	0x3fe9b8a9, 0x03562038, 0x0483259d, 0x3fd73a4a, 0x3fcfd50b, 0x04e767c5, 0x0613e1c5, 0x3fb5f4ea, 

+	0x3fac1a5b, 0x0677edbb, 0x07a3adff, 0x3f8adc77, 0x3f7e8e1e, 0x08077457, 0x09324ca7, 0x3f55f796, 

+	0x3f473759, 0x0995bdfd, 0x0abf8043, 0x3f174e70, 0x3f061e95, 0x0b228d42, 0x0c4b0b94, 0x3eceeaad, 

+	0x3ebb4ddb, 0x0cada4f5, 0x0dd4b19a, 0x3e7cd778, 0x3e66d0b4, 0x0e36c82a, 0x0f5c35a3, 0x3e212179, 

+	0x3e08b42a, 0x0fbdba40, 0x10e15b4e, 0x3dbbd6d4, 0x3da106bd, 0x11423ef0, 0x1263e699, 0x3d4d0728, 

+	0x3d2fd86c, 0x12c41a4f, 0x13e39be9, 0x3cd4c38b, 0x3cb53aaa, 0x144310dd, 0x15604013, 0x3c531e88, 

+	0x3c314060, 0x15bee78c, 0x16d99864, 0x3bc82c1f, 0x3ba3fde7, 0x173763c9, 0x184f6aab, 0x3b3401bb, 

+	0x3b0d8909, 0x18ac4b87, 0x19c17d44, 0x3a96b636, 0x3a6df8f8, 0x1a1d6544, 0x1b2f971e, 0x39f061d2, 

+	0x39c5664f, 0x1b8a7815, 0x1c997fc4, 0x39411e33, 0x3913eb0e, 0x1cf34baf, 0x1dfeff67, 0x38890663, 

+	0x3859a292, 0x1e57a86d, 0x1f5fdee6, 0x37c836c2, 0x3796a996, 0x1fb7575c, 0x20bbe7d8, 0x36fecd0e, 

+	0x36cb1e2a, 0x21122240, 0x2212e492, 0x362ce855, 0x35f71fb1, 0x2267d3a0, 0x2364a02e, 0x3552a8f4, 

+	0x351acedd, 0x23b836ca, 0x24b0e699, 0x34703095, 0x34364da6, 0x250317df, 0x25f78497, 0x3385a222, 

+	0x3349bf48, 0x264843d9, 0x273847c8, 0x329321c7, 0x32554840, 0x27878893, 0x2872feb6, 0x3198d4ea, 

+	0x31590e3e, 0x28c0b4d2, 0x29a778db, 0x3096e223, 0x30553828, 0x29f3984c, 0x2ad586a3, 0x2f8d713a, 

+	0x2f49ee0f, 0x2b2003ac, 0x2bfcf97c, 0x2e7cab1c, 0x2e37592c, 0x2c45c8a0, 0x2d1da3d5, 0x2d64b9da, 

+	/* 1024 */

+	0x3fffffb1, 0x0006487f, 0x002bfb74, 0x3ffff0e3, 0x3fffe705, 0x00388c6e, 0x005e3f4c, 0x3fffba9b, 

+	0x3fffa6de, 0x006ad03b, 0x009082ea, 0x3fff5cd8, 0x3fff3f3c, 0x009d13c5, 0x00c2c62f, 0x3ffed79b, 

+	0x3ffeb021, 0x00cf56ef, 0x00f508fc, 0x3ffe2ae5, 0x3ffdf98c, 0x01019998, 0x01274b31, 0x3ffd56b5, 

+	0x3ffd1b7e, 0x0133dba3, 0x01598cb1, 0x3ffc5b0c, 0x3ffc15f7, 0x01661cf0, 0x018bcd5b, 0x3ffb37ec, 

+	0x3ffae8f9, 0x01985d60, 0x01be0d11, 0x3ff9ed53, 0x3ff99483, 0x01ca9cd4, 0x01f04bb4, 0x3ff87b44, 

+	0x3ff81896, 0x01fcdb2e, 0x02228924, 0x3ff6e1bf, 0x3ff67534, 0x022f184d, 0x0254c544, 0x3ff520c5, 

+	0x3ff4aa5d, 0x02615414, 0x0286fff3, 0x3ff33858, 0x3ff2b813, 0x02938e62, 0x02b93914, 0x3ff12878, 

+	0x3ff09e56, 0x02c5c71a, 0x02eb7086, 0x3feef126, 0x3fee5d28, 0x02f7fe1c, 0x031da62b, 0x3fec9265, 

+	0x3febf48b, 0x032a3349, 0x034fd9e5, 0x3fea0c35, 0x3fe96480, 0x035c6682, 0x03820b93, 0x3fe75e98, 

+	0x3fe6ad08, 0x038e97a9, 0x03b43b17, 0x3fe48990, 0x3fe3ce26, 0x03c0c69e, 0x03e66852, 0x3fe18d1f, 

+	0x3fe0c7da, 0x03f2f342, 0x04189326, 0x3fde6945, 0x3fdd9a27, 0x04251d77, 0x044abb73, 0x3fdb1e06, 

+	0x3fda450f, 0x0457451d, 0x047ce11a, 0x3fd7ab64, 0x3fd6c894, 0x04896a16, 0x04af03fc, 0x3fd4115f, 

+	0x3fd324b7, 0x04bb8c42, 0x04e123fa, 0x3fd04ffc, 0x3fcf597c, 0x04edab83, 0x051340f6, 0x3fcc673b, 

+	0x3fcb66e4, 0x051fc7b9, 0x05455ad1, 0x3fc8571f, 0x3fc74cf3, 0x0551e0c7, 0x0577716b, 0x3fc41fac, 

+	0x3fc30baa, 0x0583f68c, 0x05a984a6, 0x3fbfc0e3, 0x3fbea30c, 0x05b608eb, 0x05db9463, 0x3fbb3ac7, 

+	0x3fba131b, 0x05e817c3, 0x060da083, 0x3fb68d5b, 0x3fb55bdc, 0x061a22f7, 0x063fa8e7, 0x3fb1b8a2, 

+	0x3fb07d50, 0x064c2a67, 0x0671ad71, 0x3facbc9f, 0x3fab777b, 0x067e2df5, 0x06a3ae00, 0x3fa79954, 

+	0x3fa64a5f, 0x06b02d81, 0x06d5aa77, 0x3fa24ec6, 0x3fa0f600, 0x06e228ee, 0x0707a2b7, 0x3f9cdcf7, 

+	0x3f9b7a62, 0x0714201b, 0x073996a1, 0x3f9743eb, 0x3f95d787, 0x074612eb, 0x076b8616, 0x3f9183a5, 

+	0x3f900d72, 0x0778013d, 0x079d70f7, 0x3f8b9c28, 0x3f8a1c29, 0x07a9eaf5, 0x07cf5726, 0x3f858d79, 

+	0x3f8403ae, 0x07dbcff2, 0x08013883, 0x3f7f579b, 0x3f7dc405, 0x080db016, 0x083314f1, 0x3f78fa92, 

+	0x3f775d31, 0x083f8b43, 0x0864ec4f, 0x3f727661, 0x3f70cf38, 0x08716159, 0x0896be80, 0x3f6bcb0e, 

+	0x3f6a1a1c, 0x08a3323a, 0x08c88b65, 0x3f64f89b, 0x3f633de2, 0x08d4fdc6, 0x08fa52de, 0x3f5dff0e, 

+	0x3f5c3a8f, 0x0906c3e0, 0x092c14ce, 0x3f56de6a, 0x3f551026, 0x09388469, 0x095dd116, 0x3f4f96b4, 

+	0x3f4dbeac, 0x096a3f42, 0x098f8796, 0x3f4827f0, 0x3f464626, 0x099bf44c, 0x09c13831, 0x3f409223, 

+	0x3f3ea697, 0x09cda368, 0x09f2e2c7, 0x3f38d552, 0x3f36e006, 0x09ff4c78, 0x0a24873a, 0x3f30f181, 

+	0x3f2ef276, 0x0a30ef5e, 0x0a56256c, 0x3f28e6b6, 0x3f26ddec, 0x0a628bfa, 0x0a87bd3d, 0x3f20b4f5, 

+	0x3f1ea26e, 0x0a94222f, 0x0ab94e8f, 0x3f185c43, 0x3f164001, 0x0ac5b1dc, 0x0aead944, 0x3f0fdca5, 

+	0x3f0db6a9, 0x0af73ae5, 0x0b1c5d3d, 0x3f073621, 0x3f05066d, 0x0b28bd2a, 0x0b4dda5c, 0x3efe68bc, 

+	0x3efc2f50, 0x0b5a388d, 0x0b7f5081, 0x3ef5747b, 0x3ef3315a, 0x0b8bacf0, 0x0bb0bf8f, 0x3eec5965, 

+	0x3eea0c8e, 0x0bbd1a33, 0x0be22766, 0x3ee3177e, 0x3ee0c0f4, 0x0bee8038, 0x0c1387e9, 0x3ed9aecc, 

+	0x3ed74e91, 0x0c1fdee1, 0x0c44e0f9, 0x3ed01f55, 0x3ecdb56a, 0x0c513610, 0x0c763278, 0x3ec66920, 

+	0x3ec3f585, 0x0c8285a5, 0x0ca77c47, 0x3ebc8c31, 0x3eba0ee9, 0x0cb3cd84, 0x0cd8be47, 0x3eb2888f, 

+	0x3eb0019c, 0x0ce50d8c, 0x0d09f85b, 0x3ea85e41, 0x3ea5cda3, 0x0d1645a0, 0x0d3b2a64, 0x3e9e0d4c, 

+	0x3e9b7306, 0x0d4775a1, 0x0d6c5443, 0x3e9395b7, 0x3e90f1ca, 0x0d789d71, 0x0d9d75db, 0x3e88f788, 

+	0x3e8649f5, 0x0da9bcf2, 0x0dce8f0d, 0x3e7e32c6, 0x3e7b7b90, 0x0ddad406, 0x0dff9fba, 0x3e734778, 

+	0x3e70869f, 0x0e0be28e, 0x0e30a7c5, 0x3e6835a4, 0x3e656b2b, 0x0e3ce86b, 0x0e61a70f, 0x3e5cfd51, 

+	0x3e5a2939, 0x0e6de580, 0x0e929d7a, 0x3e519e86, 0x3e4ec0d1, 0x0e9ed9af, 0x0ec38ae8, 0x3e46194a, 

+	0x3e4331fa, 0x0ecfc4d9, 0x0ef46f3b, 0x3e3a6da4, 0x3e377cbb, 0x0f00a6df, 0x0f254a53, 0x3e2e9b9c, 

+	0x3e2ba11b, 0x0f317fa5, 0x0f561c15, 0x3e22a338, 0x3e1f9f21, 0x0f624f0c, 0x0f86e460, 0x3e168480, 

+	0x3e1376d5, 0x0f9314f5, 0x0fb7a317, 0x3e0a3f7b, 0x3e07283f, 0x0fc3d143, 0x0fe8581d, 0x3dfdd432, 

+	0x3dfab365, 0x0ff483d7, 0x10190352, 0x3df142ab, 0x3dee1851, 0x10252c94, 0x1049a49a, 0x3de48aef, 

+	0x3de15708, 0x1055cb5b, 0x107a3bd5, 0x3dd7ad05, 0x3dd46f94, 0x1086600e, 0x10aac8e6, 0x3dcaa8f5, 

+	0x3dc761fc, 0x10b6ea90, 0x10db4baf, 0x3dbd7ec7, 0x3dba2e48, 0x10e76ac3, 0x110bc413, 0x3db02e84, 

+	0x3dacd481, 0x1117e088, 0x113c31f3, 0x3da2b834, 0x3d9f54af, 0x11484bc2, 0x116c9531, 0x3d951bde, 

+	0x3d91aed9, 0x1178ac53, 0x119cedaf, 0x3d87598c, 0x3d83e309, 0x11a9021d, 0x11cd3b50, 0x3d797145, 

+	0x3d75f147, 0x11d94d02, 0x11fd7df6, 0x3d6b6313, 0x3d67d99b, 0x12098ce5, 0x122db583, 0x3d5d2efe, 

+	0x3d599c0e, 0x1239c1a7, 0x125de1da, 0x3d4ed50f, 0x3d4b38aa, 0x1269eb2b, 0x128e02dc, 0x3d40554e, 

+	0x3d3caf76, 0x129a0954, 0x12be186c, 0x3d31afc5, 0x3d2e007c, 0x12ca1c03, 0x12ee226c, 0x3d22e47c, 

+	0x3d1f2bc5, 0x12fa231b, 0x131e20c0, 0x3d13f37e, 0x3d10315a, 0x132a1e7e, 0x134e1348, 0x3d04dcd2, 

+	0x3d011145, 0x135a0e0e, 0x137df9e7, 0x3cf5a082, 0x3cf1cb8e, 0x1389f1af, 0x13add481, 0x3ce63e98, 

+	0x3ce2603f, 0x13b9c943, 0x13dda2f7, 0x3cd6b71e, 0x3cd2cf62, 0x13e994ab, 0x140d652c, 0x3cc70a1c, 

+	0x3cc318ff, 0x141953cb, 0x143d1b02, 0x3cb7379c, 0x3cb33d22, 0x14490685, 0x146cc45c, 0x3ca73fa9, 

+	0x3ca33bd3, 0x1478acbc, 0x149c611d, 0x3c97224c, 0x3c93151d, 0x14a84652, 0x14cbf127, 0x3c86df8e, 

+	0x3c82c909, 0x14d7d32a, 0x14fb745e, 0x3c76777b, 0x3c7257a2, 0x15075327, 0x152aeaa3, 0x3c65ea1c, 

+	0x3c61c0f1, 0x1536c62b, 0x155a53d9, 0x3c55377b, 0x3c510501, 0x15662c18, 0x1589afe3, 0x3c445fa2, 

+	0x3c4023dd, 0x159584d3, 0x15b8fea4, 0x3c33629d, 0x3c2f1d8e, 0x15c4d03e, 0x15e83fff, 0x3c224075, 

+	0x3c1df21f, 0x15f40e3a, 0x161773d6, 0x3c10f935, 0x3c0ca19b, 0x16233eac, 0x16469a0d, 0x3bff8ce8, 

+	0x3bfb2c0c, 0x16526176, 0x1675b286, 0x3bedfb99, 0x3be9917e, 0x1681767c, 0x16a4bd25, 0x3bdc4552, 

+	0x3bd7d1fa, 0x16b07d9f, 0x16d3b9cc, 0x3bca6a1d, 0x3bc5ed8d, 0x16df76c3, 0x1702a85e, 0x3bb86a08, 

+	0x3bb3e440, 0x170e61cc, 0x173188be, 0x3ba6451b, 0x3ba1b620, 0x173d3e9b, 0x17605ad0, 0x3b93fb63, 

+	0x3b8f6337, 0x176c0d15, 0x178f1e76, 0x3b818ceb, 0x3b7ceb90, 0x179acd1c, 0x17bdd394, 0x3b6ef9be, 

+	0x3b6a4f38, 0x17c97e93, 0x17ec7a0d, 0x3b5c41e8, 0x3b578e39, 0x17f8215e, 0x181b11c4, 0x3b496574, 

+	0x3b44a8a0, 0x1826b561, 0x18499a9d, 0x3b36646e, 0x3b319e77, 0x18553a7d, 0x1878147a, 0x3b233ee1, 

+	0x3b1e6fca, 0x1883b097, 0x18a67f3f, 0x3b0ff4d9, 0x3b0b1ca6, 0x18b21791, 0x18d4dad0, 0x3afc8663, 

+	0x3af7a516, 0x18e06f50, 0x1903270f, 0x3ae8f38b, 0x3ae40926, 0x190eb7b7, 0x193163e1, 0x3ad53c5b, 

+	0x3ad048e3, 0x193cf0a9, 0x195f9128, 0x3ac160e1, 0x3abc6458, 0x196b1a09, 0x198daec8, 0x3aad6129, 

+	0x3aa85b92, 0x199933bb, 0x19bbbca6, 0x3a993d3e, 0x3a942e9d, 0x19c73da3, 0x19e9baa3, 0x3a84f52f, 

+	0x3a7fdd86, 0x19f537a4, 0x1a17a8a5, 0x3a708906, 0x3a6b6859, 0x1a2321a2, 0x1a45868e, 0x3a5bf8d1, 

+	0x3a56cf23, 0x1a50fb81, 0x1a735442, 0x3a47449c, 0x3a4211f0, 0x1a7ec524, 0x1aa111a6, 0x3a326c74, 

+	0x3a2d30cd, 0x1aac7e6f, 0x1acebe9d, 0x3a1d7066, 0x3a182bc8, 0x1ada2746, 0x1afc5b0a, 0x3a08507f, 

+	0x3a0302ed, 0x1b07bf8c, 0x1b29e6d2, 0x39f30ccc, 0x39edb649, 0x1b354727, 0x1b5761d8, 0x39dda55a, 

+	0x39d845e9, 0x1b62bdf8, 0x1b84cc01, 0x39c81a36, 0x39c2b1da, 0x1b9023e5, 0x1bb22530, 0x39b26b6d, 

+	0x39acfa2b, 0x1bbd78d2, 0x1bdf6d4a, 0x399c990d, 0x39971ee7, 0x1beabca1, 0x1c0ca432, 0x3986a324, 

+	0x3981201e, 0x1c17ef39, 0x1c39c9cd, 0x397089bf, 0x396afddc, 0x1c45107c, 0x1c66ddfe, 0x395a4ceb, 

+	0x3954b82e, 0x1c72204f, 0x1c93e0ab, 0x3943ecb6, 0x393e4f23, 0x1c9f1e96, 0x1cc0d1b6, 0x392d692f, 

+	0x3927c2c9, 0x1ccc0b35, 0x1cedb106, 0x3916c262, 0x3911132d, 0x1cf8e611, 0x1d1a7e7d, 0x38fff85e, 

+	0x38fa405e, 0x1d25af0d, 0x1d473a00, 0x38e90b31, 0x38e34a69, 0x1d52660f, 0x1d73e374, 0x38d1fae9, 

+	0x38cc315d, 0x1d7f0afb, 0x1da07abc, 0x38bac795, 0x38b4f547, 0x1dab9db5, 0x1dccffbf, 0x38a37142, 

+	0x389d9637, 0x1dd81e21, 0x1df9725f, 0x388bf7ff, 0x3886143b, 0x1e048c24, 0x1e25d282, 0x38745bdb, 

+	0x386e6f60, 0x1e30e7a4, 0x1e52200c, 0x385c9ce3, 0x3856a7b6, 0x1e5d3084, 0x1e7e5ae2, 0x3844bb28, 

+	0x383ebd4c, 0x1e8966a8, 0x1eaa82e9, 0x382cb6b7, 0x3826b030, 0x1eb589f7, 0x1ed69805, 0x38148f9f, 

+	0x380e8071, 0x1ee19a54, 0x1f029a1c, 0x37fc45ef, 0x37f62e1d, 0x1f0d97a5, 0x1f2e8911, 0x37e3d9b7, 

+	0x37ddb945, 0x1f3981ce, 0x1f5a64cb, 0x37cb4b04, 0x37c521f6, 0x1f6558b5, 0x1f862d2d, 0x37b299e7, 

+	0x37ac6841, 0x1f911c3d, 0x1fb1e21d, 0x3799c66f, 0x37938c34, 0x1fbccc4d, 0x1fdd8381, 0x3780d0aa, 

+	0x377a8ddf, 0x1fe868c8, 0x2009113c, 0x3767b8a9, 0x37616d51, 0x2013f196, 0x20348b35, 0x374e7e7b, 

+	0x37482a9a, 0x203f6699, 0x205ff14f, 0x3735222f, 0x372ec5c9, 0x206ac7b8, 0x208b4372, 0x371ba3d4, 

+	0x37153eee, 0x209614d9, 0x20b68181, 0x3702037c, 0x36fb9618, 0x20c14ddf, 0x20e1ab63, 0x36e84135, 

+	0x36e1cb58, 0x20ec72b1, 0x210cc0fc, 0x36ce5d10, 0x36c7debd, 0x21178334, 0x2137c232, 0x36b4571b, 

+	0x36add058, 0x21427f4d, 0x2162aeea, 0x369a2f69, 0x3693a038, 0x216d66e2, 0x218d870b, 0x367fe608, 

+	0x36794e6e, 0x219839d8, 0x21b84a79, 0x36657b08, 0x365edb09, 0x21c2f815, 0x21e2f91a, 0x364aee7b, 

+	0x3644461b, 0x21eda17f, 0x220d92d4, 0x36304070, 0x36298fb4, 0x221835fb, 0x2238178d, 0x361570f8, 

+	0x360eb7e3, 0x2242b56f, 0x22628729, 0x35fa8023, 0x35f3beba, 0x226d1fc1, 0x228ce191, 0x35df6e03, 

+	0x35d8a449, 0x229774d7, 0x22b726a8, 0x35c43aa7, 0x35bd68a1, 0x22c1b496, 0x22e15655, 0x35a8e621, 

+	0x35a20bd3, 0x22ebdee5, 0x230b707e, 0x358d7081, 0x35868def, 0x2315f3a8, 0x23357509, 0x3571d9d9, 

+	0x356aef08, 0x233ff2c8, 0x235f63dc, 0x35562239, 0x354f2f2c, 0x2369dc29, 0x23893cdd, 0x353a49b2, 

+	0x35334e6f, 0x2393afb2, 0x23b2fff3, 0x351e5056, 0x35174ce0, 0x23bd6d48, 0x23dcad03, 0x35023636, 

+	0x34fb2a92, 0x23e714d3, 0x240643f4, 0x34e5fb63, 0x34dee795, 0x2410a639, 0x242fc4ad, 0x34c99fef, 

+	0x34c283fb, 0x243a215f, 0x24592f13, 0x34ad23eb, 0x34a5ffd5, 0x2463862c, 0x2482830d, 0x34908768, 

+	0x34895b36, 0x248cd487, 0x24abc082, 0x3473ca79, 0x346c962f, 0x24b60c57, 0x24d4e757, 0x3456ed2f, 

+	0x344fb0d1, 0x24df2d81, 0x24fdf775, 0x3439ef9c, 0x3432ab2e, 0x250837ed, 0x2526f0c1, 0x341cd1d2, 

+	0x34158559, 0x25312b81, 0x254fd323, 0x33ff93e2, 0x33f83f62, 0x255a0823, 0x25789e80, 0x33e235df, 

+	0x33dad95e, 0x2582cdbc, 0x25a152c0, 0x33c4b7db, 0x33bd535c, 0x25ab7c30, 0x25c9efca, 0x33a719e8, 

+	0x339fad70, 0x25d41369, 0x25f27584, 0x33895c18, 0x3381e7ac, 0x25fc934b, 0x261ae3d6, 0x336b7e7e, 

+	0x33640223, 0x2624fbbf, 0x26433aa7, 0x334d812d, 0x3345fce6, 0x264d4cac, 0x266b79dd, 0x332f6435, 

+	0x3327d808, 0x267585f8, 0x2693a161, 0x331127ab, 0x3309939c, 0x269da78b, 0x26bbb119, 0x32f2cba1, 

+	0x32eb2fb5, 0x26c5b14c, 0x26e3a8ec, 0x32d45029, 0x32ccac64, 0x26eda322, 0x270b88c2, 0x32b5b557, 

+	0x32ae09be, 0x27157cf5, 0x27335082, 0x3296fb3d, 0x328f47d5, 0x273d3eac, 0x275b0014, 0x327821ee, 

+	0x327066bc, 0x2764e82f, 0x27829760, 0x3259297d, 0x32516686, 0x278c7965, 0x27aa164c, 0x323a11fe, 

+	0x32324746, 0x27b3f235, 0x27d17cc1, 0x321adb83, 0x3213090f, 0x27db5288, 0x27f8caa5, 0x31fb8620, 

+	0x31f3abf5, 0x28029a45, 0x281fffe2, 0x31dc11e8, 0x31d4300b, 0x2829c954, 0x28471c5e, 0x31bc7eee, 

+	0x31b49564, 0x2850df9d, 0x286e2002, 0x319ccd46, 0x3194dc14, 0x2877dd07, 0x28950ab6, 0x317cfd04, 

+	0x3175042e, 0x289ec17a, 0x28bbdc61, 0x315d0e3b, 0x31550dc6, 0x28c58cdf, 0x28e294eb, 0x313d00ff, 

+	0x3134f8f1, 0x28ec3f1e, 0x2909343e, 0x311cd564, 0x3114c5c0, 0x2912d81f, 0x292fba40, 0x30fc8b7d, 

+	0x30f47449, 0x293957c9, 0x295626da, 0x30dc235e, 0x30d404a0, 0x295fbe06, 0x297c79f5, 0x30bb9d1c, 

+	0x30b376d8, 0x29860abd, 0x29a2b378, 0x309af8ca, 0x3092cb05, 0x29ac3dd7, 0x29c8d34d, 0x307a367c, 

+	0x3072013c, 0x29d2573c, 0x29eed95b, 0x30595648, 0x30511991, 0x29f856d5, 0x2a14c58b, 0x30385840, 

+	0x30301418, 0x2a1e3c8a, 0x2a3a97c7, 0x30173c7a, 0x300ef0e5, 0x2a440844, 0x2a604ff5, 0x2ff6030a, 

+	0x2fedb00d, 0x2a69b9ec, 0x2a85ee00, 0x2fd4ac04, 0x2fcc51a5, 0x2a8f516b, 0x2aab71d0, 0x2fb3377c, 

+	0x2faad5c1, 0x2ab4cea9, 0x2ad0db4e, 0x2f91a589, 0x2f893c75, 0x2ada318e, 0x2af62a63, 0x2f6ff63d, 

+	0x2f6785d7, 0x2aff7a05, 0x2b1b5ef8, 0x2f4e29af, 0x2f45b1fb, 0x2b24a7f6, 0x2b4078f5, 0x2f2c3ff2, 

+	0x2f23c0f6, 0x2b49bb4a, 0x2b657844, 0x2f0a391d, 0x2f01b2de, 0x2b6eb3ea, 0x2b8a5cce, 0x2ee81543, 

+	0x2edf87c6, 0x2b9391c0, 0x2baf267d, 0x2ec5d479, 0x2ebd3fc4, 0x2bb854b4, 0x2bd3d53a, 0x2ea376d6, 

+	0x2e9adaee, 0x2bdcfcb0, 0x2bf868ed, 0x2e80fc6e, 0x2e785958, 0x2c01899e, 0x2c1ce181, 0x2e5e6556, 

+	0x2e55bb17, 0x2c25fb66, 0x2c413edf, 0x2e3bb1a4, 0x2e330042, 0x2c4a51f3, 0x2c6580f1, 0x2e18e16d, 

+	0x2e1028ed, 0x2c6e8d2e, 0x2c89a79f, 0x2df5f4c7, 0x2ded352f, 0x2c92ad01, 0x2cadb2d5, 0x2dd2ebc7, 

+	0x2dca251c, 0x2cb6b155, 0x2cd1a27b, 0x2dafc683, 0x2da6f8ca, 0x2cda9a14, 0x2cf5767c, 0x2d8c8510, 

+	0x2d83b04f, 0x2cfe6728, 0x2d192ec1, 0x2d692784, 0x2d604bc0, 0x2d22187a, 0x2d3ccb34, 0x2d45adf6

+};
+
+const int twidTab512[8*6 + 32*6 + 128*6] = {

+	0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3b20d79e, 0x187de2a6, 

+	0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 

+	0x187de2a6, 0x3b20d79e, 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f, 

+	0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xe7821d5a, 0x3b20d79e, 

+	0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 

+	0xc4df2862, 0xe7821d5a, 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae, 

+

+	0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3fb11b47, 0x0645e9af, 

+	0x3fec43c6, 0x0323ecbe, 0x3f4eaafe, 0x09640837, 0x3ec52f9f, 0x0c7c5c1e, 0x3fb11b47, 0x0645e9af, 

+	0x3d3e82ad, 0x1294062e, 0x3d3e82ad, 0x1294062e, 0x3f4eaafe, 0x09640837, 0x39daf5e8, 0x1b5d1009, 

+	0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x387165e3, 0x1e2b5d38, 

+	0x3e14fdf7, 0x0f8cfcbd, 0x2f6bbe44, 0x2afad269, 0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e, 

+	0x2899e64a, 0x317900d6, 0x317900d6, 0x2899e64a, 0x3c424209, 0x158f9a75, 0x20e70f32, 0x36e5068a, 

+	0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x2899e64a, 0x317900d6, 

+	0x39daf5e8, 0x1b5d1009, 0x0f8cfcbd, 0x3e14fdf7, 0x238e7673, 0x3536cc52, 0x387165e3, 0x1e2b5d38, 

+	0x0645e9af, 0x3fb11b47, 0x1e2b5d38, 0x387165e3, 0x36e5068a, 0x20e70f32, 0xfcdc1342, 0x3fec43c6, 

+	0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f, 0x1294062e, 0x3d3e82ad, 

+	0x3367c08f, 0x261feff9, 0xea70658b, 0x3c424209, 0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a, 

+	0xe1d4a2c8, 0x387165e3, 0x0645e9af, 0x3fb11b47, 0x2f6bbe44, 0x2afad269, 0xd9e01007, 0x3367c08f, 

+	0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xf9ba1651, 0x3fb11b47, 

+	0x2afad269, 0x2f6bbe44, 0xcc983f71, 0x261feff9, 0xf383a3e2, 0x3ec52f9f, 0x2899e64a, 0x317900d6, 

+	0xc78e9a1d, 0x1e2b5d38, 0xed6bf9d2, 0x3d3e82ad, 0x261feff9, 0x3367c08f, 0xc3bdbdf7, 0x158f9a75, 

+	0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xe1d4a2c8, 0x387165e3, 

+	0x20e70f32, 0x36e5068a, 0xc013bc3a, 0x0323ecbe, 0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3, 

+	0xc04ee4b9, 0xf9ba1651, 0xd76619b6, 0x317900d6, 0x1b5d1009, 0x39daf5e8, 0xc1eb0209, 0xf0730343, 

+	0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xce86ff2a, 0x2899e64a, 

+	0x158f9a75, 0x3c424209, 0xc91af976, 0xdf18f0ce, 0xcac933ae, 0x238e7673, 0x1294062e, 0x3d3e82ad, 

+	0xce86ff2a, 0xd76619b6, 0xc78e9a1d, 0x1e2b5d38, 0x0f8cfcbd, 0x3e14fdf7, 0xd5052d97, 0xd09441bc, 

+	0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae, 0xc2c17d53, 0x1294062e, 

+	0x09640837, 0x3f4eaafe, 0xe4a2eff7, 0xc6250a18, 0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47, 

+	0xed6bf9d2, 0xc2c17d53, 0xc04ee4b9, 0x0645e9af, 0x0323ecbe, 0x3fec43c6, 0xf69bf7c9, 0xc0b15502, 

+

+	0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3ffb10c1, 0x0192155f, 

+	0x3ffec42d, 0x00c90e8f, 0x3ff4e5df, 0x025b0cae, 0x3fec43c6, 0x0323ecbe, 0x3ffb10c1, 0x0192155f, 

+	0x3fd39b5a, 0x04b54824, 0x3fd39b5a, 0x04b54824, 0x3ff4e5df, 0x025b0cae, 0x3f9c2bfa, 0x070de171, 

+	0x3fb11b47, 0x0645e9af, 0x3fec43c6, 0x0323ecbe, 0x3f4eaafe, 0x09640837, 0x3f84c8e1, 0x07d59395, 

+	0x3fe12acb, 0x03ecadcf, 0x3eeb3347, 0x0bb6ecef, 0x3f4eaafe, 0x09640837, 0x3fd39b5a, 0x04b54824, 

+	0x3e71e758, 0x0e05c135, 0x3f0ec9f4, 0x0af10a22, 0x3fc395f9, 0x057db402, 0x3de2f147, 0x104fb80e, 

+	0x3ec52f9f, 0x0c7c5c1e, 0x3fb11b47, 0x0645e9af, 0x3d3e82ad, 0x1294062e, 0x3e71e758, 0x0e05c135, 

+	0x3f9c2bfa, 0x070de171, 0x3c84d496, 0x14d1e242, 0x3e14fdf7, 0x0f8cfcbd, 0x3f84c8e1, 0x07d59395, 

+	0x3bb6276d, 0x17088530, 0x3dae81ce, 0x1111d262, 0x3f6af2e3, 0x089cf867, 0x3ad2c2e7, 0x19372a63, 

+	0x3d3e82ad, 0x1294062e, 0x3f4eaafe, 0x09640837, 0x39daf5e8, 0x1b5d1009, 0x3cc511d8, 0x14135c94, 

+	0x3f2ff249, 0x0a2abb58, 0x38cf1669, 0x1d79775b, 0x3c424209, 0x158f9a75, 0x3f0ec9f4, 0x0af10a22, 

+	0x37af8158, 0x1f8ba4db, 0x3bb6276d, 0x17088530, 0x3eeb3347, 0x0bb6ecef, 0x367c9a7d, 0x2192e09a, 

+	0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x3a8269a2, 0x19ef7943, 

+	0x3e9cc076, 0x0d415012, 0x33de87de, 0x257db64b, 0x39daf5e8, 0x1b5d1009, 0x3e71e758, 0x0e05c135, 

+	0x32744493, 0x275ff452, 0x392a9642, 0x1cc66e99, 0x3e44a5ee, 0x0ec9a7f2, 0x30f8801f, 0x29348937, 

+	0x387165e3, 0x1e2b5d38, 0x3e14fdf7, 0x0f8cfcbd, 0x2f6bbe44, 0x2afad269, 0x37af8158, 0x1f8ba4db, 

+	0x3de2f147, 0x104fb80e, 0x2dce88a9, 0x2cb2324b, 0x36e5068a, 0x20e70f32, 0x3dae81ce, 0x1111d262, 

+	0x2c216eaa, 0x2e5a106f, 0x361214b0, 0x223d66a8, 0x3d77b191, 0x11d3443f, 0x2a650525, 0x2ff1d9c6, 

+	0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e, 0x2899e64a, 0x317900d6, 0x34534f40, 0x24da0a99, 

+	0x3d02f756, 0x135410c2, 0x26c0b162, 0x32eefde9, 0x3367c08f, 0x261feff9, 0x3cc511d8, 0x14135c94, 

+	0x24da0a99, 0x34534f40, 0x32744493, 0x275ff452, 0x3c84d496, 0x14d1e242, 0x22e69ac7, 0x35a5793c, 

+	0x317900d6, 0x2899e64a, 0x3c424209, 0x158f9a75, 0x20e70f32, 0x36e5068a, 0x30761c17, 0x29cd9577, 

+	0x3bfd5cc4, 0x164c7ddd, 0x1edc1952, 0x3811884c, 0x2f6bbe44, 0x2afad269, 0x3bb6276d, 0x17088530, 

+	0x1cc66e99, 0x392a9642, 0x2e5a106f, 0x2c216eaa, 0x3b6ca4c4, 0x17c3a931, 0x1aa6c82b, 0x3a2fcee8, 

+	0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x2c216eaa, 0x2e5a106f, 

+	0x3ad2c2e7, 0x19372a63, 0x164c7ddd, 0x3bfd5cc4, 0x2afad269, 0x2f6bbe44, 0x3a8269a2, 0x19ef7943, 

+	0x14135c94, 0x3cc511d8, 0x29cd9577, 0x30761c17, 0x3a2fcee8, 0x1aa6c82b, 0x11d3443f, 0x3d77b191, 

+	0x2899e64a, 0x317900d6, 0x39daf5e8, 0x1b5d1009, 0x0f8cfcbd, 0x3e14fdf7, 0x275ff452, 0x32744493, 

+	0x3983e1e7, 0x1c1249d8, 0x0d415012, 0x3e9cc076, 0x261feff9, 0x3367c08f, 0x392a9642, 0x1cc66e99, 

+	0x0af10a22, 0x3f0ec9f4, 0x24da0a99, 0x34534f40, 0x38cf1669, 0x1d79775b, 0x089cf867, 0x3f6af2e3, 

+	0x238e7673, 0x3536cc52, 0x387165e3, 0x1e2b5d38, 0x0645e9af, 0x3fb11b47, 0x223d66a8, 0x361214b0, 

+	0x3811884c, 0x1edc1952, 0x03ecadcf, 0x3fe12acb, 0x20e70f32, 0x36e5068a, 0x37af8158, 0x1f8ba4db, 

+	0x0192155f, 0x3ffb10c1, 0x1f8ba4db, 0x37af8158, 0x374b54ce, 0x2039f90e, 0xff36f171, 0x3ffec42d, 

+	0x1e2b5d38, 0x387165e3, 0x36e5068a, 0x20e70f32, 0xfcdc1342, 0x3fec43c6, 0x1cc66e99, 0x392a9642, 

+	0x367c9a7d, 0x2192e09a, 0xfa824bfe, 0x3fc395f9, 0x1b5d1009, 0x39daf5e8, 0x361214b0, 0x223d66a8, 

+	0xf82a6c6b, 0x3f84c8e1, 0x19ef7943, 0x3a8269a2, 0x35a5793c, 0x22e69ac7, 0xf5d544a8, 0x3f2ff249, 

+	0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f, 0x17088530, 0x3bb6276d, 

+	0x34c61236, 0x2434f332, 0xf136580e, 0x3e44a5ee, 0x158f9a75, 0x3c424209, 0x34534f40, 0x24da0a99, 

+	0xeeee2d9e, 0x3dae81ce, 0x14135c94, 0x3cc511d8, 0x33de87de, 0x257db64b, 0xecabef3e, 0x3d02f756, 

+	0x1294062e, 0x3d3e82ad, 0x3367c08f, 0x261feff9, 0xea70658b, 0x3c424209, 0x1111d262, 0x3dae81ce, 

+	0x32eefde9, 0x26c0b162, 0xe83c56cf, 0x3b6ca4c4, 0x0f8cfcbd, 0x3e14fdf7, 0x32744493, 0x275ff452, 

+	0xe61086bd, 0x3a8269a2, 0x0e05c135, 0x3e71e758, 0x31f79947, 0x27fdb2a6, 0xe3edb628, 0x3983e1e7, 

+	0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a, 0xe1d4a2c8, 0x387165e3, 0x0af10a22, 0x3f0ec9f4, 

+	0x30f8801f, 0x29348937, 0xdfc606f2, 0x374b54ce, 0x09640837, 0x3f4eaafe, 0x30761c17, 0x29cd9577, 

+	0xddc29958, 0x361214b0, 0x07d59395, 0x3f84c8e1, 0x2ff1d9c6, 0x2a650525, 0xdbcb0cce, 0x34c61236, 

+	0x0645e9af, 0x3fb11b47, 0x2f6bbe44, 0x2afad269, 0xd9e01007, 0x3367c08f, 0x04b54824, 0x3fd39b5a, 

+	0x2ee3cebe, 0x2b8ef77c, 0xd8024d5a, 0x31f79947, 0x0323ecbe, 0x3fec43c6, 0x2e5a106f, 0x2c216eaa, 

+	0xd6326a89, 0x30761c17, 0x0192155f, 0x3ffb10c1, 0x2dce88a9, 0x2cb2324b, 0xd4710884, 0x2ee3cebe, 

+	0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xfe6deaa1, 0x3ffb10c1, 

+	0x2cb2324b, 0x2dce88a9, 0xd11c3142, 0x2b8ef77c, 0xfcdc1342, 0x3fec43c6, 0x2c216eaa, 0x2e5a106f, 

+	0xcf89e3e9, 0x29cd9577, 0xfb4ab7dc, 0x3fd39b5a, 0x2b8ef77c, 0x2ee3cebe, 0xce0866b9, 0x27fdb2a6, 

+	0xf9ba1651, 0x3fb11b47, 0x2afad269, 0x2f6bbe44, 0xcc983f71, 0x261feff9, 0xf82a6c6b, 0x3f84c8e1, 

+	0x2a650525, 0x2ff1d9c6, 0xcb39edca, 0x2434f332, 0xf69bf7c9, 0x3f4eaafe, 0x29cd9577, 0x30761c17, 

+	0xc9edeb50, 0x223d66a8, 0xf50ef5de, 0x3f0ec9f4, 0x29348937, 0x30f8801f, 0xc8b4ab32, 0x2039f90e, 

+	0xf383a3e2, 0x3ec52f9f, 0x2899e64a, 0x317900d6, 0xc78e9a1d, 0x1e2b5d38, 0xf1fa3ecb, 0x3e71e758, 

+	0x27fdb2a6, 0x31f79947, 0xc67c1e19, 0x1c1249d8, 0xf0730343, 0x3e14fdf7, 0x275ff452, 0x32744493, 

+	0xc57d965e, 0x19ef7943, 0xeeee2d9e, 0x3dae81ce, 0x26c0b162, 0x32eefde9, 0xc4935b3c, 0x17c3a931, 

+	0xed6bf9d2, 0x3d3e82ad, 0x261feff9, 0x3367c08f, 0xc3bdbdf7, 0x158f9a75, 0xebeca36c, 0x3cc511d8, 

+	0x257db64b, 0x33de87de, 0xc2fd08aa, 0x135410c2, 0xea70658b, 0x3c424209, 0x24da0a99, 0x34534f40, 

+	0xc2517e32, 0x1111d262, 0xe8f77ad0, 0x3bb6276d, 0x2434f332, 0x34c61236, 0xc1bb5a12, 0x0ec9a7f2, 

+	0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xe61086bd, 0x3a8269a2, 

+	0x22e69ac7, 0x35a5793c, 0xc0d00db7, 0x0a2abb58, 0xe4a2eff7, 0x39daf5e8, 0x223d66a8, 0x361214b0, 

+	0xc07b371f, 0x07d59395, 0xe3399167, 0x392a9642, 0x2192e09a, 0x367c9a7d, 0xc03c6a07, 0x057db402, 

+	0xe1d4a2c8, 0x387165e3, 0x20e70f32, 0x36e5068a, 0xc013bc3a, 0x0323ecbe, 0xe0745b25, 0x37af8158, 

+	0x2039f90e, 0x374b54ce, 0xc0013bd3, 0x00c90e8f, 0xdf18f0ce, 0x36e5068a, 0x1f8ba4db, 0x37af8158, 

+	0xc004ef3f, 0xfe6deaa1, 0xddc29958, 0x361214b0, 0x1edc1952, 0x3811884c, 0xc01ed535, 0xfc135231, 

+	0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3, 0xc04ee4b9, 0xf9ba1651, 0xdb25f567, 0x34534f40, 

+	0x1d79775b, 0x38cf1669, 0xc0950d1d, 0xf7630799, 0xd9e01007, 0x3367c08f, 0x1cc66e99, 0x392a9642, 

+	0xc0f1360c, 0xf50ef5de, 0xd8a00bae, 0x32744493, 0x1c1249d8, 0x3983e1e7, 0xc1633f8a, 0xf2beafee, 

+	0xd76619b6, 0x317900d6, 0x1b5d1009, 0x39daf5e8, 0xc1eb0209, 0xf0730343, 0xd6326a89, 0x30761c17, 

+	0x1aa6c82b, 0x3a2fcee8, 0xc2884e6f, 0xee2cbbc1, 0xd5052d97, 0x2f6bbe44, 0x19ef7943, 0x3a8269a2, 

+	0xc33aee28, 0xebeca36c, 0xd3de9156, 0x2e5a106f, 0x19372a63, 0x3ad2c2e7, 0xc402a33c, 0xe9b38223, 

+	0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xd1a5ef91, 0x2c216eaa, 

+	0x17c3a931, 0x3b6ca4c4, 0xc5d03118, 0xe55937d5, 0xd09441bc, 0x2afad269, 0x17088530, 0x3bb6276d, 

+	0xc6d569be, 0xe3399167, 0xcf89e3e9, 0x29cd9577, 0x164c7ddd, 0x3bfd5cc4, 0xc7ee77b4, 0xe123e6ae, 

+	0xce86ff2a, 0x2899e64a, 0x158f9a75, 0x3c424209, 0xc91af976, 0xdf18f0ce, 0xcd8bbb6d, 0x275ff452, 

+	0x14d1e242, 0x3c84d496, 0xca5a86c4, 0xdd196539, 0xcc983f71, 0x261feff9, 0x14135c94, 0x3cc511d8, 

+	0xcbacb0c0, 0xdb25f567, 0xcbacb0c0, 0x24da0a99, 0x135410c2, 0x3d02f756, 0xcd110217, 0xd93f4e9e, 

+	0xcac933ae, 0x238e7673, 0x1294062e, 0x3d3e82ad, 0xce86ff2a, 0xd76619b6, 0xc9edeb50, 0x223d66a8, 

+	0x11d3443f, 0x3d77b191, 0xd00e263a, 0xd59afadb, 0xc91af976, 0x20e70f32, 0x1111d262, 0x3dae81ce, 

+	0xd1a5ef91, 0xd3de9156, 0xc8507ea8, 0x1f8ba4db, 0x104fb80e, 0x3de2f147, 0xd34dcdb5, 0xd2317757, 

+	0xc78e9a1d, 0x1e2b5d38, 0x0f8cfcbd, 0x3e14fdf7, 0xd5052d97, 0xd09441bc, 0xc6d569be, 0x1cc66e99, 

+	0x0ec9a7f2, 0x3e44a5ee, 0xd6cb76c9, 0xcf077fe1, 0xc6250a18, 0x1b5d1009, 0x0e05c135, 0x3e71e758, 

+	0xd8a00bae, 0xcd8bbb6d, 0xc57d965e, 0x19ef7943, 0x0d415012, 0x3e9cc076, 0xda8249b5, 0xcc217822, 

+	0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae, 0xc449d893, 0x17088530, 

+	0x0bb6ecef, 0x3eeb3347, 0xde6d1f66, 0xc9836583, 0xc3bdbdf7, 0x158f9a75, 0x0af10a22, 0x3f0ec9f4, 

+	0xe0745b25, 0xc8507ea8, 0xc33aee28, 0x14135c94, 0x0a2abb58, 0x3f2ff249, 0xe28688a5, 0xc730e997, 

+	0xc2c17d53, 0x1294062e, 0x09640837, 0x3f4eaafe, 0xe4a2eff7, 0xc6250a18, 0xc2517e32, 0x1111d262, 

+	0x089cf867, 0x3f6af2e3, 0xe6c8d59d, 0xc52d3d19, 0xc1eb0209, 0x0f8cfcbd, 0x07d59395, 0x3f84c8e1, 

+	0xe8f77ad0, 0xc449d893, 0xc18e18a8, 0x0e05c135, 0x070de171, 0x3f9c2bfa, 0xeb2e1dbe, 0xc37b2b6a, 

+	0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47, 0xed6bf9d2, 0xc2c17d53, 0xc0f1360c, 0x0af10a22, 

+	0x057db402, 0x3fc395f9, 0xefb047f2, 0xc21d0eb9, 0xc0b15502, 0x09640837, 0x04b54824, 0x3fd39b5a, 

+	0xf1fa3ecb, 0xc18e18a8, 0xc07b371f, 0x07d59395, 0x03ecadcf, 0x3fe12acb, 0xf4491311, 0xc114ccb9, 

+	0xc04ee4b9, 0x0645e9af, 0x0323ecbe, 0x3fec43c6, 0xf69bf7c9, 0xc0b15502, 0xc02c64a6, 0x04b54824, 

+	0x025b0cae, 0x3ff4e5df, 0xf8f21e8f, 0xc063d406, 0xc013bc3a, 0x0323ecbe, 0x0192155f, 0x3ffb10c1, 

+	0xfb4ab7dc, 0xc02c64a6, 0xc004ef3f, 0x0192155f, 0x00c90e8f, 0x3ffec42d, 0xfda4f352, 0xc00b1a21

+};

+

+const int twidTab64[4*6 + 16*6] = {

+	0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x2d413ccc, 0x2d413ccc, 

+	0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 

+	0xd2bec334, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 

+

+	0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3ec52f9f, 0x0c7c5c1e, 

+	0x3fb11b47, 0x0645e9af, 0x3d3e82ad, 0x1294062e, 0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e, 

+	0x3536cc52, 0x238e7673, 0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e, 0x2899e64a, 0x317900d6, 

+	0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x238e7673, 0x3536cc52, 

+	0x387165e3, 0x1e2b5d38, 0x0645e9af, 0x3fb11b47, 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 

+	0xf383a3e2, 0x3ec52f9f, 0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a, 0xe1d4a2c8, 0x387165e3, 

+	0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xf383a3e2, 0x3ec52f9f, 

+	0x2899e64a, 0x317900d6, 0xc78e9a1d, 0x1e2b5d38, 0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52, 

+	0xc13ad061, 0x0c7c5c1e, 0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3, 0xc04ee4b9, 0xf9ba1651, 

+	0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xcac933ae, 0x238e7673, 

+	0x1294062e, 0x3d3e82ad, 0xce86ff2a, 0xd76619b6, 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 

+	0xdc71898d, 0xcac933ae, 0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47, 0xed6bf9d2, 0xc2c17d53 

+};

+#endif  //ARMV5E

+

+const int ShortWindowSine[FRAME_LEN_SHORT/2] ={  

+	0x00c97fff, 0x025b7ffa, 0x03ed7ff1, 0x057f7fe2, 0x07117fce, 0x08a27fb5, 0x0a337f98, 0x0bc47f75, 

+	0x0d547f4e, 0x0ee47f22, 0x10737ef0, 0x12017eba, 0x138f7e7f, 0x151c7e3f, 0x16a87dfb, 0x18337db1, 

+	0x19be7d63, 0x1b477d0f, 0x1cd07cb7, 0x1e577c5a, 0x1fdd7bf9, 0x21627b92, 0x22e57b27, 0x24677ab7, 

+	0x25e87a42, 0x276879c9, 0x28e5794a, 0x2a6278c8, 0x2bdc7840, 0x2d5577b4, 0x2ecc7723, 0x3042768e, 

+	0x31b575f4, 0x33277556, 0x349774b3, 0x3604740b, 0x3770735f, 0x38d972af, 0x3a4071fa, 0x3ba57141, 

+	0x3d087083, 0x3e686fc2, 0x3fc66efb, 0x41216e31, 0x427a6d62, 0x43d16c8f, 0x45246bb8, 0x46756add, 

+	0x47c469fd, 0x490f691a, 0x4a586832, 0x4b9e6747, 0x4ce16657, 0x4e216564, 0x4f5e646c, 0x50986371, 

+	0x51cf6272, 0x5303616f, 0x54336068, 0x55605f5e, 0x568a5e50, 0x57b15d3e, 0x58d45c29, 0x59f45b10

+};
+
+const int LongWindowKBD[FRAME_LEN_LONG/2]={  
+	0x000a7fff, 0x000e7fff, 0x00127fff, 0x00157fff, 0x00197fff, 0x001c7fff, 0x00207fff, 0x00237fff, 

+	0x00267fff, 0x002a7fff, 0x002d7fff, 0x00307fff, 0x00347fff, 0x00387fff, 0x003b7fff, 0x003f7fff, 

+	0x00437fff, 0x00477fff, 0x004b7fff, 0x004f7fff, 0x00537fff, 0x00577fff, 0x005b7fff, 0x00607fff, 

+	0x00647fff, 0x00697fff, 0x006d7fff, 0x00727fff, 0x00777fff, 0x007c7fff, 0x00817fff, 0x00867fff, 

+	0x008b7fff, 0x00917fff, 0x00967fff, 0x009c7fff, 0x00a17fff, 0x00a77fff, 0x00ad7fff, 0x00b37fff, 

+	0x00b97fff, 0x00bf7fff, 0x00c67fff, 0x00cc7fff, 0x00d37fff, 0x00da7fff, 0x00e07fff, 0x00e77fff, 

+	0x00ee7fff, 0x00f57fff, 0x00fd7fff, 0x01047fff, 0x010c7fff, 0x01137fff, 0x011b7fff, 0x01237fff, 

+	0x012b7fff, 0x01337fff, 0x013c7ffe, 0x01447ffe, 0x014d7ffe, 0x01567ffe, 0x015f7ffe, 0x01687ffe, 

+	0x01717ffe, 0x017a7ffe, 0x01837ffe, 0x018d7ffe, 0x01977ffd, 0x01a17ffd, 0x01ab7ffd, 0x01b57ffd, 

+	0x01bf7ffd, 0x01ca7ffd, 0x01d47ffd, 0x01df7ffc, 0x01ea7ffc, 0x01f57ffc, 0x02007ffc, 0x020c7ffc, 

+	0x02177ffc, 0x02237ffb, 0x022f7ffb, 0x023b7ffb, 0x02477ffb, 0x02537ffb, 0x02607ffa, 0x026d7ffa, 

+	0x027a7ffa, 0x02877ffa, 0x02947ff9, 0x02a17ff9, 0x02af7ff9, 0x02bc7ff9, 0x02ca7ff8, 0x02d87ff8, 

+	0x02e77ff8, 0x02f57ff7, 0x03047ff7, 0x03127ff7, 0x03217ff6, 0x03317ff6, 0x03407ff5, 0x034f7ff5, 

+	0x035f7ff5, 0x036f7ff4, 0x037f7ff4, 0x038f7ff3, 0x03a07ff3, 0x03b07ff2, 0x03c17ff2, 0x03d27ff1, 

+	0x03e37ff1, 0x03f57ff0, 0x04067ff0, 0x04187fef, 0x042a7fef, 0x043c7fee, 0x044f7fed, 0x04617fed, 

+	0x04747fec, 0x04877feb, 0x049a7feb, 0x04ae7fea, 0x04c17fe9, 0x04d57fe9, 0x04e97fe8, 0x04fd7fe7, 

+	0x05127fe6, 0x05277fe5, 0x053b7fe5, 0x05507fe4, 0x05667fe3, 0x057b7fe2, 0x05917fe1, 0x05a77fe0, 

+	0x05bd7fdf, 0x05d37fde, 0x05ea7fdd, 0x06017fdc, 0x06187fdb, 0x062f7fda, 0x06467fd9, 0x065e7fd7, 

+	0x06767fd6, 0x068e7fd5, 0x06a67fd4, 0x06bf7fd2, 0x06d87fd1, 0x06f17fd0, 0x070a7fce, 0x07237fcd, 

+	0x073d7fcc, 0x07577fca, 0x07717fc9, 0x078c7fc7, 0x07a67fc5, 0x07c17fc4, 0x07dc7fc2, 0x07f77fc0, 

+	0x08137fbf, 0x082f7fbd, 0x084b7fbb, 0x08677fb9, 0x08847fb7, 0x08a07fb6, 0x08bd7fb4, 0x08da7fb2, 

+	0x08f87faf, 0x09167fad, 0x09347fab, 0x09527fa9, 0x09707fa7, 0x098f7fa5, 0x09ae7fa2, 0x09cd7fa0, 

+	0x09ec7f9d, 0x0a0c7f9b, 0x0a2c7f98, 0x0a4c7f96, 0x0a6c7f93, 0x0a8d7f91, 0x0aae7f8e, 0x0acf7f8b, 

+	0x0af07f88, 0x0b127f85, 0x0b337f82, 0x0b557f7f, 0x0b787f7c, 0x0b9a7f79, 0x0bbd7f76, 0x0be07f73, 

+	0x0c047f6f, 0x0c277f6c, 0x0c4b7f69, 0x0c6f7f65, 0x0c937f61, 0x0cb87f5e, 0x0cdd7f5a, 0x0d027f56, 

+	0x0d277f53, 0x0d4d7f4f, 0x0d737f4b, 0x0d997f47, 0x0dbf7f43, 0x0de67f3e, 0x0e0c7f3a, 0x0e347f36, 

+	0x0e5b7f31, 0x0e837f2d, 0x0eaa7f28, 0x0ed37f24, 0x0efb7f1f, 0x0f237f1a, 0x0f4c7f15, 0x0f757f10, 

+	0x0f9f7f0b, 0x0fc87f06, 0x0ff27f01, 0x101c7efb, 0x10477ef6, 0x10717ef0, 0x109c7eeb, 0x10c87ee5, 

+	0x10f37edf, 0x111f7eda, 0x114a7ed4, 0x11777ece, 0x11a37ec7, 0x11d07ec1, 0x11fd7ebb, 0x122a7eb4, 

+	0x12577eae, 0x12857ea7, 0x12b37ea0, 0x12e17e9a, 0x130f7e93, 0x133e7e8c, 0x136d7e84, 0x139c7e7d, 

+	0x13cc7e76, 0x13fb7e6e, 0x142b7e67, 0x145b7e5f, 0x148c7e57, 0x14bc7e4f, 0x14ed7e47, 0x151e7e3f, 

+	0x15507e37, 0x15817e2e, 0x15b37e26, 0x15e57e1d, 0x16187e14, 0x164a7e0b, 0x167d7e02, 0x16b07df9, 

+	0x16e47df0, 0x17177de6, 0x174b7ddd, 0x177f7dd3, 0x17b37dc9, 0x17e87dbf, 0x181d7db5, 0x18527dab, 

+	0x18877da1, 0x18bc7d96, 0x18f27d8c, 0x19287d81, 0x195e7d76, 0x19957d6b, 0x19cb7d60, 0x1a027d54, 

+	0x1a397d49, 0x1a717d3d, 0x1aa87d31, 0x1ae07d26, 0x1b187d19, 0x1b507d0d, 0x1b897d01, 0x1bc27cf4, 

+	0x1bfb7ce8, 0x1c347cdb, 0x1c6d7cce, 0x1ca77cc1, 0x1ce17cb3, 0x1d1b7ca6, 0x1d557c98, 0x1d8f7c8a, 

+	0x1dca7c7c, 0x1e057c6e, 0x1e407c60, 0x1e7b7c51, 0x1eb77c43, 0x1ef37c34, 0x1f2f7c25, 0x1f6b7c16, 

+	0x1fa77c06, 0x1fe47bf7, 0x20217be7, 0x205e7bd7, 0x209b7bc7, 0x20d87bb7, 0x21167ba6, 0x21547b96, 

+	0x21927b85, 0x21d07b74, 0x220e7b63, 0x224d7b52, 0x228c7b40, 0x22cb7b2e, 0x230a7b1c, 0x23497b0a, 

+	0x23897af8, 0x23c87ae6, 0x24087ad3, 0x24487ac0, 0x24897aad, 0x24c97a9a, 0x250a7a86, 0x254b7a73, 

+	0x258c7a5f, 0x25cd7a4b, 0x260e7a36, 0x26507a22, 0x26917a0d, 0x26d379f8, 0x271579e3, 0x275779ce, 

+	0x279a79b8, 0x27dc79a3, 0x281f798d, 0x28627977, 0x28a57960, 0x28e8794a, 0x292b7933, 0x296f791c, 

+	0x29b27905, 0x29f678ed, 0x2a3a78d6, 0x2a7e78be, 0x2ac278a6, 0x2b07788d, 0x2b4b7875, 0x2b90785c, 

+	0x2bd47843, 0x2c19782a, 0x2c5e7810, 0x2ca477f7, 0x2ce977dd, 0x2d2e77c3, 0x2d7477a8, 0x2dba778e, 

+	0x2dff7773, 0x2e457758, 0x2e8b773d, 0x2ed27721, 0x2f187706, 0x2f5e76ea, 0x2fa576cd, 0x2fec76b1, 

+	0x30327694, 0x30797677, 0x30c0765a, 0x3107763d, 0x314e761f, 0x31967601, 0x31dd75e3, 0x322575c5, 

+	0x326c75a6, 0x32b47588, 0x32fc7569, 0x33447549, 0x338c752a, 0x33d4750a, 0x341c74ea, 0x346474ca, 

+	0x34ac74a9, 0x34f57488, 0x353d7467, 0x35857446, 0x35ce7424, 0x36177403, 0x365f73e1, 0x36a873be, 

+	0x36f1739c, 0x373a7379, 0x37837356, 0x37cc7333, 0x3815730f, 0x385e72ec, 0x38a772c8, 0x38f172a3, 

+	0x393a727f, 0x3983725a, 0x39cd7235, 0x3a167210, 0x3a6071ea, 0x3aa971c4, 0x3af3719e, 0x3b3c7178, 

+	0x3b867151, 0x3bd0712b, 0x3c197104, 0x3c6370dc, 0x3cad70b5, 0x3cf7708d, 0x3d407065, 0x3d8a703c, 

+	0x3dd47014, 0x3e1e6feb, 0x3e686fc2, 0x3eb16f98, 0x3efb6f6f, 0x3f456f45, 0x3f8f6f1b, 0x3fd96ef0, 

+	0x40236ec6, 0x406d6e9b, 0x40b66e70, 0x41006e44, 0x414a6e19, 0x41946ded, 0x41de6dc1, 0x42286d94, 

+	0x42716d68, 0x42bb6d3b, 0x43056d0d, 0x434f6ce0, 0x43986cb2, 0x43e26c84, 0x442c6c56, 0x44756c28, 

+	0x44bf6bf9, 0x45086bca, 0x45526b9b, 0x459b6b6b, 0x45e56b3c, 0x462e6b0c, 0x46786adb, 0x46c16aab, 

+	0x470a6a7a, 0x47536a49, 0x479c6a18, 0x47e569e7, 0x482e69b5, 0x48776983, 0x48c06951, 0x4909691e, 

+	0x495268ec, 0x499b68b9, 0x49e36885, 0x4a2c6852, 0x4a74681e, 0x4abd67ea, 0x4b0567b6, 0x4b4d6782, 

+	0x4b95674d, 0x4bde6718, 0x4c2666e3, 0x4c6d66ae, 0x4cb56678, 0x4cfd6642, 0x4d45660c, 0x4d8c65d6, 

+	0x4dd4659f, 0x4e1b6568, 0x4e626531, 0x4ea964fa, 0x4ef064c3, 0x4f37648b, 0x4f7e6453, 0x4fc5641b, 

+	0x500b63e2, 0x505263aa, 0x50986371, 0x50df6338, 0x512562fe, 0x516b62c5, 0x51b1628b, 0x51f66251, 

+	0x523c6217, 0x528161dc, 0x52c761a2, 0x530c6167, 0x5351612c, 0x539660f1, 0x53db60b5, 0x54206079, 

+	0x5464603d, 0x54a96001, 0x54ed5fc5, 0x55315f88, 0x55755f4b, 0x55b95f0e, 0x55fc5ed1, 0x56405e94, 

+	0x56835e56, 0x56c75e18, 0x570a5dda, 0x574d5d9c, 0x578f5d5e, 0x57d25d1f, 0x58145ce0, 0x58565ca1, 

+	0x58995c62, 0x58da5c23, 0x591c5be3, 0x595e5ba4, 0x599f5b64, 0x59e05b24, 0x5a215ae3, 0x5a625aa3
+};
+
+
+/*
+  form factor
+*/
+/* sqrt(((i+(1<<(FF_SQRT_BITS-2)+0.5)/2^31) */
+const Word32 formfac_sqrttable[96] = {
+  0x000407f8, 0x000417b9, 0x0004273f, 0x0004368c, 0x000445a1, 0x00045483, 0x00046332, 0x000471b0,
+  0x00048000, 0x00048e22, 0x00049c1a, 0x0004a9e7, 0x0004b78c, 0x0004c50a, 0x0004d263, 0x0004df96,
+  0x0004eca7, 0x0004f995, 0x00050662, 0x0005130e, 0x00051f9c, 0x00052c0a, 0x0005385b, 0x00054490,
+  0x000550a8, 0x00055ca5, 0x00056888, 0x00057450, 0x00058000, 0x00058b96, 0x00059715, 0x0005a27c,
+  0x0005adcc, 0x0005b906, 0x0005c42b, 0x0005cf39, 0x0005da33, 0x0005e519, 0x0005efea, 0x0005faa8,
+  0x00060552, 0x00060fea, 0x00061a70, 0x000624e3, 0x00062f45, 0x00063996, 0x000643d5, 0x00064e04,
+  0x00065823, 0x00066231, 0x00066c30, 0x0006761f, 0x00068000, 0x000689d1, 0x00069393, 0x00069d47,
+  0x0006a6ed, 0x0006b085, 0x0006ba10, 0x0006c38d, 0x0006ccfc, 0x0006d65f, 0x0006dfb5, 0x0006e8fe,
+  0x0006f23b, 0x0006fb6c, 0x00070490, 0x00070da9, 0x000716b6, 0x00071fb8, 0x000728ae, 0x00073199,
+  0x00073a79, 0x0007434e, 0x00074c19, 0x000754d9, 0x00075d8e, 0x0007663a, 0x00076edb, 0x00077772,
+  0x00078000, 0x00078883, 0x000790fd, 0x0007996e, 0x0007a1d5, 0x0007aa33, 0x0007b288, 0x0007bad4,
+  0x0007c318, 0x0007cb52, 0x0007d384, 0x0007dbad, 0x0007e3ce, 0x0007ebe6, 0x0007f3f6, 0x0007fbfe
+};
+
+
+
+/*!
+  \name    quantizer and inverse quantizer tables
+
+  \brief   these tables are used for the non
+           linear quantizer and inverse quantizer
+           
+*/
+const Word32 mTab_3_4[512] = {
+	0x4c1bf829, 0x4c3880de, 0x4c550603, 0x4c71879c, 
+	0x4c8e05aa, 0x4caa8030, 0x4cc6f72f, 0x4ce36aab, 
+	0x4cffdaa4, 0x4d1c471d, 0x4d38b019, 0x4d55159a, 
+	0x4d7177a1, 0x4d8dd631, 0x4daa314b, 0x4dc688f3, 
+	0x4de2dd2a, 0x4dff2df2, 0x4e1b7b4d, 0x4e37c53d, 
+	0x4e540bc5, 0x4e704ee6, 0x4e8c8ea3, 0x4ea8cafd, 
+	0x4ec503f7, 0x4ee13992, 0x4efd6bd0, 0x4f199ab4, 
+	0x4f35c640, 0x4f51ee75, 0x4f6e1356, 0x4f8a34e4, 
+	0x4fa65321, 0x4fc26e10, 0x4fde85b2, 0x4ffa9a0a, 
+	0x5016ab18, 0x5032b8e0, 0x504ec362, 0x506acaa1, 
+	0x5086cea0, 0x50a2cf5e, 0x50becce0, 0x50dac725, 
+	0x50f6be31, 0x5112b205, 0x512ea2a3, 0x514a900d, 
+	0x51667a45, 0x5182614c, 0x519e4524, 0x51ba25cf, 
+	0x51d60350, 0x51f1dda7, 0x520db4d6, 0x522988e0, 
+	0x524559c6, 0x52612789, 0x527cf22d, 0x5298b9b1, 
+	0x52b47e19, 0x52d03f65, 0x52ebfd98, 0x5307b8b4, 
+	0x532370b9, 0x533f25aa, 0x535ad789, 0x53768656, 
+	0x53923215, 0x53addac6, 0x53c9806b, 0x53e52306, 
+	0x5400c298, 0x541c5f24, 0x5437f8ab, 0x54538f2e, 
+	0x546f22af, 0x548ab330, 0x54a640b3, 0x54c1cb38, 
+	0x54dd52c2, 0x54f8d753, 0x551458eb, 0x552fd78d, 
+	0x554b5339, 0x5566cbf3, 0x558241bb, 0x559db492, 
+	0x55b9247b, 0x55d49177, 0x55effb87, 0x560b62ad, 
+	0x5626c6eb, 0x56422842, 0x565d86b4, 0x5678e242, 
+	0x56943aee, 0x56af90b9, 0x56cae3a4, 0x56e633b2, 
+	0x570180e4, 0x571ccb3b, 0x573812b8, 0x5753575e, 
+	0x576e992e, 0x5789d829, 0x57a51450, 0x57c04da6, 
+	0x57db842b, 0x57f6b7e1, 0x5811e8c9, 0x582d16e6, 
+	0x58484238, 0x58636ac0, 0x587e9081, 0x5899b37c, 
+	0x58b4d3b1, 0x58cff123, 0x58eb0bd3, 0x590623c2, 
+	0x592138f2, 0x593c4b63, 0x59575b19, 0x59726812, 
+	0x598d7253, 0x59a879da, 0x59c37eab, 0x59de80c6, 
+	0x59f9802d, 0x5a147ce0, 0x5a2f76e2, 0x5a4a6e34, 
+	0x5a6562d6, 0x5a8054cb, 0x5a9b4414, 0x5ab630b2, 
+	0x5ad11aa6, 0x5aec01f1, 0x5b06e696, 0x5b21c895, 
+	0x5b3ca7ef, 0x5b5784a6, 0x5b725ebc, 0x5b8d3631, 
+	0x5ba80b06, 0x5bc2dd3e, 0x5bddacd9, 0x5bf879d8, 
+	0x5c13443d, 0x5c2e0c09, 0x5c48d13e, 0x5c6393dc, 
+	0x5c7e53e5, 0x5c99115a, 0x5cb3cc3c, 0x5cce848d, 
+	0x5ce93a4e, 0x5d03ed80, 0x5d1e9e24, 0x5d394c3b, 
+	0x5d53f7c7, 0x5d6ea0c9, 0x5d894742, 0x5da3eb33, 
+	0x5dbe8c9e, 0x5dd92b84, 0x5df3c7e5, 0x5e0e61c3, 
+	0x5e28f920, 0x5e438dfc, 0x5e5e2059, 0x5e78b037, 
+	0x5e933d99, 0x5eadc87e, 0x5ec850e9, 0x5ee2d6da, 
+	0x5efd5a53, 0x5f17db54, 0x5f3259e0, 0x5f4cd5f6, 
+	0x5f674f99, 0x5f81c6c8, 0x5f9c3b87, 0x5fb6add4, 
+	0x5fd11db3, 0x5feb8b23, 0x6005f626, 0x60205ebd, 
+	0x603ac4e9, 0x605528ac, 0x606f8a05, 0x6089e8f7, 
+	0x60a44583, 0x60be9fa9, 0x60d8f76b, 0x60f34cca, 
+	0x610d9fc7, 0x6127f062, 0x61423e9e, 0x615c8a7a, 
+	0x6176d3f9, 0x61911b1b, 0x61ab5fe1, 0x61c5a24d, 
+	0x61dfe25f, 0x61fa2018, 0x62145b7a, 0x622e9485, 
+	0x6248cb3b, 0x6262ff9d, 0x627d31ab, 0x62976167, 
+	0x62b18ed1, 0x62cbb9eb, 0x62e5e2b6, 0x63000933, 
+	0x631a2d62, 0x63344f45, 0x634e6edd, 0x63688c2b, 
+	0x6382a730, 0x639cbfec, 0x63b6d661, 0x63d0ea90, 
+	0x63eafc7a, 0x64050c1f, 0x641f1982, 0x643924a2, 
+	0x64532d80, 0x646d341f, 0x6487387e, 0x64a13a9e, 
+	0x64bb3a81, 0x64d53828, 0x64ef3393, 0x65092cc4, 
+	0x652323bb, 0x653d1879, 0x65570b00, 0x6570fb50, 
+	0x658ae96b, 0x65a4d550, 0x65bebf01, 0x65d8a680, 
+	0x65f28bcc, 0x660c6ee8, 0x66264fd3, 0x66402e8f, 
+	0x665a0b1c, 0x6673e57d, 0x668dbdb0, 0x66a793b8, 
+	0x66c16795, 0x66db3949, 0x66f508d4, 0x670ed636, 
+	0x6728a172, 0x67426a87, 0x675c3177, 0x6775f643, 
+	0x678fb8eb, 0x67a97971, 0x67c337d5, 0x67dcf418, 
+	0x67f6ae3b, 0x6810663f, 0x682a1c25, 0x6843cfed, 
+	0x685d8199, 0x68773129, 0x6890de9f, 0x68aa89fa, 
+	0x68c4333d, 0x68ddda67, 0x68f77f7a, 0x69112277, 
+	0x692ac35e, 0x69446230, 0x695dfeee, 0x6977999a, 
+	0x69913232, 0x69aac8ba, 0x69c45d31, 0x69ddef98, 
+	0x69f77ff0, 0x6a110e3a, 0x6a2a9a77, 0x6a4424a8, 
+	0x6a5daccc, 0x6a7732e6, 0x6a90b6f6, 0x6aaa38fd, 
+	0x6ac3b8fb, 0x6add36f2, 0x6af6b2e2, 0x6b102ccd, 
+	0x6b29a4b2, 0x6b431a92, 0x6b5c8e6f, 0x6b76004a, 
+	0x6b8f7022, 0x6ba8ddf9, 0x6bc249d0, 0x6bdbb3a7, 
+	0x6bf51b80, 0x6c0e815a, 0x6c27e537, 0x6c414718, 
+	0x6c5aa6fd, 0x6c7404e7, 0x6c8d60d7, 0x6ca6bace, 
+	0x6cc012cc, 0x6cd968d2, 0x6cf2bce1, 0x6d0c0ef9, 
+	0x6d255f1d, 0x6d3ead4b, 0x6d57f985, 0x6d7143cc, 
+	0x6d8a8c21, 0x6da3d283, 0x6dbd16f5, 0x6dd65976, 
+	0x6def9a08, 0x6e08d8ab, 0x6e221560, 0x6e3b5027, 
+	0x6e548902, 0x6e6dbff1, 0x6e86f4f5, 0x6ea0280e, 
+	0x6eb9593e, 0x6ed28885, 0x6eebb5e3, 0x6f04e15a, 
+	0x6f1e0aea, 0x6f373294, 0x6f505859, 0x6f697c39, 
+	0x6f829e35, 0x6f9bbe4e, 0x6fb4dc85, 0x6fcdf8d9, 
+	0x6fe7134d, 0x70002be0, 0x70194293, 0x70325767, 
+	0x704b6a5d, 0x70647b76, 0x707d8ab1, 0x70969811, 
+	0x70afa394, 0x70c8ad3d, 0x70e1b50c, 0x70fabb01, 
+	0x7113bf1d, 0x712cc161, 0x7145c1ce, 0x715ec064, 
+	0x7177bd24, 0x7190b80f, 0x71a9b124, 0x71c2a866, 
+	0x71db9dd4, 0x71f49170, 0x720d8339, 0x72267331, 
+	0x723f6159, 0x72584db0, 0x72713838, 0x728a20f1, 
+	0x72a307db, 0x72bbecf9, 0x72d4d049, 0x72edb1ce, 
+	0x73069187, 0x731f6f75, 0x73384b98, 0x735125f3, 
+	0x7369fe84, 0x7382d54d, 0x739baa4e, 0x73b47d89, 
+	0x73cd4efd, 0x73e61eab, 0x73feec94, 0x7417b8b8, 
+	0x74308319, 0x74494bb6, 0x74621291, 0x747ad7aa, 
+	0x74939b02, 0x74ac5c98, 0x74c51c6f, 0x74ddda86, 
+	0x74f696de, 0x750f5178, 0x75280a54, 0x7540c174, 
+	0x755976d7, 0x75722a7e, 0x758adc69, 0x75a38c9b, 
+	0x75bc3b12, 0x75d4e7cf, 0x75ed92d4, 0x76063c21, 
+	0x761ee3b6, 0x76378994, 0x76502dbc, 0x7668d02e, 
+	0x768170eb, 0x769a0ff3, 0x76b2ad47, 0x76cb48e7, 
+	0x76e3e2d5, 0x76fc7b10, 0x7715119a, 0x772da673, 
+	0x7746399b, 0x775ecb13, 0x77775adc, 0x778fe8f6, 
+	0x77a87561, 0x77c1001f, 0x77d98930, 0x77f21095, 
+	0x780a964d, 0x78231a5b, 0x783b9cbd, 0x78541d75, 
+	0x786c9c84, 0x788519e9, 0x789d95a6, 0x78b60fbb, 
+	0x78ce8828, 0x78e6feef, 0x78ff740f, 0x7917e78a, 
+	0x7930595f, 0x7948c990, 0x7961381d, 0x7979a506, 
+	0x7992104c, 0x79aa79f0, 0x79c2e1f1, 0x79db4852, 
+	0x79f3ad11, 0x7a0c1031, 0x7a2471b0, 0x7a3cd191, 
+	0x7a552fd3, 0x7a6d8c76, 0x7a85e77d, 0x7a9e40e6, 
+	0x7ab698b2, 0x7aceeee3, 0x7ae74378, 0x7aff9673, 
+	0x7b17e7d2, 0x7b303799, 0x7b4885c5, 0x7b60d259, 
+	0x7b791d55, 0x7b9166b9, 0x7ba9ae86, 0x7bc1f4bc, 
+	0x7bda395c, 0x7bf27c66, 0x7c0abddb, 0x7c22fdbb, 
+	0x7c3b3c07, 0x7c5378c0, 0x7c6bb3e5, 0x7c83ed78, 
+	0x7c9c2579, 0x7cb45be9, 0x7ccc90c7, 0x7ce4c414, 
+	0x7cfcf5d2, 0x7d152600, 0x7d2d549f, 0x7d4581b0, 
+	0x7d5dad32, 0x7d75d727, 0x7d8dff8f, 0x7da6266a, 
+	0x7dbe4bba, 0x7dd66f7d, 0x7dee91b6, 0x7e06b264, 
+	0x7e1ed188, 0x7e36ef22, 0x7e4f0b34, 0x7e6725bd, 
+	0x7e7f3ebd, 0x7e975636, 0x7eaf6c28, 0x7ec78093, 
+	0x7edf9378, 0x7ef7a4d7, 0x7f0fb4b1, 0x7f27c307, 
+	0x7f3fcfd8, 0x7f57db25, 0x7f6fe4ef, 0x7f87ed36, 
+	0x7f9ff3fb, 0x7fb7f93e, 0x7fcffcff, 0x7fe7ff40
+};
+
+const Word32 mTab_4_3[512]={
+	0x32cbfd4a, 0x32eddd70, 0x330fc339, 0x3331aea3, 
+	0x33539fac, 0x33759652, 0x33979294, 0x33b99470, 
+	0x33db9be4, 0x33fda8ed, 0x341fbb8b, 0x3441d3bb, 
+	0x3463f17c, 0x348614cc, 0x34a83da8, 0x34ca6c10, 
+	0x34eca001, 0x350ed979, 0x35311877, 0x35535cfa, 
+	0x3575a6fe, 0x3597f683, 0x35ba4b87, 0x35dca607, 
+	0x35ff0603, 0x36216b78, 0x3643d665, 0x366646c7, 
+	0x3688bc9e, 0x36ab37e8, 0x36cdb8a2, 0x36f03ecb, 
+	0x3712ca62, 0x37355b64, 0x3757f1d1, 0x377a8da5, 
+	0x379d2ee0, 0x37bfd580, 0x37e28184, 0x380532e8, 
+	0x3827e9ad, 0x384aa5d0, 0x386d674f, 0x38902e2a, 
+	0x38b2fa5d, 0x38d5cbe9, 0x38f8a2ca, 0x391b7eff, 
+	0x393e6088, 0x39614761, 0x3984338a, 0x39a72501, 
+	0x39ca1bc4, 0x39ed17d1, 0x3a101928, 0x3a331fc6, 
+	0x3a562baa, 0x3a793cd2, 0x3a9c533d, 0x3abf6ee9, 
+	0x3ae28fd5, 0x3b05b5ff, 0x3b28e165, 0x3b4c1206, 
+	0x3b6f47e0, 0x3b9282f2, 0x3bb5c33a, 0x3bd908b7, 
+	0x3bfc5368, 0x3c1fa349, 0x3c42f85b, 0x3c66529c, 
+	0x3c89b209, 0x3cad16a2, 0x3cd08065, 0x3cf3ef51, 
+	0x3d176364, 0x3d3adc9c, 0x3d5e5af8, 0x3d81de77, 
+	0x3da56717, 0x3dc8f4d6, 0x3dec87b4, 0x3e101fae, 
+	0x3e33bcc3, 0x3e575ef2, 0x3e7b063a, 0x3e9eb298, 
+	0x3ec2640c, 0x3ee61a93, 0x3f09d62d, 0x3f2d96d8, 
+	0x3f515c93, 0x3f75275b, 0x3f98f731, 0x3fbccc11, 
+	0x3fe0a5fc, 0x400484ef, 0x402868ea, 0x404c51e9, 
+	0x40703fee, 0x409432f5, 0x40b82afd, 0x40dc2806, 
+	0x41002a0d, 0x41243111, 0x41483d12, 0x416c4e0d, 
+	0x41906401, 0x41b47eed, 0x41d89ecf, 0x41fcc3a7, 
+	0x4220ed72, 0x42451c30, 0x42694fde, 0x428d887d, 
+	0x42b1c609, 0x42d60883, 0x42fa4fe8, 0x431e9c37, 
+	0x4342ed70, 0x43674390, 0x438b9e96, 0x43affe82, 
+	0x43d46351, 0x43f8cd03, 0x441d3b95, 0x4441af08, 
+	0x44662758, 0x448aa487, 0x44af2690, 0x44d3ad75, 
+	0x44f83933, 0x451cc9c8, 0x45415f35, 0x4565f977, 
+	0x458a988d, 0x45af3c76, 0x45d3e531, 0x45f892bc, 
+	0x461d4516, 0x4641fc3e, 0x4666b832, 0x468b78f2, 
+	0x46b03e7c, 0x46d508cf, 0x46f9d7e9, 0x471eabca, 
+	0x47438470, 0x476861d9, 0x478d4406, 0x47b22af3, 
+	0x47d716a1, 0x47fc070e, 0x4820fc39, 0x4845f620, 
+	0x486af4c3, 0x488ff820, 0x48b50035, 0x48da0d03, 
+	0x48ff1e87, 0x492434c0, 0x49494fad, 0x496e6f4d, 
+	0x4993939f, 0x49b8bca2, 0x49ddea54, 0x4a031cb4, 
+	0x4a2853c1, 0x4a4d8f7a, 0x4a72cfde, 0x4a9814eb, 
+	0x4abd5ea1, 0x4ae2acfd, 0x4b080000, 0x4b2d57a8, 
+	0x4b52b3f3, 0x4b7814e1, 0x4b9d7a70, 0x4bc2e49f, 
+	0x4be8536e, 0x4c0dc6db, 0x4c333ee4, 0x4c58bb89, 
+	0x4c7e3cc9, 0x4ca3c2a2, 0x4cc94d14, 0x4ceedc1c, 
+	0x4d146fbb, 0x4d3a07ef, 0x4d5fa4b6, 0x4d854611, 
+	0x4daaebfd, 0x4dd09679, 0x4df64585, 0x4e1bf91f, 
+	0x4e41b146, 0x4e676dfa, 0x4e8d2f38, 0x4eb2f501, 
+	0x4ed8bf52, 0x4efe8e2b, 0x4f24618a, 0x4f4a3970, 
+	0x4f7015d9, 0x4f95f6c6, 0x4fbbdc36, 0x4fe1c626, 
+	0x5007b497, 0x502da787, 0x50539ef5, 0x50799ae1, 
+	0x509f9b48, 0x50c5a02a, 0x50eba985, 0x5111b75a, 
+	0x5137c9a6, 0x515de069, 0x5183fba2, 0x51aa1b4f, 
+	0x51d03f70, 0x51f66803, 0x521c9508, 0x5242c67d, 
+	0x5268fc62, 0x528f36b5, 0x52b57575, 0x52dbb8a2, 
+	0x5302003a, 0x53284c3c, 0x534e9ca8, 0x5374f17c, 
+	0x539b4ab7, 0x53c1a858, 0x53e80a5f, 0x540e70ca, 
+	0x5434db98, 0x545b4ac8, 0x5481be5a, 0x54a8364b, 
+	0x54ceb29c, 0x54f5334c, 0x551bb858, 0x554241c1, 
+	0x5568cf85, 0x558f61a3, 0x55b5f81b, 0x55dc92eb, 
+	0x56033212, 0x5629d590, 0x56507d63, 0x5677298a, 
+	0x569dda05, 0x56c48ed3, 0x56eb47f2, 0x57120562, 
+	0x5738c721, 0x575f8d2f, 0x5786578a, 0x57ad2633, 
+	0x57d3f927, 0x57fad066, 0x5821abef, 0x58488bc0, 
+	0x586f6fda, 0x5896583b, 0x58bd44e2, 0x58e435ce, 
+	0x590b2aff, 0x59322473, 0x59592229, 0x59802420, 
+	0x59a72a59, 0x59ce34d0, 0x59f54387, 0x5a1c567b, 
+	0x5a436dac, 0x5a6a8919, 0x5a91a8c1, 0x5ab8cca3, 
+	0x5adff4be, 0x5b072111, 0x5b2e519c, 0x5b55865e, 
+	0x5b7cbf54, 0x5ba3fc80, 0x5bcb3ddf, 0x5bf28371, 
+	0x5c19cd35, 0x5c411b2a, 0x5c686d4f, 0x5c8fc3a4, 
+	0x5cb71e27, 0x5cde7cd7, 0x5d05dfb4, 0x5d2d46bd, 
+	0x5d54b1f0, 0x5d7c214e, 0x5da394d4, 0x5dcb0c83, 
+	0x5df28859, 0x5e1a0856, 0x5e418c78, 0x5e6914be, 
+	0x5e90a129, 0x5eb831b7, 0x5edfc667, 0x5f075f38, 
+	0x5f2efc29, 0x5f569d3a, 0x5f7e426a, 0x5fa5ebb7, 
+	0x5fcd9921, 0x5ff54aa8, 0x601d004a, 0x6044ba06, 
+	0x606c77dc, 0x609439ca, 0x60bbffd0, 0x60e3c9ee, 
+	0x610b9821, 0x61336a6a, 0x615b40c8, 0x61831b39, 
+	0x61aaf9bd, 0x61d2dc53, 0x61fac2fa, 0x6222adb2, 
+	0x624a9c79, 0x62728f4f, 0x629a8633, 0x62c28123, 
+	0x62ea8020, 0x63128329, 0x633a8a3c, 0x63629559, 
+	0x638aa47f, 0x63b2b7ad, 0x63dacee2, 0x6402ea1e, 
+	0x642b0960, 0x64532ca6, 0x647b53f1, 0x64a37f3f, 
+	0x64cbae8f, 0x64f3e1e2, 0x651c1935, 0x65445488, 
+	0x656c93db, 0x6594d72c, 0x65bd1e7b, 0x65e569c7, 
+	0x660db90f, 0x66360c53, 0x665e6391, 0x6686bec9, 
+	0x66af1dfa, 0x66d78123, 0x66ffe844, 0x6728535b, 
+	0x6750c268, 0x6779356b, 0x67a1ac62, 0x67ca274c, 
+	0x67f2a629, 0x681b28f9, 0x6843afb9, 0x686c3a6a, 
+	0x6894c90b, 0x68bd5b9b, 0x68e5f219, 0x690e8c84, 
+	0x69372add, 0x695fcd21, 0x69887350, 0x69b11d6a, 
+	0x69d9cb6d, 0x6a027d5a, 0x6a2b332f, 0x6a53eceb, 
+	0x6a7caa8d, 0x6aa56c16, 0x6ace3184, 0x6af6fad6, 
+	0x6b1fc80c, 0x6b489925, 0x6b716e20, 0x6b9a46fd, 
+	0x6bc323bb, 0x6bec0458, 0x6c14e8d5, 0x6c3dd130, 
+	0x6c66bd69, 0x6c8fad80, 0x6cb8a172, 0x6ce19940, 
+	0x6d0a94e9, 0x6d33946d, 0x6d5c97ca, 0x6d859eff, 
+	0x6daeaa0d, 0x6dd7b8f1, 0x6e00cbad, 0x6e29e23e, 
+	0x6e52fca4, 0x6e7c1adf, 0x6ea53cee, 0x6ece62cf, 
+	0x6ef78c83, 0x6f20ba09, 0x6f49eb5f, 0x6f732085, 
+	0x6f9c597b, 0x6fc59640, 0x6feed6d3, 0x70181b33, 
+	0x70416360, 0x706aaf59, 0x7093ff1d, 0x70bd52ab, 
+	0x70e6aa04, 0x71100525, 0x7139640f, 0x7162c6c1, 
+	0x718c2d3a, 0x71b5977a, 0x71df057f, 0x72087749, 
+	0x7231ecd8, 0x725b662a, 0x7284e33f, 0x72ae6417, 
+	0x72d7e8b0, 0x7301710a, 0x732afd24, 0x73548cfe, 
+	0x737e2097, 0x73a7b7ee, 0x73d15303, 0x73faf1d5, 
+	0x74249462, 0x744e3aac, 0x7477e4b0, 0x74a1926e, 
+	0x74cb43e6, 0x74f4f917, 0x751eb201, 0x75486ea1, 
+	0x75722ef9, 0x759bf307, 0x75c5baca, 0x75ef8642, 
+	0x7619556f, 0x7643284f, 0x766cfee2, 0x7696d928, 
+	0x76c0b71f, 0x76ea98c7, 0x77147e20, 0x773e6728, 
+	0x776853df, 0x77924445, 0x77bc3858, 0x77e63019, 
+	0x78102b85, 0x783a2a9e, 0x78642d62, 0x788e33d1, 
+	0x78b83de9, 0x78e24bab, 0x790c5d15, 0x79367228, 
+	0x79608ae1, 0x798aa742, 0x79b4c748, 0x79deeaf4, 
+	0x7a091245, 0x7a333d3a, 0x7a5d6bd2, 0x7a879e0e, 
+	0x7ab1d3ec, 0x7adc0d6b, 0x7b064a8c, 0x7b308b4d, 
+	0x7b5acfae, 0x7b8517ae, 0x7baf634c, 0x7bd9b289, 
+	0x7c040563, 0x7c2e5bda, 0x7c58b5ec, 0x7c83139b, 
+	0x7cad74e4, 0x7cd7d9c7, 0x7d024244, 0x7d2cae5a, 
+	0x7d571e09, 0x7d81914f, 0x7dac082d, 0x7dd682a1, 
+	0x7e0100ac, 0x7e2b824b, 0x7e560780, 0x7e809048, 
+	0x7eab1ca5, 0x7ed5ac94, 0x7f004015, 0x7f2ad729, 
+	0x7f5571cd, 0x7f801003, 0x7faab1c8, 0x7fd5571d
+};
+
+

+const Word32 invSBF[24] = {

+  0x3FFD34FC, 0x2D3F8000, 0x24F18C7E, 0x1FFE9A7E, 

+  0x1C9DF10C, 0x1A1F851A, 0x182FE994, 0x169FC000, 

+  0x15542AAA, 0x143C31C2, 0x134B1B6C, 0x127920BE, 

+  0x11BF2FCC, 0x111A749E, 0x1085FC42, 0x0FFFA7BE, 

+  0x0F855818, 0x0F14EE56, 0x0EAE6A78, 0x0E4EF886, 

+  0x0DF69880, 0x0DA49568, 0x0D578542, 0x0D101D0C

+};

+
+const Word16 pow2tominusNover16[17] = {
+  0x7fff, 0x7a93, 0x7560, 0x7066,
+  0x6ba2, 0x6712, 0x62b4, 0x5e84,
+  0x5a82, 0x56ac, 0x52ff, 0x4f7b,
+  0x4c1c, 0x48e2, 0x45cb, 0x42d5,
+  0x4000
+};

+

+const Word16 sideInfoTabLong[MAX_SFB_LONG + 1] = {

+  9, 9, 9, 9, 9, 9, 9, 9, 9, 

+  9, 9, 9, 9, 9, 9, 9, 9, 9, 

+  9, 9, 9, 9, 9, 9, 9, 9, 9, 

+  9, 9, 9, 9, 14, 14, 14, 14, 

+  14, 14, 14, 14, 14, 14, 14, 

+  14, 14, 14, 14, 14, 14, 14, 

+  14, 14, 14

+};

+

+const Word16 sideInfoTabShort[MAX_SFB_SHORT + 1] = {

+  7, 7, 7, 7, 7, 7, 7, 10, 10, 

+  10, 10, 10, 10, 10, 13, 13

+};
+
+Word32 specExpMantTableComb_enc[4][14] =
+{
+  {0x40000000,  0x50a28be6,  0x6597fa95,  0x40000000, 
+   0x50a28be6,  0x6597fa95,  0x40000000,  0x50a28be6, 
+   0x6597fa95,  0x40000000,  0x50a28be6,  0x6597fa95, 
+   0x40000000,  0x50a28be6}, 
+
+  {0x4c1bf829,  0x5fe4435e,  0x78d0df9c,  0x4c1bf829, 
+   0x5fe4435e,  0x78d0df9c,  0x4c1bf829,  0x5fe4435e, 
+   0x78d0df9c,  0x4c1bf829,  0x5fe4435e,  0x78d0df9c, 
+   0x4c1bf829,  0x5fe4435e}, 
+
+  {0x5a82799a,  0x7208f81d,  0x47d66b0f,  0x5a82799a, 
+   0x7208f81d,  0x47d66b0f,  0x5a82799a,  0x7208f81d, 
+   0x47d66b0f,  0x5a82799a,  0x7208f81d,  0x47d66b0f, 
+   0x5a82799a,  0x7208f81d}, 
+
+  {0x6ba27e65,  0x43ce3e4b,  0x556e0424,  0x6ba27e65, 
+   0x43ce3e4b,  0x556e0424,  0x6ba27e65,  0x43ce3e4b, 
+   0x556e0424,  0x6ba27e65,  0x43ce3e4b,  0x556e0424, 
+   0x6ba27e65,  0x43ce3e4b}
+};
+
+const  UWord8 specExpTableComb_enc[4][14] =
+{
+  {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18},
+  {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18},
+  {1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18},
+  {1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19}
+};
+
+const Word16 quantBorders[4][4] = {

+  /* pow(1.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */

+  {0x0400, 0x0ee7, 0x1c86, 0x2c0d},

+  /* pow(2.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */

+  {0x04c2, 0x11b9, 0x21eb, 0x3463},

+  /* pow(3.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */

+  {0x05a8, 0x1514, 0x2856, 0x3e4c},

+  /* pow(4.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */

+  {0x06ba, 0x1911, 0x2ff8, 0x4a16},

+};

+
+const Word16 quantRecon[4][3] = {

+  {0x0800, 0x1429, 0x229d},

+  {0x0983, 0x17f9, 0x292a},

+  {0x0b50, 0x1c82, 0x30f4},

+  {0x0d74, 0x21e7, 0x3a37},

+};
+
+const int sampRateTab[NUM_SAMPLE_RATES] = {

+    96000, 88200, 64000, 48000, 44100, 32000, 

+	24000, 22050, 16000, 12000, 11025,  8000

+};
+
+
+const int	rates[8] = {		

+	160, 240, 320, 400, 480, 560, 640, 0

+};

+
+const int BandwithCoefTab[8][NUM_SAMPLE_RATES] = {
+	{ 7000,  7000,  4666,  3500,  3500,  2800,  2800,  2800,  2800,  2000,  2000,  2000},
+	{12000, 12000,  8000,  6000,  6000,  6000,  4000,  4000,  4000,  3000,  3000,  3000},
+	{18000, 18000, 12000,  9000,  9000,  9000,  7000,  7000,  7000,  5000,  5000,  5000},
+	{20000, 20000, 16000, 12000, 12000, 12000,  9000,  9000,  9000,  6000,  6000,  6000},
+	{20000, 20000, 18666, 14000, 14000, 14000, 10000, 10000, 10000,  7000,  7000,  7000},
+	{20000, 20000, 20000, 16000, 16000, 16000, 12000, 12000, 12000,  8000,  8000,  8000},
+	{20000, 20000, 20000, 20000, 20000, 20000, 15000, 15000, 15000, 10000, 10000, 10000},
+	{20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000}
+};
+
+
+/* total number of scale factor bands in one window */

+const UWord8 sfBandTotalShort[NUM_SAMPLE_RATES] = {

+    12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15

+};

+

+const UWord8 sfBandTotalLong[NUM_SAMPLE_RATES] = {

+    41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40

+};

+

+/* scale factor band tables */

+const int sfBandTabShortOffset[NUM_SAMPLE_RATES] = {0, 0, 0, 13, 13, 13, 28, 28, 44, 44, 44, 60};

+

+const short sfBandTabShort[76] = {

+	/* short block 64, 88, 96 kHz [13]  */

+	0,   4,   8,  12,  16,  20,  24,  32,  40,  48,  64,  92, 128,

+

+	/* short block 32, 44, 48 kHz [15]  */

+	0,   4,   8,  12,  16,  20,  28,  36,  44,  56,  68,  80,  96, 112, 128,

+

+	/* short block 22, 24 kHz [16]  */

+	0,   4,   8,  12,  16,  20,  24,  28,  36,  44,  52,  64,  76,  92, 108, 128,

+

+	/* short block 11, 12, 16 kHz [16] */

+	0,   4,   8,  12,  16,  20,  24,  28,  32,  40,  48,  60,  72,  88, 108, 128,

+

+	/* short block 8 kHz [16] */

+	0,   4,   8,  12,  16,  20,  24,  28,  36,  44,  52,  60,  72,  88, 108, 128

+};

+

+const int sfBandTabLongOffset[NUM_SAMPLE_RATES] = {0, 0, 42, 90, 90, 140, 192, 192, 240, 240, 240, 284};

+

+const short sfBandTabLong[325] = {

+	/* long block 88, 96 kHz [42]  */

+	  0,   4,   8,  12,  16,  20,  24,  28,  32,  36,  40,  44,  48,   52,

+	 56,  64,  72,  80,  88,  96, 108, 120, 132, 144, 156, 172, 188,  212,

+	240, 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024,

+

+	/* long block 64 kHz [48]  */

+	  0,   4,   8,  12,  16,  20,  24,  28,  32,  36,  40,  44,  48,  52,  56,   64,

+	 72,  80,  88, 100, 112, 124, 140, 156, 172, 192, 216, 240, 268, 304, 344,  384,

+	424, 464, 504, 544, 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024,

+

+	/* long block 44, 48 kHz [50] */

+	  0,   4,   8,  12,  16,  20,  24,  28,  32,  36,  40,  48,  56,  64,  72,   80,  88,

+	 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384,  416, 448,

+	480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 1024,

+

+	/* long block 32 kHz [52] */

+	  0,   4,   8,  12,  16,  20,  24,  28,  32,  36,  40,  48,  56,  64,  72,   80,  88,  96,

+	108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416,  448, 480, 512,

+	544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024,

+

+	/* long block 22, 24 kHz [48] */

+	  0,   4,   8,  12,  16,  20,  24,  28,  32,  36,  40,  44,  52,  60,  68,   76,

+	 84,  92, 100, 108, 116, 124, 136, 148, 160, 172, 188, 204, 220, 240, 260,  284,

+	308, 336, 364, 396, 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024,

+

+	/* long block 11, 12, 16 kHz [44] */

+	  0,   8,  16,  24,  32,  40,  48,  56,  64,  72,  80,  88, 100,  112, 124,

+	136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320,  344, 368,

+	396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024,

+

+	/* long block 8 kHz [41]  */

+	  0,  12,  24,  36,  48,  60,  72,  84,  96, 108, 120, 132,  144, 156,

+	172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372,  396, 420,

+	448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024

+};

+
+/*
+  these tables are used only for counting and 
+  are stored in packed format
+*/
+const UWord16 huff_ltab1_2[3][3][3][3]=
+{
+  {
+    {
+      {0x0b09,0x0907,0x0b09},
+      {0x0a08,0x0706,0x0a08},
+      {0x0b09,0x0908,0x0b09}
+    },
+    {
+      {0x0a08,0x0706,0x0a07},
+      {0x0706,0x0505,0x0706},
+      {0x0907,0x0706,0x0a08}
+    },
+    {
+      {0x0b09,0x0907,0x0b08},
+      {0x0908,0x0706,0x0908},
+      {0x0b09,0x0907,0x0b09}
+    }
+  },
+  {
+    {
+      {0x0908,0x0706,0x0907},
+      {0x0706,0x0505,0x0706},
+      {0x0907,0x0706,0x0908}
+    },
+    {
+      {0x0706,0x0505,0x0706},
+      {0x0505,0x0103,0x0505},
+      {0x0706,0x0505,0x0706}
+    },
+    {
+      {0x0908,0x0706,0x0907},
+      {0x0706,0x0505,0x0706},
+      {0x0908,0x0706,0x0908}
+    }
+  },
+  {
+    {
+      {0x0b09,0x0907,0x0b09},
+      {0x0908,0x0706,0x0908},
+      {0x0b08,0x0907,0x0b09}
+    },
+    {
+      {0x0a08,0x0706,0x0907},
+      {0x0706,0x0504,0x0706},
+      {0x0908,0x0706,0x0a07}
+    },
+    {
+      {0x0b09,0x0907,0x0b09},
+      {0x0a07,0x0706,0x0908},
+      {0x0b09,0x0907,0x0b09}
+    }
+  }
+};
+
+
+const UWord16 huff_ltab3_4[3][3][3][3]=
+{
+  {
+    {
+      {0x0104,0x0405,0x0808},
+      {0x0405,0x0504,0x0808},
+      {0x0909,0x0908,0x0a0b}
+    },
+    {
+      {0x0405,0x0605,0x0908},
+      {0x0605,0x0604,0x0908},
+      {0x0908,0x0907,0x0a0a}
+    },
+    {
+      {0x0909,0x0a08,0x0d0b},
+      {0x0908,0x0908,0x0b0a},
+      {0x0b0b,0x0a0a,0x0c0b}
+    }
+  },
+  {
+    {
+      {0x0404,0x0605,0x0a08},
+      {0x0604,0x0704,0x0a08},
+      {0x0a08,0x0a08,0x0c0a}
+    },
+    {
+      {0x0504,0x0704,0x0b08},
+      {0x0604,0x0704,0x0a07},
+      {0x0908,0x0907,0x0b09}
+    },
+    {
+      {0x0908,0x0a08,0x0d0a},
+      {0x0807,0x0907,0x0c09},
+      {0x0a0a,0x0b09,0x0c0a}
+    }
+  },
+  {
+    {
+      {0x0808,0x0a08,0x0f0b},
+      {0x0908,0x0b07,0x0f0a},
+      {0x0d0b,0x0e0a,0x100c}
+    },
+    {
+      {0x0808,0x0a07,0x0e0a},
+      {0x0907,0x0a07,0x0e09},
+      {0x0c0a,0x0c09,0x0f0b}
+    },
+    {
+      {0x0b0b,0x0c0a,0x100c},
+      {0x0a0a,0x0b09,0x0f0b},
+      {0x0c0b,0x0c0a,0x0f0b}
+    }
+  }
+};
+
+const UWord16 huff_ltab5_6[9][9]=
+{
+  {0x0d0b,0x0c0a,0x0b09,0x0b09,0x0a09,0x0b09,0x0b09,0x0c0a,0x0d0b},
+  {0x0c0a,0x0b09,0x0a08,0x0907,0x0807,0x0907,0x0a08,0x0b09,0x0c0a},
+  {0x0c09,0x0a08,0x0906,0x0806,0x0706,0x0806,0x0906,0x0a08,0x0b09},
+  {0x0b09,0x0907,0x0806,0x0504,0x0404,0x0504,0x0806,0x0907,0x0b09},
+  {0x0a09,0x0807,0x0706,0x0404,0x0104,0x0404,0x0706,0x0807,0x0b09},
+  {0x0b09,0x0907,0x0806,0x0504,0x0404,0x0504,0x0806,0x0907,0x0b09},
+  {0x0b09,0x0a08,0x0906,0x0806,0x0706,0x0806,0x0906,0x0a08,0x0b09},
+  {0x0c0a,0x0b09,0x0a08,0x0907,0x0807,0x0907,0x0a07,0x0b08,0x0c0a},
+  {0x0d0b,0x0c0a,0x0c09,0x0b09,0x0a09,0x0a09,0x0b09,0x0c0a,0x0d0b}
+};
+
+const UWord16 huff_ltab7_8[8][8]=
+{
+  {0x0105,0x0304,0x0605,0x0706,0x0807,0x0908,0x0a09,0x0b0a},
+  {0x0304,0x0403,0x0604,0x0705,0x0806,0x0807,0x0907,0x0908},
+  {0x0605,0x0604,0x0704,0x0805,0x0806,0x0907,0x0907,0x0a08},
+  {0x0706,0x0705,0x0805,0x0806,0x0906,0x0907,0x0a08,0x0a08},
+  {0x0807,0x0806,0x0906,0x0906,0x0a07,0x0a07,0x0a08,0x0b09},
+  {0x0908,0x0807,0x0906,0x0907,0x0a07,0x0a08,0x0b08,0x0b0a},
+  {0x0a09,0x0907,0x0907,0x0a08,0x0a08,0x0b08,0x0c09,0x0c09},
+  {0x0b0a,0x0a08,0x0a08,0x0a08,0x0b09,0x0b09,0x0c09,0x0c0a}
+};
+
+const UWord16 huff_ltab9_10[13][13]=
+{
+  {0x0106,0x0305,0x0606,0x0806,0x0907,0x0a08,0x0a09,0x0b0a,0x0b0a,0x0c0a,0x0c0b,0x0d0b,0x0d0c},
+  {0x0305,0x0404,0x0604,0x0705,0x0806,0x0807,0x0907,0x0a08,0x0a08,0x0a09,0x0b0a,0x0c0a,0x0c0b},
+  {0x0606,0x0604,0x0705,0x0805,0x0806,0x0906,0x0a07,0x0a08,0x0a08,0x0b09,0x0c09,0x0c0a,0x0c0a},
+  {0x0806,0x0705,0x0805,0x0905,0x0906,0x0a07,0x0a07,0x0b08,0x0b08,0x0b09,0x0c09,0x0c0a,0x0d0a},
+  {0x0907,0x0806,0x0906,0x0906,0x0a06,0x0a07,0x0b07,0x0b08,0x0b08,0x0c09,0x0c09,0x0c0a,0x0d0a},
+  {0x0a08,0x0907,0x0906,0x0a07,0x0b07,0x0b07,0x0b08,0x0c08,0x0b08,0x0c09,0x0c0a,0x0d0a,0x0d0b},
+  {0x0b09,0x0907,0x0a07,0x0b07,0x0b07,0x0b08,0x0c08,0x0c09,0x0c09,0x0c09,0x0d0a,0x0d0a,0x0d0b},
+  {0x0b09,0x0a08,0x0a08,0x0b08,0x0b08,0x0c08,0x0c09,0x0d09,0x0d09,0x0d0a,0x0d0a,0x0d0b,0x0d0b},
+  {0x0b09,0x0a08,0x0a08,0x0b08,0x0b08,0x0b08,0x0c09,0x0c09,0x0d0a,0x0d0a,0x0e0a,0x0d0b,0x0e0b},
+  {0x0b0a,0x0a09,0x0b09,0x0b09,0x0c09,0x0c09,0x0c09,0x0c0a,0x0d0a,0x0d0a,0x0e0b,0x0e0b,0x0e0c},
+  {0x0c0a,0x0b09,0x0b09,0x0c09,0x0c09,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0e0b,0x0e0b,0x0e0b,0x0f0c},
+  {0x0c0b,0x0b0a,0x0c09,0x0c0a,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0d0b,0x0e0b,0x0e0b,0x0f0b,0x0f0c},
+  {0x0d0b,0x0c0a,0x0c0a,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0d0b,0x0e0b,0x0e0c,0x0e0c,0x0e0c,0x0f0c}
+};
+
+const UWord16 huff_ltab11[17][17]=
+{
+  {0x0004,0x0005,0x0006,0x0007,0x0008,0x0008,0x0009,0x000a,0x000a,0x000a,0x000b,0x000b,0x000c,0x000b,0x000c,0x000c,0x000a},
+  {0x0005,0x0004,0x0005,0x0006,0x0007,0x0007,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000b,0x0008},
+  {0x0006,0x0005,0x0005,0x0006,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008},
+  {0x0007,0x0006,0x0006,0x0006,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008},
+  {0x0008,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008},
+  {0x0008,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008},
+  {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x0008},
+  {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x0008},
+  {0x000a,0x0009,0x0008,0x0008,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x0008},
+  {0x000a,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x0008},
+  {0x000b,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000a,0x000b,0x000b,0x0008},
+  {0x000b,0x000a,0x0009,0x0009,0x000a,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x0008},
+  {0x000b,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009},
+  {0x000b,0x000a,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009},
+  {0x000b,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009},
+  {0x000c,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x000c,0x000c,0x0009},
+  {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0005}
+};
+
+const UWord16 huff_ltabscf[121]=
+{
+  0x0012,
+  0x0012,
+  0x0012,
+  0x0012,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0012,
+  0x0013,
+  0x0012,
+  0x0011,
+  0x0011,
+  0x0010,
+  0x0011,
+  0x0010,
+  0x0010,
+  0x0010,
+  0x0010,
+  0x000f,
+  0x000f,
+  0x000e,
+  0x000e,
+  0x000e,
+  0x000e,
+  0x000e,
+  0x000e,
+  0x000d,
+  0x000d,
+  0x000c,
+  0x000c,
+  0x000c,
+  0x000b,
+  0x000c,
+  0x000b,
+  0x000a,
+  0x000a,
+  0x000a,
+  0x0009,
+  0x0009,
+  0x0008,
+  0x0008,
+  0x0008,
+  0x0007,
+  0x0006,
+  0x0006,
+  0x0005,
+  0x0004,
+  0x0003,
+  0x0001,
+  0x0004,
+  0x0004,
+  0x0005,
+  0x0006,
+  0x0006,
+  0x0007,
+  0x0007,
+  0x0008,
+  0x0008,
+  0x0009,
+  0x0009,
+  0x000a,
+  0x000a,
+  0x000a,
+  0x000b,
+  0x000b,
+  0x000b,
+  0x000b,
+  0x000c,
+  0x000c,
+  0x000d,
+  0x000d,
+  0x000d,
+  0x000e,
+  0x000e,
+  0x0010,
+  0x000f,
+  0x0010,
+  0x000f,
+  0x0012,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013,
+  0x0013
+};
+
+
+const UWord16 huff_ctab1[3][3][3][3]=
+{
+  {
+    {
+      {0x07f8,0x01f1,0x07fd},
+      {0x03f5,0x0068,0x03f0},
+      {0x07f7,0x01ec,0x07f5}
+    },
+    {
+      {0x03f1,0x0072,0x03f4},
+      {0x0074,0x0011,0x0076},
+      {0x01eb,0x006c,0x03f6}
+    },
+    {
+      {0x07fc,0x01e1,0x07f1},
+      {0x01f0,0x0061,0x01f6},
+      {0x07f2,0x01ea,0x07fb}
+    }
+  },
+  {
+    {
+      {0x01f2,0x0069,0x01ed},
+      {0x0077,0x0017,0x006f},
+      {0x01e6,0x0064,0x01e5}
+    },
+    {
+      {0x0067,0x0015,0x0062},
+      {0x0012,0x0000,0x0014},
+      {0x0065,0x0016,0x006d}
+    },
+    {
+      {0x01e9,0x0063,0x01e4},
+      {0x006b,0x0013,0x0071},
+      {0x01e3,0x0070,0x01f3}
+    }
+  },
+  {
+    {
+      {0x07fe,0x01e7,0x07f3},
+      {0x01ef,0x0060,0x01ee},
+      {0x07f0,0x01e2,0x07fa}
+    },
+    {
+      {0x03f3,0x006a,0x01e8},
+      {0x0075,0x0010,0x0073},
+      {0x01f4,0x006e,0x03f7}
+    },
+    {
+      {0x07f6,0x01e0,0x07f9},
+      {0x03f2,0x0066,0x01f5},
+      {0x07ff,0x01f7,0x07f4}
+    }
+  }
+};
+
+const UWord16 huff_ctab2[3][3][3][3]=
+{
+  {
+    {
+      {0x01f3,0x006f,0x01fd},
+      {0x00eb,0x0023,0x00ea},
+      {0x01f7,0x00e8,0x01fa}
+    },
+    {
+      {0x00f2,0x002d,0x0070},
+      {0x0020,0x0006,0x002b},
+      {0x006e,0x0028,0x00e9}
+    },
+    {
+      {0x01f9,0x0066,0x00f8},
+      {0x00e7,0x001b,0x00f1},
+      {0x01f4,0x006b,0x01f5}
+    }
+  },
+  {
+    {
+      {0x00ec,0x002a,0x006c},
+      {0x002c,0x000a,0x0027},
+      {0x0067,0x001a,0x00f5}
+    },
+    {
+      {0x0024,0x0008,0x001f},
+      {0x0009,0x0000,0x0007},
+      {0x001d,0x000b,0x0030}
+    },
+    {
+      {0x00ef,0x001c,0x0064},
+      {0x001e,0x000c,0x0029},
+      {0x00f3,0x002f,0x00f0}
+    }
+  },
+  {
+    {
+      {0x01fc,0x0071,0x01f2},
+      {0x00f4,0x0021,0x00e6},
+      {0x00f7,0x0068,0x01f8}
+    },
+    {
+      {0x00ee,0x0022,0x0065},
+      {0x0031,0x0002,0x0026},
+      {0x00ed,0x0025,0x006a}
+    },
+    {
+      {0x01fb,0x0072,0x01fe},
+      {0x0069,0x002e,0x00f6},
+      {0x01ff,0x006d,0x01f6}
+    }
+  }
+};
+
+const UWord16 huff_ctab3[3][3][3][3]=
+{
+  {
+    {
+      {0x0000,0x0009,0x00ef},
+      {0x000b,0x0019,0x00f0},
+      {0x01eb,0x01e6,0x03f2}
+    },
+    {
+      {0x000a,0x0035,0x01ef},
+      {0x0034,0x0037,0x01e9},
+      {0x01ed,0x01e7,0x03f3}
+    },
+    {
+      {0x01ee,0x03ed,0x1ffa},
+      {0x01ec,0x01f2,0x07f9},
+      {0x07f8,0x03f8,0x0ff8}
+    }
+  },
+  {
+    {
+      {0x0008,0x0038,0x03f6},
+      {0x0036,0x0075,0x03f1},
+      {0x03eb,0x03ec,0x0ff4}
+    },
+    {
+      {0x0018,0x0076,0x07f4},
+      {0x0039,0x0074,0x03ef},
+      {0x01f3,0x01f4,0x07f6}
+    },
+    {
+      {0x01e8,0x03ea,0x1ffc},
+      {0x00f2,0x01f1,0x0ffb},
+      {0x03f5,0x07f3,0x0ffc}
+    }
+  },
+  {
+    {
+      {0x00ee,0x03f7,0x7ffe},
+      {0x01f0,0x07f5,0x7ffd},
+      {0x1ffb,0x3ffa,0xffff}
+    },
+    {
+      {0x00f1,0x03f0,0x3ffc},
+      {0x01ea,0x03ee,0x3ffb},
+      {0x0ff6,0x0ffa,0x7ffc}
+    },
+    {
+      {0x07f2,0x0ff5,0xfffe},
+      {0x03f4,0x07f7,0x7ffb},
+      {0x0ff7,0x0ff9,0x7ffa}
+    }
+  }
+};
+
+const UWord16 huff_ctab4[3][3][3][3]=
+{
+  {
+    {
+      {0x0007,0x0016,0x00f6},
+      {0x0018,0x0008,0x00ef},
+      {0x01ef,0x00f3,0x07f8}
+    },
+    {
+      {0x0019,0x0017,0x00ed},
+      {0x0015,0x0001,0x00e2},
+      {0x00f0,0x0070,0x03f0}
+    },
+    {
+      {0x01ee,0x00f1,0x07fa},
+      {0x00ee,0x00e4,0x03f2},
+      {0x07f6,0x03ef,0x07fd}
+    }
+  },
+  {
+    {
+      {0x0005,0x0014,0x00f2},
+      {0x0009,0x0004,0x00e5},
+      {0x00f4,0x00e8,0x03f4}
+    },
+    {
+      {0x0006,0x0002,0x00e7},
+      {0x0003,0x0000,0x006b},
+      {0x00e3,0x0069,0x01f3}
+    },
+    {
+      {0x00eb,0x00e6,0x03f6},
+      {0x006e,0x006a,0x01f4},
+      {0x03ec,0x01f0,0x03f9}
+    }
+  },
+  {
+    {
+      {0x00f5,0x00ec,0x07fb},
+      {0x00ea,0x006f,0x03f7},
+      {0x07f9,0x03f3,0x0fff}
+    },
+    {
+      {0x00e9,0x006d,0x03f8},
+      {0x006c,0x0068,0x01f5},
+      {0x03ee,0x01f2,0x07f4}
+    },
+    {
+      {0x07f7,0x03f1,0x0ffe},
+      {0x03ed,0x01f1,0x07f5},
+      {0x07fe,0x03f5,0x07fc}
+    }
+  }
+};
+const UWord16 huff_ctab5[9][9]=
+{
+  {0x1fff,0x0ff7,0x07f4,0x07e8,0x03f1,0x07ee,0x07f9,0x0ff8,0x1ffd},
+  {0x0ffd,0x07f1,0x03e8,0x01e8,0x00f0,0x01ec,0x03ee,0x07f2,0x0ffa},
+  {0x0ff4,0x03ef,0x01f2,0x00e8,0x0070,0x00ec,0x01f0,0x03ea,0x07f3},
+  {0x07eb,0x01eb,0x00ea,0x001a,0x0008,0x0019,0x00ee,0x01ef,0x07ed},
+  {0x03f0,0x00f2,0x0073,0x000b,0x0000,0x000a,0x0071,0x00f3,0x07e9},
+  {0x07ef,0x01ee,0x00ef,0x0018,0x0009,0x001b,0x00eb,0x01e9,0x07ec},
+  {0x07f6,0x03eb,0x01f3,0x00ed,0x0072,0x00e9,0x01f1,0x03ed,0x07f7},
+  {0x0ff6,0x07f0,0x03e9,0x01ed,0x00f1,0x01ea,0x03ec,0x07f8,0x0ff9},
+  {0x1ffc,0x0ffc,0x0ff5,0x07ea,0x03f3,0x03f2,0x07f5,0x0ffb,0x1ffe}
+};
+
+const UWord16 huff_ctab6[9][9]=
+{
+  {0x07fe,0x03fd,0x01f1,0x01eb,0x01f4,0x01ea,0x01f0,0x03fc,0x07fd},
+  {0x03f6,0x01e5,0x00ea,0x006c,0x0071,0x0068,0x00f0,0x01e6,0x03f7},
+  {0x01f3,0x00ef,0x0032,0x0027,0x0028,0x0026,0x0031,0x00eb,0x01f7},
+  {0x01e8,0x006f,0x002e,0x0008,0x0004,0x0006,0x0029,0x006b,0x01ee},
+  {0x01ef,0x0072,0x002d,0x0002,0x0000,0x0003,0x002f,0x0073,0x01fa},
+  {0x01e7,0x006e,0x002b,0x0007,0x0001,0x0005,0x002c,0x006d,0x01ec},
+  {0x01f9,0x00ee,0x0030,0x0024,0x002a,0x0025,0x0033,0x00ec,0x01f2},
+  {0x03f8,0x01e4,0x00ed,0x006a,0x0070,0x0069,0x0074,0x00f1,0x03fa},
+  {0x07ff,0x03f9,0x01f6,0x01ed,0x01f8,0x01e9,0x01f5,0x03fb,0x07fc}
+};
+
+const UWord16 huff_ctab7[8][8]=
+{
+  {0x0000,0x0005,0x0037,0x0074,0x00f2,0x01eb,0x03ed,0x07f7},
+  {0x0004,0x000c,0x0035,0x0071,0x00ec,0x00ee,0x01ee,0x01f5},
+  {0x0036,0x0034,0x0072,0x00ea,0x00f1,0x01e9,0x01f3,0x03f5},
+  {0x0073,0x0070,0x00eb,0x00f0,0x01f1,0x01f0,0x03ec,0x03fa},
+  {0x00f3,0x00ed,0x01e8,0x01ef,0x03ef,0x03f1,0x03f9,0x07fb},
+  {0x01ed,0x00ef,0x01ea,0x01f2,0x03f3,0x03f8,0x07f9,0x07fc},
+  {0x03ee,0x01ec,0x01f4,0x03f4,0x03f7,0x07f8,0x0ffd,0x0ffe},
+  {0x07f6,0x03f0,0x03f2,0x03f6,0x07fa,0x07fd,0x0ffc,0x0fff}
+};
+
+const UWord16 huff_ctab8[8][8]=
+{
+  {0x000e,0x0005,0x0010,0x0030,0x006f,0x00f1,0x01fa,0x03fe},
+  {0x0003,0x0000,0x0004,0x0012,0x002c,0x006a,0x0075,0x00f8},
+  {0x000f,0x0002,0x0006,0x0014,0x002e,0x0069,0x0072,0x00f5},
+  {0x002f,0x0011,0x0013,0x002a,0x0032,0x006c,0x00ec,0x00fa},
+  {0x0071,0x002b,0x002d,0x0031,0x006d,0x0070,0x00f2,0x01f9},
+  {0x00ef,0x0068,0x0033,0x006b,0x006e,0x00ee,0x00f9,0x03fc},
+  {0x01f8,0x0074,0x0073,0x00ed,0x00f0,0x00f6,0x01f6,0x01fd},
+  {0x03fd,0x00f3,0x00f4,0x00f7,0x01f7,0x01fb,0x01fc,0x03ff}
+};
+
+const UWord16 huff_ctab9[13][13]=
+{
+  {0x0000,0x0005,0x0037,0x00e7,0x01de,0x03ce,0x03d9,0x07c8,0x07cd,0x0fc8,0x0fdd,0x1fe4,0x1fec},
+  {0x0004,0x000c,0x0035,0x0072,0x00ea,0x00ed,0x01e2,0x03d1,0x03d3,0x03e0,0x07d8,0x0fcf,0x0fd5},
+  {0x0036,0x0034,0x0071,0x00e8,0x00ec,0x01e1,0x03cf,0x03dd,0x03db,0x07d0,0x0fc7,0x0fd4,0x0fe4},
+  {0x00e6,0x0070,0x00e9,0x01dd,0x01e3,0x03d2,0x03dc,0x07cc,0x07ca,0x07de,0x0fd8,0x0fea,0x1fdb},
+  {0x01df,0x00eb,0x01dc,0x01e6,0x03d5,0x03de,0x07cb,0x07dd,0x07dc,0x0fcd,0x0fe2,0x0fe7,0x1fe1},
+  {0x03d0,0x01e0,0x01e4,0x03d6,0x07c5,0x07d1,0x07db,0x0fd2,0x07e0,0x0fd9,0x0feb,0x1fe3,0x1fe9},
+  {0x07c4,0x01e5,0x03d7,0x07c6,0x07cf,0x07da,0x0fcb,0x0fda,0x0fe3,0x0fe9,0x1fe6,0x1ff3,0x1ff7},
+  {0x07d3,0x03d8,0x03e1,0x07d4,0x07d9,0x0fd3,0x0fde,0x1fdd,0x1fd9,0x1fe2,0x1fea,0x1ff1,0x1ff6},
+  {0x07d2,0x03d4,0x03da,0x07c7,0x07d7,0x07e2,0x0fce,0x0fdb,0x1fd8,0x1fee,0x3ff0,0x1ff4,0x3ff2},
+  {0x07e1,0x03df,0x07c9,0x07d6,0x0fca,0x0fd0,0x0fe5,0x0fe6,0x1feb,0x1fef,0x3ff3,0x3ff4,0x3ff5},
+  {0x0fe0,0x07ce,0x07d5,0x0fc6,0x0fd1,0x0fe1,0x1fe0,0x1fe8,0x1ff0,0x3ff1,0x3ff8,0x3ff6,0x7ffc},
+  {0x0fe8,0x07df,0x0fc9,0x0fd7,0x0fdc,0x1fdc,0x1fdf,0x1fed,0x1ff5,0x3ff9,0x3ffb,0x7ffd,0x7ffe},
+  {0x1fe7,0x0fcc,0x0fd6,0x0fdf,0x1fde,0x1fda,0x1fe5,0x1ff2,0x3ffa,0x3ff7,0x3ffc,0x3ffd,0x7fff}
+};
+
+const UWord16 huff_ctab10[13][13]=
+{
+  {0x0022,0x0008,0x001d,0x0026,0x005f,0x00d3,0x01cf,0x03d0,0x03d7,0x03ed,0x07f0,0x07f6,0x0ffd},
+  {0x0007,0x0000,0x0001,0x0009,0x0020,0x0054,0x0060,0x00d5,0x00dc,0x01d4,0x03cd,0x03de,0x07e7},
+  {0x001c,0x0002,0x0006,0x000c,0x001e,0x0028,0x005b,0x00cd,0x00d9,0x01ce,0x01dc,0x03d9,0x03f1},
+  {0x0025,0x000b,0x000a,0x000d,0x0024,0x0057,0x0061,0x00cc,0x00dd,0x01cc,0x01de,0x03d3,0x03e7},
+  {0x005d,0x0021,0x001f,0x0023,0x0027,0x0059,0x0064,0x00d8,0x00df,0x01d2,0x01e2,0x03dd,0x03ee},
+  {0x00d1,0x0055,0x0029,0x0056,0x0058,0x0062,0x00ce,0x00e0,0x00e2,0x01da,0x03d4,0x03e3,0x07eb},
+  {0x01c9,0x005e,0x005a,0x005c,0x0063,0x00ca,0x00da,0x01c7,0x01ca,0x01e0,0x03db,0x03e8,0x07ec},
+  {0x01e3,0x00d2,0x00cb,0x00d0,0x00d7,0x00db,0x01c6,0x01d5,0x01d8,0x03ca,0x03da,0x07ea,0x07f1},
+  {0x01e1,0x00d4,0x00cf,0x00d6,0x00de,0x00e1,0x01d0,0x01d6,0x03d1,0x03d5,0x03f2,0x07ee,0x07fb},
+  {0x03e9,0x01cd,0x01c8,0x01cb,0x01d1,0x01d7,0x01df,0x03cf,0x03e0,0x03ef,0x07e6,0x07f8,0x0ffa},
+  {0x03eb,0x01dd,0x01d3,0x01d9,0x01db,0x03d2,0x03cc,0x03dc,0x03ea,0x07ed,0x07f3,0x07f9,0x0ff9},
+  {0x07f2,0x03ce,0x01e4,0x03cb,0x03d8,0x03d6,0x03e2,0x03e5,0x07e8,0x07f4,0x07f5,0x07f7,0x0ffb},
+  {0x07fa,0x03ec,0x03df,0x03e1,0x03e4,0x03e6,0x03f0,0x07e9,0x07ef,0x0ff8,0x0ffe,0x0ffc,0x0fff}
+};
+
+const UWord16 huff_ctab11[17][17]=
+{
+  {0x0000,0x0006,0x0019,0x003d,0x009c,0x00c6,0x01a7,0x0390,0x03c2,0x03df,0x07e6,0x07f3,0x0ffb,0x07ec,0x0ffa,0x0ffe,0x038e},
+  {0x0005,0x0001,0x0008,0x0014,0x0037,0x0042,0x0092,0x00af,0x0191,0x01a5,0x01b5,0x039e,0x03c0,0x03a2,0x03cd,0x07d6,0x00ae},
+  {0x0017,0x0007,0x0009,0x0018,0x0039,0x0040,0x008e,0x00a3,0x00b8,0x0199,0x01ac,0x01c1,0x03b1,0x0396,0x03be,0x03ca,0x009d},
+  {0x003c,0x0015,0x0016,0x001a,0x003b,0x0044,0x0091,0x00a5,0x00be,0x0196,0x01ae,0x01b9,0x03a1,0x0391,0x03a5,0x03d5,0x0094},
+  {0x009a,0x0036,0x0038,0x003a,0x0041,0x008c,0x009b,0x00b0,0x00c3,0x019e,0x01ab,0x01bc,0x039f,0x038f,0x03a9,0x03cf,0x0093},
+  {0x00bf,0x003e,0x003f,0x0043,0x0045,0x009e,0x00a7,0x00b9,0x0194,0x01a2,0x01ba,0x01c3,0x03a6,0x03a7,0x03bb,0x03d4,0x009f},
+  {0x01a0,0x008f,0x008d,0x0090,0x0098,0x00a6,0x00b6,0x00c4,0x019f,0x01af,0x01bf,0x0399,0x03bf,0x03b4,0x03c9,0x03e7,0x00a8},
+  {0x01b6,0x00ab,0x00a4,0x00aa,0x00b2,0x00c2,0x00c5,0x0198,0x01a4,0x01b8,0x038c,0x03a4,0x03c4,0x03c6,0x03dd,0x03e8,0x00ad},
+  {0x03af,0x0192,0x00bd,0x00bc,0x018e,0x0197,0x019a,0x01a3,0x01b1,0x038d,0x0398,0x03b7,0x03d3,0x03d1,0x03db,0x07dd,0x00b4},
+  {0x03de,0x01a9,0x019b,0x019c,0x01a1,0x01aa,0x01ad,0x01b3,0x038b,0x03b2,0x03b8,0x03ce,0x03e1,0x03e0,0x07d2,0x07e5,0x00b7},
+  {0x07e3,0x01bb,0x01a8,0x01a6,0x01b0,0x01b2,0x01b7,0x039b,0x039a,0x03ba,0x03b5,0x03d6,0x07d7,0x03e4,0x07d8,0x07ea,0x00ba},
+  {0x07e8,0x03a0,0x01bd,0x01b4,0x038a,0x01c4,0x0392,0x03aa,0x03b0,0x03bc,0x03d7,0x07d4,0x07dc,0x07db,0x07d5,0x07f0,0x00c1},
+  {0x07fb,0x03c8,0x03a3,0x0395,0x039d,0x03ac,0x03ae,0x03c5,0x03d8,0x03e2,0x03e6,0x07e4,0x07e7,0x07e0,0x07e9,0x07f7,0x0190},
+  {0x07f2,0x0393,0x01be,0x01c0,0x0394,0x0397,0x03ad,0x03c3,0x03c1,0x03d2,0x07da,0x07d9,0x07df,0x07eb,0x07f4,0x07fa,0x0195},
+  {0x07f8,0x03bd,0x039c,0x03ab,0x03a8,0x03b3,0x03b9,0x03d0,0x03e3,0x03e5,0x07e2,0x07de,0x07ed,0x07f1,0x07f9,0x07fc,0x0193},
+  {0x0ffd,0x03dc,0x03b6,0x03c7,0x03cc,0x03cb,0x03d9,0x03da,0x07d3,0x07e1,0x07ee,0x07ef,0x07f5,0x07f6,0x0ffc,0x0fff,0x019d},
+  {0x01c2,0x00b5,0x00a1,0x0096,0x0097,0x0095,0x0099,0x00a0,0x00a2,0x00ac,0x00a9,0x00b1,0x00b3,0x00bb,0x00c0,0x018f,0x0004}
+};
+
+const UWord32 huff_ctabscf[121]=
+{
+  0x0003ffe8,
+  0x0003ffe6,
+  0x0003ffe7,
+  0x0003ffe5,
+  0x0007fff5,
+  0x0007fff1,
+  0x0007ffed,
+  0x0007fff6,
+  0x0007ffee,
+  0x0007ffef,
+  0x0007fff0,
+  0x0007fffc,
+  0x0007fffd,
+  0x0007ffff,
+  0x0007fffe,
+  0x0007fff7,
+  0x0007fff8,
+  0x0007fffb,
+  0x0007fff9,
+  0x0003ffe4,
+  0x0007fffa,
+  0x0003ffe3,
+  0x0001ffef,
+  0x0001fff0,
+  0x0000fff5,
+  0x0001ffee,
+  0x0000fff2,
+  0x0000fff3,
+  0x0000fff4,
+  0x0000fff1,
+  0x00007ff6,
+  0x00007ff7,
+  0x00003ff9,
+  0x00003ff5,
+  0x00003ff7,
+  0x00003ff3,
+  0x00003ff6,
+  0x00003ff2,
+  0x00001ff7,
+  0x00001ff5,
+  0x00000ff9,
+  0x00000ff7,
+  0x00000ff6,
+  0x000007f9,
+  0x00000ff4,
+  0x000007f8,
+  0x000003f9,
+  0x000003f7,
+  0x000003f5,
+  0x000001f8,
+  0x000001f7,
+  0x000000fa,
+  0x000000f8,
+  0x000000f6,
+  0x00000079,
+  0x0000003a,
+  0x00000038,
+  0x0000001a,
+  0x0000000b,
+  0x00000004,
+  0x00000000,
+  0x0000000a,
+  0x0000000c,
+  0x0000001b,
+  0x00000039,
+  0x0000003b,
+  0x00000078,
+  0x0000007a,
+  0x000000f7,
+  0x000000f9,
+  0x000001f6,
+  0x000001f9,
+  0x000003f4,
+  0x000003f6,
+  0x000003f8,
+  0x000007f5,
+  0x000007f4,
+  0x000007f6,
+  0x000007f7,
+  0x00000ff5,
+  0x00000ff8,
+  0x00001ff4,
+  0x00001ff6,
+  0x00001ff8,
+  0x00003ff8,
+  0x00003ff4,
+  0x0000fff0,
+  0x00007ff4,
+  0x0000fff6,
+  0x00007ff5,
+  0x0003ffe2,
+  0x0007ffd9,
+  0x0007ffda,
+  0x0007ffdb,
+  0x0007ffdc,
+  0x0007ffdd,
+  0x0007ffde,
+  0x0007ffd8,
+  0x0007ffd2,
+  0x0007ffd3,
+  0x0007ffd4,
+  0x0007ffd5,
+  0x0007ffd6,
+  0x0007fff2,
+  0x0007ffdf,
+  0x0007ffe7,
+  0x0007ffe8,
+  0x0007ffe9,
+  0x0007ffea,
+  0x0007ffeb,
+  0x0007ffe6,
+  0x0007ffe0,
+  0x0007ffe1,
+  0x0007ffe2,
+  0x0007ffe3,
+  0x0007ffe4,
+  0x0007ffe5,
+  0x0007ffd7,
+  0x0007ffec,
+  0x0007fff4,
+  0x0007fff3
+};
+
+const Word32 m_log2_table[INT_BITS] = {
+  0x00000000,0x4ae00d00,0x2934f080,0x15c01a3f, 
+  0x0b31fb80,0x05aeb4e0,0x02dcf2d0,0x016fe50c, 
+  0x00b84e23,0x005c3e10,0x002e24ca,0x001713d6,
+  0x000b8a47,0x0005c53b,0x0002e2a3,0x00017153,
+  0x0000b8aa,0x00005c55,0x00002e2b,0x00001715,
+  0x00000b8b,0x000005c5,0x000002e3,0x00000171, 
+  0x000000b9,0x0000005c,0x0000002e,0x00000017,
+  0x0000000c,0x00000006,0x00000003,0x00000001
+};
+
+
+/*
+  3 bit resolution
+*/
+const Word32 tnsCoeff3[8] =
+{
+  0x81f1d1d4,
+  0x9126147c,
+  0xadb922f7,
+  0xd438af09,
+  0x00000000,
+  0x37898087,
+  0x64130dfa,
+  0x7cca6ffb,
+};
+
+const Word32 tnsCoeff3Borders[8] =
+{
+  0x80000000,  /* -4 */
+  0x87b826de,  /* -3 */
+  0x9df24153,  /* -2 */
+  0xbfffffe5,  /* -1 */
+  0xe9c5e578,  /*  0 */
+  0x1c7b90f0,  /*  1 */
+  0x4fce83aa,  /*  2 */
+  0x7352f2c4,  /*  3 */
+};
+
+
+/*
+  4 bit resolution
+*/
+
+const Word32 tnsCoeff4[16] =
+{
+  0x808bc84b,
+  0x84e2e57d,
+  0x8d6b49fb,
+  0x99da9207,
+  0xa9c45707,
+  0xbc9dde78,
+  0xd1c2d4fc,
+  0xe87ae539,
+  0x00000000,
+  0x1a9cd9c0,
+  0x340ff23b,
+  0x4b3c8bf7,
+  0x5f1f5e80,
+  0x6ed9eb84,
+  0x79bc3880,
+  0x7f4c7e89
+};
+
+const Word32 tnsCoeff4Borders[16]=
+{
+  0x80000000,  /* -8 */
+  0x822defef,  /* -7 */
+  0x88a4bfe5,  /* -6 */
+  0x932c159c,  /* -5 */
+  0xa16827c1,  /* -4 */
+  0xb2dcde26,  /* -3 */
+  0xc6f20b91,  /* -2 */
+  0xdcf89c64,  /* -1 */
+  0xf4308ce1,  /*  0 */
+  0x0d613054,  /*  1 */
+  0x278dde80,  /*  2 */
+  0x4000001b,  /*  3 */
+  0x55a6127c,  /*  4 */
+  0x678dde8f,  /*  5 */
+  0x74ef0ed8,  /*  6 */
+  0x7d33f0db   /*  7 */
+};
+
+
+const unsigned char bitrevTab[17 + 129] = 

+{

+/* 64 */

+0x01, 0x08, 0x02, 0x04, 0x03, 0x0c, 0x05, 0x0a, 0x07, 0x0e, 0x0b, 0x0d, 0x00, 0x06, 0x09, 0x0f,

+0x00,

+

+/* 512 */

+0x01, 0x40, 0x02, 0x20, 0x03, 0x60, 0x04, 0x10, 0x05, 0x50, 0x06, 0x30, 0x07, 0x70, 0x09, 0x48,

+0x0a, 0x28, 0x0b, 0x68, 0x0c, 0x18, 0x0d, 0x58, 0x0e, 0x38, 0x0f, 0x78, 0x11, 0x44, 0x12, 0x24,

+0x13, 0x64, 0x15, 0x54, 0x16, 0x34, 0x17, 0x74, 0x19, 0x4c, 0x1a, 0x2c, 0x1b, 0x6c, 0x1d, 0x5c,

+0x1e, 0x3c, 0x1f, 0x7c, 0x21, 0x42, 0x23, 0x62, 0x25, 0x52, 0x26, 0x32, 0x27, 0x72, 0x29, 0x4a,

+0x2b, 0x6a, 0x2d, 0x5a, 0x2e, 0x3a, 0x2f, 0x7a, 0x31, 0x46, 0x33, 0x66, 0x35, 0x56, 0x37, 0x76,

+0x39, 0x4e, 0x3b, 0x6e, 0x3d, 0x5e, 0x3f, 0x7e, 0x43, 0x61, 0x45, 0x51, 0x47, 0x71, 0x4b, 0x69,

+0x4d, 0x59, 0x4f, 0x79, 0x53, 0x65, 0x57, 0x75, 0x5b, 0x6d, 0x5f, 0x7d, 0x67, 0x73, 0x6f, 0x7b,

+0x00, 0x08, 0x14, 0x1c, 0x22, 0x2a, 0x36, 0x3e, 0x41, 0x49, 0x55, 0x5d, 0x63, 0x6b, 0x77, 0x7f,

+0x00,

+};
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc.c b/media/libstagefright/codecs/aacenc/src/aacenc.c
new file mode 100644
index 0000000..552ae41
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/aacenc.c
@@ -0,0 +1,495 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		aacenc.c

+

+	Content:	aac encoder interface functions

+

+*******************************************************************************/

+

+#include "voAAC.h"

+#include "typedef.h"

+#include "aacenc_core.h"

+#include "aac_rom.h"

+#include "cmnMemory.h"

+#include "memalign.h"

+

+/**

+* Init the audio codec module and return codec handle

+* \param phCodec [OUT] Return the video codec handle

+* \param vType	[IN] The codec type if the module support multi codec.

+* \param pUserData	[IN] The init param. It is memory operator or alloced memory

+* \retval VO_ERR_NONE Succeeded.

+*/

+VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData)

+{

+	AAC_ENCODER*hAacEnc;

+	AACENC_CONFIG config;

+	int error;

+

+#ifdef USE_DEAULT_MEM

+	VO_MEM_OPERATOR voMemoprator;

+#endif

+	VO_MEM_OPERATOR *pMemOP;

+	int interMem;

+

+	interMem = 0;

+	error = 0;

+	

+	/* init the memory operator */

+	if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )

+	{

+#ifdef USE_DEAULT_MEM

+		voMemoprator.Alloc = cmnMemAlloc;

+		voMemoprator.Copy = cmnMemCopy;

+		voMemoprator.Free = cmnMemFree;

+		voMemoprator.Set = cmnMemSet;

+		voMemoprator.Check = cmnMemCheck;

+

+		interMem = 1;

+

+		pMemOP = &voMemoprator;

+#else

+		*phCodec = NULL;

+		return VO_ERR_INVALID_ARG;

+#endif

+	}

+	else

+	{

+		pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;

+	}

+

+	/* init the aac encoder handle */

+	hAacEnc = (AAC_ENCODER*)mem_malloc(pMemOP, sizeof(AAC_ENCODER), 32, VO_INDEX_ENC_AAC);

+	if(NULL == hAacEnc)

+	{

+		error = 1;

+	}

+

+	if(!error)

+	{

+		/* init the aac encoder intra memory */

+		hAacEnc->intbuf = (short *)mem_malloc(pMemOP, AACENC_BLOCKSIZE*MAX_CHANNELS*sizeof(short), 32, VO_INDEX_ENC_AAC);

+		if(NULL == hAacEnc->intbuf)

+		{

+			error = 1;

+		}

+	}

+

+	if (!error) {
+		/* init the aac encoder psychoacoustic */
+		error = (PsyNew(&hAacEnc->psyKernel, MAX_CHANNELS, pMemOP) ||
+			PsyOutNew(&hAacEnc->psyOut, pMemOP));
+	}

+

+	if (!error) {
+		/* init the aac encoder quantization elements */
+		error = QCOutNew(&hAacEnc->qcOut,MAX_CHANNELS, pMemOP);
+	}

+

+	if (!error) {
+		/* init the aac encoder quantization state */
+		error = QCNew(&hAacEnc->qcKernel, pMemOP);
+	}
+
+	/* uninit the aac encoder if error is nozero */
+	if(error)
+	{
+		AacEncClose(hAacEnc, pMemOP);
+		if(hAacEnc)
+		{
+			mem_free(pMemOP, hAacEnc, VO_INDEX_ENC_AAC);
+			hAacEnc = NULL;
+		}		
+		*phCodec = NULL;
+		return VO_ERR_OUTOF_MEMORY;
+	}

+

+	/* init the aac encoder memory operator  */

+#ifdef USE_DEAULT_MEM

+	if(interMem)

+	{

+		hAacEnc->voMemoprator.Alloc = cmnMemAlloc;

+		hAacEnc->voMemoprator.Copy = cmnMemCopy;

+		hAacEnc->voMemoprator.Free = cmnMemFree;

+		hAacEnc->voMemoprator.Set = cmnMemSet;

+		hAacEnc->voMemoprator.Check = cmnMemCheck;

+

+		pMemOP = &hAacEnc->voMemoprator;

+	}

+#endif

+	/* init the aac encoder default parameter  */

+	if(hAacEnc->initOK == 0)

+	{

+		 AACENC_CONFIG config;

+		 config.adtsUsed = 1;

+		 config.bitRate = 128000;

+		 config.nChannelsIn = 2;

+		 config.nChannelsOut = 2;

+		 config.sampleRate = 44100;

+		 config.bandWidth = 20000;

+

+		 AacEncOpen(hAacEnc, config);

+	}

+

+	hAacEnc->voMemop = pMemOP;

+

+	*phCodec = hAacEnc;

+

+	return VO_ERR_NONE;

+}

+

+/**

+* Set input audio data.

+* \param hCodec [IN]] The Codec Handle which was created by Init function.

+* \param pInput [IN] The input buffer param.

+* \param pOutBuffer [OUT] The output buffer info.

+* \retval VO_ERR_NONE Succeeded.

+*/

+VO_U32 VO_API voAACEncSetInputData(VO_HANDLE hCodec, VO_CODECBUFFER * pInput)

+{

+	AAC_ENCODER *hAacEnc;

+	int  length;

+

+	if(NULL == hCodec || NULL == pInput || NULL == pInput->Buffer)

+	{

+		return VO_ERR_INVALID_ARG;

+	}

+	

+	hAacEnc = (AAC_ENCODER *)hCodec;

+	

+	/* init input pcm buffer and length*/

+	hAacEnc->inbuf = (short *)pInput->Buffer;

+	hAacEnc->inlen = pInput->Length / sizeof(short);

+	hAacEnc->uselength = 0;

+

+	hAacEnc->encbuf = hAacEnc->inbuf;

+	hAacEnc->enclen = hAacEnc->inlen;

+	

+	/* rebuild intra pcm buffer and length*/

+	if(hAacEnc->intlen)

+	{

+		length = min(hAacEnc->config.nChannelsIn*AACENC_BLOCKSIZE - hAacEnc->intlen, hAacEnc->inlen);

+		hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf + hAacEnc->intlen, 

+			hAacEnc->inbuf, length*sizeof(short));

+

+		hAacEnc->encbuf = hAacEnc->intbuf;

+		hAacEnc->enclen = hAacEnc->intlen + length;

+

+		hAacEnc->inbuf += length;

+		hAacEnc->inlen -= length;

+	}

+	

+	return VO_ERR_NONE;

+}

+

+/**

+* Get the outut audio data

+* \param hCodec [IN]] The Codec Handle which was created by Init function.

+* \param pOutBuffer [OUT] The output audio data

+* \param pOutInfo [OUT] The dec module filled audio format and used the input size.

+*						 pOutInfo->InputUsed is total used the input size.

+* \retval  VO_ERR_NONE Succeeded.

+*			VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought.

+*/

+VO_U32 VO_API voAACEncGetOutputData(VO_HANDLE hCodec, VO_CODECBUFFER * pOutput, VO_AUDIO_OUTPUTINFO * pOutInfo)

+{

+	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;

+	Word16 numAncDataBytes=0;

+	Word32  inbuflen;

+	int ret, length;

+	if(NULL == hAacEnc)

+		return VO_ERR_INVALID_ARG;

+

+	 inbuflen = AACENC_BLOCKSIZE*hAacEnc->config.nChannelsIn;

+

+	 /* check the input pcm buffer and length*/

+	 if(NULL == hAacEnc->encbuf || hAacEnc->enclen < inbuflen)

+	 {

+		length = hAacEnc->enclen;		

+		if(hAacEnc->intlen == 0)

+		{	

+			hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf, 

+				hAacEnc->encbuf, length*sizeof(short));		

+			hAacEnc->uselength += length*sizeof(short);

+		}

+		else

+		{

+			hAacEnc->uselength += (length - hAacEnc->intlen)*sizeof(short);

+		}

+

+		hAacEnc->intlen = length;

+

+		pOutput->Length = 0;

+		if(pOutInfo)

+			pOutInfo->InputUsed = hAacEnc->uselength;

+		return VO_ERR_INPUT_BUFFER_SMALL;	

+	 }

+

+	 /* check the output aac buffer and length*/

+	 if(NULL == pOutput || NULL == pOutput->Buffer || pOutput->Length < (6144/8)*hAacEnc->config.nChannelsOut/(sizeof(Word32)))

+		 return VO_ERR_OUTPUT_BUFFER_SMALL;

+

+	 /* aac encoder core function */

+	 AacEncEncode( hAacEnc,

+			(Word16*)hAacEnc->encbuf,

+			NULL,

+			&numAncDataBytes,

+			pOutput->Buffer,

+			&pOutput->Length);

+

+	 /* update the input pcm buffer and length*/

+	 if(hAacEnc->intlen)

+	 {

+		length = inbuflen - hAacEnc->intlen;		

+		hAacEnc->encbuf = hAacEnc->inbuf;

+		hAacEnc->enclen = hAacEnc->inlen;

+		hAacEnc->uselength += length*sizeof(short);

+		hAacEnc->intlen = 0;

+	 }

+	 else

+	 {

+		 hAacEnc->encbuf = hAacEnc->encbuf + inbuflen;

+		 hAacEnc->enclen = hAacEnc->enclen - inbuflen;

+		 hAacEnc->uselength += inbuflen*sizeof(short);

+	 }	 

+

+	 /* update the output aac information */

+	if(pOutInfo)

+	{

+		pOutInfo->Format.Channels = hAacEnc->config.nChannelsOut;

+		pOutInfo->Format.SampleRate = hAacEnc->config.sampleRate;

+		pOutInfo->Format.SampleBits = 16;

+		pOutInfo->InputUsed = hAacEnc->uselength;

+	}

+

+	 return VO_ERR_NONE;

+}

+

+/**

+* Uninit the Codec.

+* \param hCodec [IN]] The Codec Handle which was created by Init function.

+* \retval VO_ERR_NONE Succeeded.

+*/

+VO_U32 VO_API voAACEncUninit(VO_HANDLE hCodec)

+{

+	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;

+	

+	if(NULL != hAacEnc)

+	{

+		/* close the aac encoder */

+		AacEncClose(hAacEnc, hAacEnc->voMemop);

+

+		/* free the aac encoder handle*/

+		mem_free(hAacEnc->voMemop, hAacEnc, VO_INDEX_ENC_AAC);

+		hAacEnc = NULL;

+	}	

+

+	return VO_ERR_NONE;

+}

+

+/**

+* Set the param for special target.

+* \param hCodec [IN]] The Codec Handle which was created by Init function.

+* \param uParamID [IN] The param ID.

+* \param pData [IN] The param value depend on the ID>

+* \retval VO_ERR_NONE Succeeded.

+*/

+VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)

+{

+	AACENC_CONFIG config;

+	AACENC_PARAM* pAAC_param;

+	VO_AUDIO_FORMAT *pWAV_Format;

+	AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;

+	int ret, i, bitrate, tmp;

+	int SampleRateIdx;

+

+	if(NULL == hAacEnc)

+		return VO_ERR_INVALID_ARG;

+	

+	switch(uParamID)

+	{

+	case VO_PID_AAC_ENCPARAM:  /* init aac encoder parameter*/

+		AacInitDefaultConfig(&config);

+		if(pData == NULL)

+			return VO_ERR_INVALID_ARG;

+		pAAC_param = (AACENC_PARAM*)pData;

+		config.adtsUsed = pAAC_param->adtsUsed;

+		config.bitRate = pAAC_param->bitRate;

+		config.nChannelsIn = pAAC_param->nChannels;

+		config.nChannelsOut = pAAC_param->nChannels;

+		config.sampleRate = pAAC_param->sampleRate;

+

+		/* check the channel */

+		if(config.nChannelsIn< 1  || config.nChannelsIn > MAX_CHANNELS  ||

+             config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)

+			 return VO_ERR_AUDIO_UNSCHANNEL;

+

+		/* check the samplerate */

+		ret = -1;

+		for(i = 0; i < NUM_SAMPLE_RATES; i++)

+		{

+			if(config.sampleRate == sampRateTab[i])

+			{

+				ret = 0;

+				break;

+			}

+		}

+		if(ret < 0)

+			return VO_ERR_AUDIO_UNSSAMPLERATE;

+

+		SampleRateIdx = i;

+

+		tmp = 441;

+		if(config.sampleRate%8000 == 0) 

+			tmp =480;

+		/* check the bitrate */

+		if(config.bitRate!=0 && (config.bitRate/config.nChannelsOut < 4000) ||

+           (config.bitRate/config.nChannelsOut > 160000) || 

+		   (config.bitRate > config.sampleRate*6*config.nChannelsOut))

+		{

+			config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;

+

+			if(config.bitRate/config.nChannelsOut < 4000)

+				config.bitRate = 4000 * config.nChannelsOut;

+			else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)

+				config.bitRate = config.sampleRate*6*config.nChannelsOut;

+			else if(config.bitRate/config.nChannelsOut > 160000)

+				config.bitRate = config.nChannelsOut*160000;

+		}

+

+		/* check the bandwidth */

+		bitrate = config.bitRate / config.nChannelsOut;

+		bitrate = bitrate * tmp / config.sampleRate;

+

+		for (i = 0; rates[i]; i++)

+		{

+			if (rates[i] >= bitrate)

+				break;

+		}

+

+		config.bandWidth = BandwithCoefTab[i][SampleRateIdx];

+

+		/* init aac encoder core */

+		ret = AacEncOpen(hAacEnc, config);

+		if(ret) 

+			return VO_ERR_AUDIO_UNSFEATURE;

+		break;

+	case VO_PID_AUDIO_FORMAT:	/* init pcm channel and samplerate*/

+		AacInitDefaultConfig(&config);

+		if(pData == NULL)

+			return VO_ERR_INVALID_ARG;

+		pWAV_Format = (VO_AUDIO_FORMAT*)pData;

+		config.adtsUsed = 1;

+		config.nChannelsIn = pWAV_Format->Channels;

+		config.nChannelsOut = pWAV_Format->Channels;

+		config.sampleRate = pWAV_Format->SampleRate;

+

+		/* check the channel */

+		if(config.nChannelsIn< 1  || config.nChannelsIn > MAX_CHANNELS  ||

+             config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)

+			 return VO_ERR_AUDIO_UNSCHANNEL;

+

+		/* check the samplebits */

+		if(pWAV_Format->SampleBits != 16)

+		{

+			return VO_ERR_AUDIO_UNSFEATURE;

+		}

+

+		/* check the samplerate */

+		ret = -1;

+		for(i = 0; i < NUM_SAMPLE_RATES; i++)

+		{

+			if(config.sampleRate == sampRateTab[i])

+			{

+				ret = 0;

+				break;

+			}

+		}

+		if(ret < 0)

+			return VO_ERR_AUDIO_UNSSAMPLERATE;

+

+		SampleRateIdx = i;

+

+		/* update the bitrates */

+		tmp = 441;

+		if(config.sampleRate%8000 == 0) 

+			tmp =480;

+

+		config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;

+

+		if(config.bitRate/config.nChannelsOut < 4000)

+			config.bitRate = 4000 * config.nChannelsOut;

+		else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)

+			config.bitRate = config.sampleRate*6*config.nChannelsOut;

+		else if(config.bitRate/config.nChannelsOut > 160000)

+			config.bitRate = config.nChannelsOut*160000;

+

+		/* check the bandwidth */

+		bitrate = config.bitRate / config.nChannelsOut;

+		bitrate = bitrate * tmp / config.sampleRate;

+

+		for (i = 0; rates[i]; i++)

+		{

+			if (rates[i] >= bitrate)

+				break;

+		}

+

+		config.bandWidth = BandwithCoefTab[i][SampleRateIdx];

+		

+		/* init aac encoder core */

+		ret = AacEncOpen(hAacEnc, config);

+		if(ret) 

+			return VO_ERR_AUDIO_UNSFEATURE;

+		break;

+	default:

+		return VO_ERR_WRONG_PARAM_ID;

+	}

+

+	return VO_ERR_NONE;

+}

+

+/**

+* Get the param for special target.

+* \param hCodec [IN]] The Codec Handle which was created by Init function.

+* \param uParamID [IN] The param ID.

+* \param pData [IN] The param value depend on the ID>

+* \retval VO_ERR_NONE Succeeded.

+*/

+VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)

+{

+	return VO_ERR_NONE;

+}

+

+/**

+ * Get audio codec API interface

+ * \param pEncHandle [out] Return the AAC Encoder handle.

+ * \retval VO_ERR_OK Succeeded.

+ */

+VO_S32 VO_API voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle)

+{

+	if(pDecHandle == NULL)

+		return VO_ERR_INVALID_ARG;

+		

+	pDecHandle->Init = voAACEncInit;

+	pDecHandle->SetInputData = voAACEncSetInputData;

+	pDecHandle->GetOutputData = voAACEncGetOutputData;

+	pDecHandle->SetParam = voAACEncSetParam;

+	pDecHandle->GetParam = voAACEncGetParam;

+	pDecHandle->Uninit = voAACEncUninit;

+

+	return VO_ERR_NONE;

+}
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc_core.c b/media/libstagefright/codecs/aacenc/src/aacenc_core.c
new file mode 100644
index 0000000..616475c
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/aacenc_core.c
@@ -0,0 +1,239 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		aacenc_core.c

+

+	Content:	aac encoder core functions

+

+*******************************************************************************/
+
+#include "typedef.h"
+#include "aacenc_core.h"
+#include "bitenc.h"
+
+#include "psy_configuration.h"
+#include "psy_main.h"
+#include "qc_main.h"
+#include "psy_main.h"
+#include "channel_map.h"
+#include "aac_rom.h"
+
+/********************************************************************************
+*
+* function name: AacInitDefaultConfig
+* description:  gives reasonable default configuration
+*
+**********************************************************************************/
+void AacInitDefaultConfig(AACENC_CONFIG *config)
+{
+  /* default configurations */
+  config->adtsUsed        = 1;
+  config->nChannelsIn     = 2;
+  config->nChannelsOut    = 2;
+  config->bitRate         = 128000;                      
+  config->bandWidth       = 0;                           
+}
+
+/********************************************************************************
+*
+* function name: AacEncOpen
+* description:  allocate and initialize a new encoder instance
+* returns:      0 if success
+*
+**********************************************************************************/
+Word16  AacEncOpen(  AAC_ENCODER*      hAacEnc,        /* pointer to an encoder handle, initialized on return */
+                     const  AACENC_CONFIG     config   /* pre-initialized config struct */
+                     )
+{
+  Word32 i;

+  Word32 error = 0;
+  Word16 profile = 1;

+
+  ELEMENT_INFO *elInfo = NULL;
+   
+  if (hAacEnc==0) {
+    error=1;                                  
+  }
+   
+  if (!error) {
+    hAacEnc->config = config;
+  }
+
+  if (!error) {
+    error = InitElementInfo (config.nChannelsOut,
+                             &hAacEnc->elInfo);
+  }
+

+  if (!error) {
+    elInfo = &hAacEnc->elInfo;
+  }
+
+  if (!error) {
+    /* use or not tns tool for long and short block */
+	 Word16 tnsMask=3;      
+
+	/* init encoder psychoacoustic */
+    error = psyMainInit(&hAacEnc->psyKernel,
+                        config.sampleRate,
+                        config.bitRate,
+                        elInfo->nChannelsInEl,
+                        tnsMask,
+                        hAacEnc->config.bandWidth);
+  }
+
+ /* use or not adts header */
+  if(!error) {

+	  hAacEnc->qcOut.qcElement.adtsUsed = config.adtsUsed;

+  }
+
+  /* init encoder quantization */
+  if (!error) {
+    struct QC_INIT qcInit;
+
+    /*qcInit.channelMapping = &hAacEnc->channelMapping;*/
+    qcInit.elInfo = &hAacEnc->elInfo;
+
+    qcInit.maxBits = (Word16) (MAXBITS_COEF*elInfo->nChannelsInEl);
+    qcInit.bitRes = qcInit.maxBits;                                      
+    qcInit.averageBits = (Word16) ((config.bitRate * FRAME_LEN_LONG) / config.sampleRate);
+
+    qcInit.padding.paddingRest = config.sampleRate;                          
+
+    qcInit.meanPe = (Word16) ((10 * FRAME_LEN_LONG * hAacEnc->config.bandWidth) /
+                                              (config.sampleRate>>1));
+
+    qcInit.maxBitFac = (Word16) ((100 * (MAXBITS_COEF-MINBITS_COEF)* elInfo->nChannelsInEl)/
+                                                 (qcInit.averageBits?qcInit.averageBits:1));
+
+    qcInit.bitrate = config.bitRate;                                     
+
+    error = QCInit(&hAacEnc->qcKernel, &qcInit);
+  }
+
+  /* init bitstream encoder */
+  if (!error) {
+    hAacEnc->bseInit.nChannels   = elInfo->nChannelsInEl;                
+    hAacEnc->bseInit.bitrate     = config.bitRate;                       
+    hAacEnc->bseInit.sampleRate  = config.sampleRate;                    
+    hAacEnc->bseInit.profile     = profile;                              
+  }
+
+  return error;
+}
+
+/********************************************************************************
+*
+* function name: AacEncEncode
+* description:  encode pcm to aac data core function
+* returns:      0 if success
+*
+**********************************************************************************/
+Word16 AacEncEncode(AAC_ENCODER *aacEnc,		/*!< an encoder handle */
+                    Word16 *timeSignal,         /*!< BLOCKSIZE*nChannels audio samples, interleaved */
+                    const UWord8 *ancBytes,     /*!< pointer to ancillary data bytes */
+                    Word16 *numAncBytes,		/*!< number of ancillary Data Bytes */
+                    UWord8 *outBytes,           /*!< pointer to output buffer (must be large MINBITS_COEF/8*MAX_CHANNELS bytes) */
+                    Word32 *numOutBytes         /*!< number of bytes in output buffer after processing */
+                    )
+{
+  ELEMENT_INFO *elInfo = &aacEnc->elInfo;
+  Word16 globUsedBits;
+  Word16 ancDataBytes, ancDataBytesLeft;
+  
+  ancDataBytes = ancDataBytesLeft = *numAncBytes;                          
+
+  /* init output aac data buffer and length */
+  aacEnc->hBitStream = CreateBitBuffer(&aacEnc->bitStream, outBytes, *numOutBytes);
+
+  /* psychoacoustic process */
+  psyMain(aacEnc->config.nChannelsOut,    
+          elInfo,
+          timeSignal,
+          &aacEnc->psyKernel.psyData[elInfo->ChannelIndex[0]],
+          &aacEnc->psyKernel.tnsData[elInfo->ChannelIndex[0]],
+          &aacEnc->psyKernel.psyConfLong,
+          &aacEnc->psyKernel.psyConfShort,
+          &aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
+          &aacEnc->psyOut.psyOutElement,
+          aacEnc->psyKernel.pScratchTns,
+		  aacEnc->config.sampleRate);
+
+  /* adjust bitrate and frame length */
+  AdjustBitrate(&aacEnc->qcKernel,
+                aacEnc->config.bitRate,
+                aacEnc->config.sampleRate);
+    
+  /* quantization and coding process */
+  QCMain(&aacEnc->qcKernel,         
+         &aacEnc->qcKernel.elementBits,
+         &aacEnc->qcKernel.adjThr.adjThrStateElem,
+         &aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
+         &aacEnc->psyOut.psyOutElement,
+         &aacEnc->qcOut.qcChannel[elInfo->ChannelIndex[0]],
+         &aacEnc->qcOut.qcElement,
+         elInfo->nChannelsInEl,
+		 min(ancDataBytesLeft,ancDataBytes));
+
+  ancDataBytesLeft = ancDataBytesLeft - ancDataBytes;
+
+  globUsedBits = FinalizeBitConsumption(&aacEnc->qcKernel,
+                         &aacEnc->qcOut);
+
+  /* write bitstream process */
+  WriteBitstream(aacEnc->hBitStream,				 
+                 *elInfo,
+                 &aacEnc->qcOut,
+                 &aacEnc->psyOut,
+                 &globUsedBits,				 
+                 ancBytes,

+				 aacEnc->psyKernel.sampleRateIdx);
+
+  updateBitres(&aacEnc->qcKernel,
+               &aacEnc->qcOut);
+
+  /* write out the bitstream */
+  *numOutBytes = GetBitsAvail(aacEnc->hBitStream) >> 3;

+
+  return 0;
+}
+
+
+/********************************************************************************
+*
+* function name:AacEncClose
+* description: deallocate an encoder instance
+*
+**********************************************************************************/
+void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP)
+{
+  if (hAacEnc) {  
+    QCDelete(&hAacEnc->qcKernel, pMemOP);
+
+    QCOutDelete(&hAacEnc->qcOut, pMemOP);
+
+    PsyDelete(&hAacEnc->psyKernel, pMemOP);
+
+    PsyOutDelete(&hAacEnc->psyOut, pMemOP);
+
+    DeleteBitBuffer(&hAacEnc->hBitStream);
+
+	if(hAacEnc->intbuf)
+	{
+		mem_free(pMemOP, hAacEnc->intbuf, VO_INDEX_ENC_AAC);
+		hAacEnc->intbuf = NULL;
+	}
+  }
+}
diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c
new file mode 100644
index 0000000..0dbd216
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c
@@ -0,0 +1,1223 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		adj_thr.c

+

+	Content:	Threshold compensation functions

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "oper_32b.h"
+#include "adj_thr_data.h"
+#include "adj_thr.h"
+#include "qc_data.h"
+#include "line_pe.h"
+
+
+#define  minSnrLimit    0x6666 /* 1 dB */
+#define  PEBITS_COEF	0x170a /* 0.18*(1 << 15)*/

+

+#define  HOLE_THR_LONG	0x2873	/* 0.316*(1 << 15) */

+#define  HOLE_THR_SHORT 0x4000  /* 0.5  *(1 << 15) */

+

+#define  MS_THRSPREAD_COEF 0x7333  /* 0.9 * (1 << 15) */

+

+#define	 MIN_SNR_COEF	   0x651f  /* 3.16* (1 << (15 - 2)) */

+
+/* values for avoid hole flag */
+enum _avoid_hole_state {
+  NO_AH              =0,
+  AH_INACTIVE        =1,
+  AH_ACTIVE          =2
+};
+
+/********************************************************************************
+*
+* function name:bits2pe
+* description: convert from bits to pe
+*			   pe = 1.18*desiredBits
+*
+**********************************************************************************/
+Word16 bits2pe(const Word16 bits) {
+  return (bits + ((PEBITS_COEF * bits) >> 15));
+}
+
+/********************************************************************************
+*
+* function name:calcThreshExp
+* description: loudness calculation (threshold to the power of redExp)
+*			   thr(n)^0.25
+*
+**********************************************************************************/
+static void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
+                          PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+                          const Word16 nChannels)
+{
+  Word16 ch, sfb, sfbGrp;

+  Word32 *pthrExp, *psfbThre;
+  for (ch=0; ch<nChannels; ch++) {
+    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];

+	 for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup)	 

+	  pthrExp = &(thrExp[ch][sfbGrp]);

+	  psfbThre = psyOutChan->sfbThreshold + sfbGrp;

+	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+		*pthrExp = rsqrt(rsqrt(*psfbThre,INT_BITS),INT_BITS);

+		pthrExp++; psfbThre++;
+      }
+  }
+}
+
+/********************************************************************************
+*
+* function name:adaptMinSnr
+* description: reduce minSnr requirements for bands with relative low energies
+*
+**********************************************************************************/
+static void adaptMinSnr(PSY_OUT_CHANNEL     psyOutChannel[MAX_CHANNELS],
+                        Word16              logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+                        MINSNR_ADAPT_PARAM *msaParam,
+                        const Word16        nChannels)
+{
+  Word16 ch, sfb, sfbOffs, shift;
+  Word32 nSfb, avgEn;
+  Word16 log_avgEn = 0;
+  Word32 startRatio_x_avgEn = 0;
+                                                                           
+
+  for (ch=0; ch<nChannels; ch++) {
+    PSY_OUT_CHANNEL* psyOutChan = &psyOutChannel[ch];
+
+    /* calc average energy per scalefactor band */
+    avgEn = 0;                                                           
+    nSfb = 0;                                                            
+    for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) {
+      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+        avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfbOffs+sfb]);
+        nSfb = nSfb + 1;
+      }
+    }
+     
+    if (nSfb > 0) {
+	  avgEn = avgEn / nSfb;

+
+      log_avgEn = iLog4(avgEn);
+      startRatio_x_avgEn = fixmul(msaParam->startRatio, avgEn);
+    }
+
+    
+    /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
+    for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) {
+      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+        if (psyOutChan->sfbEnergy[sfbOffs+sfb] < startRatio_x_avgEn) {
+          Word16 dbRatio, minSnrRed;
+          Word32 snrRed;
+          Word16 newMinSnr;
+          
+          dbRatio = log_avgEn - logSfbEnergy[ch][sfbOffs+sfb];
+          dbRatio = dbRatio + (dbRatio << 1);
+
+          minSnrRed = 110 - ((dbRatio + (dbRatio << 1)) >> 2);
+          minSnrRed = max(minSnrRed, 20); /* 110: (0.375(redOffs)+1)*80,  
+                                               3: 0.00375(redRatioFac)*80
+                                               20: 0.25(maxRed) * 80 */
+
+          snrRed = minSnrRed * iLog4((psyOutChan->sfbMinSnr[sfbOffs+sfb] << 16)); 
+          /* 
+             snrRedI si now scaled by 80 (minSnrRed) and 4 (ffr_iLog4)
+          */
+        
+          newMinSnr = round16(pow2_xy(snrRed,80*4));
+         
+          psyOutChan->sfbMinSnr[sfbOffs+sfb] = min(newMinSnr, minSnrLimit);
+        }
+      }
+    }
+  }
+
+}
+
+
+/********************************************************************************
+*
+* function name:initAvoidHoleFlag
+* description: determine bands where avoid hole is not necessary resp. possible
+*
+**********************************************************************************/
+static void initAvoidHoleFlag(Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+                              PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
+                              PSY_OUT_ELEMENT* psyOutElement,
+                              const Word16 nChannels,
+                              AH_PARAM *ahParam)
+{
+  Word16 ch, sfb, sfbGrp, shift;
+  Word32 threshold;
+  Word32* psfbSpreadEn;
+
+  for (ch=0; ch<nChannels; ch++) {
+    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+     
+    if (psyOutChan->windowSequence != SHORT_WINDOW) {
+      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+         psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp;

+		 for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+			*psfbSpreadEn = *psfbSpreadEn >> 1;  /* 0.5 */

+			++psfbSpreadEn;
+        }
+      }
+    }
+    else {
+      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){

+		psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp;
+        for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+          *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3);  /* 0.63 */

+		  ++psfbSpreadEn;
+        }
+      }
+    }
+  }
+
+  /* increase minSnr for local peaks, decrease it for valleys */
+  if (ahParam->modifyMinSnr) {
+    for(ch=0; ch<nChannels; ch++) {
+      PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+         
+      if (psyOutChan->windowSequence != SHORT_WINDOW)
+        threshold = HOLE_THR_LONG;
+      else
+        threshold = HOLE_THR_SHORT;
+
+      for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+        Word16 *psfbMinSnr = psyOutChan->sfbMinSnr + sfbGrp;

+		for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+          Word32 sfbEn, sfbEnm1, sfbEnp1, avgEn;
+             
+          if (sfb > 0)
+            sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1];
+          else
+            sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp];
+             
+          if (sfb < (psyOutChan->maxSfbPerGroup-1))
+            sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1];
+          else
+            sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb];
+          avgEn = (sfbEnm1 + sfbEnp1) >> 1;
+          sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb];                             
+             
+          if (sfbEn > avgEn && avgEn > 0) {
+            Word32 tmpMinSnr;
+            shift = norm_l(sfbEn);

+			tmpMinSnr = Div_32(L_mpy_ls(avgEn, minSnrLimit) << shift, sfbEn << shift );
+            tmpMinSnr = max(tmpMinSnr, HOLE_THR_LONG);                  
+            tmpMinSnr = max(tmpMinSnr, threshold);
+            *psfbMinSnr = min(*psfbMinSnr, tmpMinSnr);
+          }
+          /* valley ? */
+             
+          if ((sfbEn < (avgEn >> 1)) && (sfbEn > 0)) {
+            Word32 tmpMinSnr;
+            Word32 minSnrEn = L_mpy_wx(avgEn, *psfbMinSnr);                 
+             
+            if(minSnrEn < sfbEn) {

+			  shift = norm_l(sfbEn);
+              tmpMinSnr = Div_32( minSnrEn << shift, sfbEn<<shift);
+            }
+            else {
+              tmpMinSnr = MAX_16;                                             
+            }
+            tmpMinSnr = min(minSnrLimit, tmpMinSnr);
+
+            *psfbMinSnr =
+              (min((tmpMinSnr >>  2), mult(*psfbMinSnr, MIN_SNR_COEF)) << 2);
+          }

+		  psfbMinSnr++;
+        }
+      }
+    }
+  }
+
+  /* stereo: adapt the minimum requirements sfbMinSnr of mid and
+     side channels */
+   
+  if (nChannels == 2) {
+    PSY_OUT_CHANNEL *psyOutChanM = &psyOutChannel[0];
+    PSY_OUT_CHANNEL *psyOutChanS = &psyOutChannel[1];
+    for (sfb=0; sfb<psyOutChanM->sfbCnt; sfb++) {
+      if (psyOutElement->toolsInfo.msMask[sfb]) {
+        Word32 sfbEnM = psyOutChanM->sfbEnergy[sfb];
+        Word32 sfbEnS = psyOutChanS->sfbEnergy[sfb];
+        Word32 maxSfbEn = max(sfbEnM, sfbEnS);
+        Word32 maxThr = L_mpy_wx(maxSfbEn, psyOutChanM->sfbMinSnr[sfb]) >> 1;        
+         
+        if(maxThr >= sfbEnM) {
+          psyOutChanM->sfbMinSnr[sfb] = MAX_16;                                          
+        }
+        else {
+          shift = norm_l(sfbEnM); 

+		  psyOutChanM->sfbMinSnr[sfb] = min(max(psyOutChanM->sfbMinSnr[sfb], 

+			  round16(Div_32(maxThr<<shift, sfbEnM << shift))), minSnrLimit);
+        }
+         
+        if(maxThr >= sfbEnS) {
+          psyOutChanS->sfbMinSnr[sfb] = MAX_16;
+        }
+        else {

+		  shift = norm_l(sfbEnS);
+          psyOutChanS->sfbMinSnr[sfb] = min(max(psyOutChanS->sfbMinSnr[sfb], 

+			  round16(Div_32(maxThr << shift, sfbEnS << shift))), minSnrLimit);
+        }
+
+         
+        if (sfbEnM > psyOutChanM->sfbSpreadedEnergy[sfb])
+          psyOutChanS->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnS, MS_THRSPREAD_COEF);
+         
+        if (sfbEnS > psyOutChanS->sfbSpreadedEnergy[sfb])
+          psyOutChanM->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnM, MS_THRSPREAD_COEF);
+      }
+    }
+  }
+
+
+  /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
+  for(ch=0; ch<nChannels; ch++) {
+    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+      Word16 *pahFlag = ahFlag[ch] + sfbGrp;

+	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+               
+        if ((psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] > psyOutChan->sfbEnergy[sfbGrp+sfb]) ||
+            (psyOutChan->sfbEnergy[sfbGrp+sfb] <= psyOutChan->sfbThreshold[sfbGrp+sfb]) ||
+            (psyOutChan->sfbMinSnr[sfbGrp+sfb] == MAX_16)) {
+          *pahFlag++ = NO_AH;
+        }
+        else {
+          *pahFlag++ = AH_INACTIVE;
+        }
+      }
+      for (sfb=psyOutChan->maxSfbPerGroup; sfb<psyOutChan->sfbPerGroup; sfb++) {
+        *pahFlag++ = NO_AH;                                                          
+      }
+    }
+  }
+}
+
+/********************************************************************************
+*
+* function name:calcPeNoAH
+* description: sum the pe data only for bands where avoid hole is inactive
+*
+**********************************************************************************/
+static void calcPeNoAH(Word16          *pe,
+                       Word16          *constPart,
+                       Word16          *nActiveLines,
+                       PE_DATA         *peData,
+                       Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+                       PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
+                       const Word16     nChannels)
+{
+  Word16 ch, sfb, sfbGrp;

+  int ipe, iconstPart, inActiveLines;
+
+  ipe = 0;                                                       
+  iconstPart = 0;                                                
+  inActiveLines = 0;                                             
+  for(ch=0; ch<nChannels; ch++) {
+    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+    PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
+    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+         
+        if (ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) {
+          ipe = ipe + peChanData->sfbPe[sfbGrp+sfb];
+          iconstPart = iconstPart + peChanData->sfbConstPart[sfbGrp+sfb];
+          inActiveLines = inActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb];
+        }
+      }
+    }
+  }

+
+  *pe = saturate(ipe);                                                       
+  *constPart = saturate(iconstPart);                                                
+  *nActiveLines = saturate(inActiveLines);  
+}
+
+/********************************************************************************
+*
+* function name:reduceThresholds
+* description: apply reduction formula
+*
+**********************************************************************************/
+static void reduceThresholds(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
+                             Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+                             Word32           thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
+                             const Word16     nChannels,
+                             const Word32     redVal)
+{
+  Word32 sfbThrReduced;
+  Word32 *psfbEn, *psfbThr;     

+  Word16 ch, sfb, sfbGrp;

+
+  for(ch=0; ch<nChannels; ch++) {
+    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+    for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) {
+ 	  psfbEn  = psyOutChan->sfbEnergy + sfbGrp;                                      

+      psfbThr = psyOutChan->sfbThreshold + sfbGrp;

+	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+         
+        if (*psfbEn > *psfbThr) {
+          /* threshold reduction formula */
+          Word32 tmp = thrExp[ch][sfbGrp+sfb] + redVal;
+          tmp = fixmul(tmp, tmp);
+          sfbThrReduced = fixmul(tmp, tmp);
+          /* avoid holes */
+          tmp = L_mpy_ls(*psfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]);
+             
+          if ((sfbThrReduced > tmp) && 
+              (ahFlag[ch][sfbGrp+sfb] != NO_AH)){
+            sfbThrReduced = max(tmp, *psfbThr);
+            ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE;                                          
+          }
+		  *psfbThr = sfbThrReduced;
+        }

+

+		psfbEn++;  psfbThr++;
+      }
+    }
+  }
+}
+
+
+/********************************************************************************
+*
+* function name:correctThresh
+* description: if pe difference deltaPe between desired pe and real pe is small enough,
+*             the difference can be distributed among the scale factor bands.
+*
+**********************************************************************************/
+static void correctThresh(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
+                          Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+                          PE_DATA          *peData,
+                          Word32           thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
+                          const Word32     redVal,
+                          const Word16     nChannels,
+                          const Word32     deltaPe)
+{
+  Word16 ch, sfb, sfbGrp,shift;
+  PSY_OUT_CHANNEL *psyOutChan;
+  PE_CHANNEL_DATA *peChanData;
+  Word32 deltaSfbPe;
+  Word32 normFactor;

+  Word32 *psfbPeFactors;

+  Word16 *psfbNActiveLines, *pahFlag;
+  Word32 sfbEn, sfbThr;
+  Word32 sfbThrReduced;
+
+  /* for each sfb calc relative factors for pe changes */
+  normFactor = 1;                                                                        
+  for(ch=0; ch<nChannels; ch++) {
+    psyOutChan = &psyOutChannel[ch];
+    peChanData = &peData->peChannelData[ch];
+    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+      psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp;

+	  psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp;

+	  pahFlag = ahFlag[ch] + sfbGrp;

+	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+        Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal;
+             
+        if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) ) {
+            
+          *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp);
+          normFactor = L_add(normFactor, *psfbPeFactors);
+        }
+        else {
+          *psfbPeFactors = 0;                                              
+        }

+		psfbPeFactors++; 

+		pahFlag++; psfbNActiveLines++;
+      }
+    }
+  }
+
+ 
+  /* calculate new thresholds */
+  for(ch=0; ch<nChannels; ch++) {
+    psyOutChan = &psyOutChannel[ch];
+    peChanData = &peData->peChannelData[ch];
+    for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+      psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp;

+	  psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp;

+	  pahFlag = ahFlag[ch] + sfbGrp;

+	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+        /* pe difference for this sfb */
+        deltaSfbPe = *psfbPeFactors * deltaPe;
+
+		/* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */         
+        if (*psfbNActiveLines > 0) {
+          /* new threshold */
+          Word32 thrFactor;
+          sfbEn  = psyOutChan->sfbEnergy[sfbGrp+sfb];
+          sfbThr = psyOutChan->sfbThreshold[sfbGrp+sfb];
+
+           if(deltaSfbPe >= 0){
+            /*
+              reduce threshold
+            */
+            thrFactor = pow2_xy(L_negate(deltaSfbPe), (normFactor* (*psfbNActiveLines)));
+              
+            sfbThrReduced = L_mpy_ls(sfbThr, round16(thrFactor));
+          }
+          else {
+            /*
+              increase threshold
+            */
+            thrFactor = pow2_xy(deltaSfbPe, (normFactor * (*psfbNActiveLines)));
+              
+             
+            if(thrFactor > sfbThr) {
+              shift = norm_l(thrFactor);

+			  sfbThrReduced = Div_32( sfbThr << shift, thrFactor<<shift );
+            }
+            else {
+              sfbThrReduced = MAX_32;                                                                            
+            }
+
+          }
+            
+          /* avoid hole */
+          sfbEn = L_mpy_ls(sfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]);
+             
+          if ((sfbThrReduced > sfbEn) &&
+              (*pahFlag == AH_INACTIVE)) {
+            sfbThrReduced = max(sfbEn, sfbThr);
+            *pahFlag = AH_ACTIVE;                                                                  
+          }
+
+          psyOutChan->sfbThreshold[sfbGrp+sfb] = sfbThrReduced;  
+        }

+

+		pahFlag++; psfbNActiveLines++; psfbPeFactors++;
+      }
+    }
+  }
+}
+
+
+/********************************************************************************
+*
+* function name:reduceMinSnr
+* description: if the desired pe can not be reached, reduce pe by reducing minSnr
+*
+**********************************************************************************/
+static void reduceMinSnr(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS], 
+                         PE_DATA         *peData, 
+                         Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+                         const Word16     nChannels,
+                         const Word16     desiredPe)
+{
+  Word16 ch, sfb, sfbSubWin;
+  Word16 deltaPe;
+
+  /* start at highest freq down to 0 */
+  sfbSubWin = psyOutChannel[0].maxSfbPerGroup;                                                 
+  while (peData->pe > desiredPe && sfbSubWin > 0) {
+       
+    sfbSubWin = sfbSubWin - 1;
+    /* loop over all subwindows */
+    for (sfb=sfbSubWin; sfb<psyOutChannel[0].sfbCnt;
+        sfb+=psyOutChannel[0].sfbPerGroup) {
+      /* loop over all channels */
+		PE_CHANNEL_DATA* peChan = peData->peChannelData;

+		PSY_OUT_CHANNEL* psyOutCh = psyOutChannel;

+		for (ch=0; ch<nChannels; ch++) {           
+        if (ahFlag[ch][sfb] != NO_AH &&
+            psyOutCh->sfbMinSnr[sfb] < minSnrLimit) {
+          psyOutCh->sfbMinSnr[sfb] = minSnrLimit;                                      
+          psyOutCh->sfbThreshold[sfb] =
+            L_mpy_ls(psyOutCh->sfbEnergy[sfb], psyOutCh->sfbMinSnr[sfb]);
+
+          /* calc new pe */
+          deltaPe = ((peChan->sfbNLines4[sfb] + (peChan->sfbNLines4[sfb] >> 1)) >> 2) -
+              peChan->sfbPe[sfb];
+          peData->pe = peData->pe + deltaPe;
+          peChan->pe = peChan->pe + deltaPe;		  
+        }

+		peChan += 1; psyOutCh += 1;
+      }
+      /* stop if enough has been saved */
+       
+      if (peData->pe <= desiredPe)
+        break;
+    }
+  }
+}
+
+/********************************************************************************
+*
+* function name:allowMoreHoles
+* description: if the desired pe can not be reached, some more scalefactor bands  
+*              have to be quantized to zero
+*
+**********************************************************************************/
+static void allowMoreHoles(PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS], 
+                           PSY_OUT_ELEMENT *psyOutElement,
+                           PE_DATA         *peData, 
+                           Word16           ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+                           const AH_PARAM  *ahParam,
+                           const Word16     nChannels,
+                           const Word16     desiredPe)
+{
+  Word16 ch, sfb;
+  Word16 actPe, shift;
+
+  actPe = peData->pe;                                                                    
+
+  /* for MS allow hole in the channel with less energy */
+     
+  if (nChannels==2 &&
+      psyOutChannel[0].windowSequence==psyOutChannel[1].windowSequence) {
+    PSY_OUT_CHANNEL *psyOutChanL = &psyOutChannel[0];
+    PSY_OUT_CHANNEL *psyOutChanR = &psyOutChannel[1];
+    for (sfb=0; sfb<psyOutChanL->sfbCnt; sfb++) {
+      Word32 minEn;
+       
+      if (psyOutElement->toolsInfo.msMask[sfb]) {
+        /* allow hole in side channel ? */
+        minEn = L_mpy_ls(psyOutChanL->sfbEnergy[sfb], (minSnrLimit * psyOutChanL->sfbMinSnr[sfb]) >> 16);
+           
+        if (ahFlag[1][sfb] != NO_AH &&
+            minEn > psyOutChanR->sfbEnergy[sfb]) {
+          ahFlag[1][sfb] = NO_AH;                                                                
+          psyOutChanR->sfbThreshold[sfb] = L_add(psyOutChanR->sfbEnergy[sfb], psyOutChanR->sfbEnergy[sfb]);
+          actPe = actPe - peData->peChannelData[1].sfbPe[sfb];
+        }
+        /* allow hole in mid channel ? */
+        else {
+        minEn = L_mpy_ls(psyOutChanR->sfbEnergy[sfb], (minSnrLimit * psyOutChanR->sfbMinSnr[sfb]) >> 16);
+             
+          if (ahFlag[0][sfb]!= NO_AH &&
+              minEn > psyOutChanL->sfbEnergy[sfb]) {
+            ahFlag[0][sfb] = NO_AH;                                                              
+            psyOutChanL->sfbThreshold[sfb] = L_add(psyOutChanL->sfbEnergy[sfb], psyOutChanL->sfbEnergy[sfb]);
+            actPe = actPe - peData->peChannelData[0].sfbPe[sfb];
+          }
+        }
+         
+        if (actPe < desiredPe)
+          break;
+      }
+    }
+  }
+
+  /* subsequently erase bands */   
+  if (actPe > desiredPe) {
+    Word16 startSfb[2];
+    Word32 avgEn, minEn;
+    Word16 ahCnt;
+    Word16 enIdx;
+    Word16 enDiff;
+    Word32 en[4];
+    Word16 minSfb, maxSfb;
+    Flag   done;
+
+    /* do not go below startSfb */
+    for (ch=0; ch<nChannels; ch++) {
+         
+      if (psyOutChannel[ch].windowSequence != SHORT_WINDOW)
+        startSfb[ch] = ahParam->startSfbL;
+      else
+        startSfb[ch] = ahParam->startSfbS;
+    }
+
+    avgEn = 0;                                                           
+    minEn = MAX_32;                                                      
+    ahCnt = 0;                                                           
+    for (ch=0; ch<nChannels; ch++) {
+      PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+      for (sfb=startSfb[ch]; sfb<psyOutChan->sfbCnt; sfb++) {
+           
+        if ((ahFlag[ch][sfb] != NO_AH) &&
+            (psyOutChan->sfbEnergy[sfb] > psyOutChan->sfbThreshold[sfb])) {
+          minEn = min(minEn, psyOutChan->sfbEnergy[sfb]);
+          avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfb]);
+          ahCnt++;
+        }
+      }
+    }
+     
+    if(ahCnt) {
+      Word32 iahCnt;
+      shift = norm_l(ahCnt);

+	  iahCnt = Div_32( 1 << shift, ahCnt << shift );
+      avgEn = fixmul(avgEn, iahCnt);
+    }
+
+    enDiff = iLog4(avgEn) - iLog4(minEn);
+    /* calc some energy borders between minEn and avgEn */
+    for (enIdx=0; enIdx<4; enIdx++) {
+      Word32 enFac;
+      enFac = ((6-(enIdx << 1)) * enDiff);
+      en[enIdx] = fixmul(avgEn, pow2_xy(L_negate(enFac),7*4));
+    }
+
+    /* start with lowest energy border at highest sfb */
+    maxSfb = psyOutChannel[0].sfbCnt - 1;
+    minSfb = startSfb[0];                                                                
+     
+    if (nChannels == 2) {
+      maxSfb = max(maxSfb, (psyOutChannel[1].sfbCnt - 1));
+      minSfb = min(minSfb, startSfb[1]);
+    }
+
+    sfb = maxSfb;                                                                        
+    enIdx = 0;                                                                           
+    done = 0;                                                                            
+    while (!done) {
+       
+      for (ch=0; ch<nChannels; ch++) {
+        PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+           
+        if (sfb>=startSfb[ch] && sfb<psyOutChan->sfbCnt) {
+          /* sfb energy below border ? */
+             
+          if (ahFlag[ch][sfb] != NO_AH && psyOutChan->sfbEnergy[sfb] < en[enIdx]){
+            /* allow hole */
+            ahFlag[ch][sfb] = NO_AH;                                                     
+            psyOutChan->sfbThreshold[sfb] = L_add(psyOutChan->sfbEnergy[sfb], psyOutChan->sfbEnergy[sfb]);
+            actPe = actPe - peData->peChannelData[ch].sfbPe[sfb];
+          }
+           
+          if (actPe < desiredPe) {
+            done = 1;                                                                    
+            break;
+          }
+        }
+      }
+      sfb = sfb - 1;
+       
+      if (sfb < minSfb) {
+        /* restart with next energy border */
+        sfb = maxSfb;                                                                    
+        enIdx = enIdx + 1;
+         
+        if (enIdx - 4 >= 0)
+          done = 1;                                                                      
+      }
+    }
+  }
+}
+
+/********************************************************************************
+*
+* function name:adaptThresholdsToPe
+* description: two guesses for the reduction value and one final correction of the
+*              thresholds
+*
+**********************************************************************************/
+static void adaptThresholdsToPe(PSY_OUT_CHANNEL     psyOutChannel[MAX_CHANNELS],
+                                PSY_OUT_ELEMENT    *psyOutElement,
+                                Word16              logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+                                PE_DATA            *peData,
+                                const Word16        nChannels,
+                                const Word16        desiredPe,
+                                AH_PARAM           *ahParam,
+                                MINSNR_ADAPT_PARAM *msaParam)
+{
+  Word16 noRedPe, redPe, redPeNoAH;
+  Word16 constPart, constPartNoAH;
+  Word16 nActiveLines, nActiveLinesNoAH;
+  Word16 desiredPeNoAH;
+  Word32 redVal, avgThrExp;
+  Word32 iter;
+
+  calcThreshExp(peData->thrExp, psyOutChannel, nChannels);
+
+  adaptMinSnr(psyOutChannel, logSfbEnergy, msaParam, nChannels);
+
+  initAvoidHoleFlag(peData->ahFlag, psyOutChannel, psyOutElement, nChannels, ahParam);
+
+  noRedPe = peData->pe;                                                          
+  constPart = peData->constPart;                                                 
+  nActiveLines = peData->nActiveLines;       
+
+  /* first guess of reduction value t^0.25 = 2^((a-pen)/4*b) */
+  avgThrExp = pow2_xy((constPart - noRedPe), (nActiveLines << 2));
+  
+  /* r1 = 2^((a-per)/4*b) - t^0.25 */
+  redVal = pow2_xy((constPart - desiredPe), (nActiveLines << 2)) - avgThrExp;
+
+  /* reduce thresholds */
+  reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal);
+
+  /* pe after first guess */
+  calcSfbPe(peData, psyOutChannel, nChannels);
+  redPe = peData->pe;                                                            
+
+  iter = 0;                                                                      
+  do {
+    /* pe for bands where avoid hole is inactive */
+    calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH,
+               peData, peData->ahFlag, psyOutChannel, nChannels);
+
+    desiredPeNoAH = desiredPe -(redPe - redPeNoAH);
+     
+    if (desiredPeNoAH < 0) {
+      desiredPeNoAH = 0;                                                         
+    }
+
+    /* second guess */
+     
+    if (nActiveLinesNoAH > 0) {
+		
+		avgThrExp = pow2_xy((constPartNoAH - redPeNoAH), (nActiveLinesNoAH << 2));
+		
+		redVal = (redVal + pow2_xy((constPartNoAH - desiredPeNoAH), (nActiveLinesNoAH << 2))) - avgThrExp;
+		
+		/* reduce thresholds */
+		reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal);
+    }
+
+    calcSfbPe(peData, psyOutChannel, nChannels);
+    redPe = peData->pe;                                                          
+
+    iter = iter+1;
+       
+  } while ((20 * abs_s(redPe - desiredPe) > desiredPe) && (iter < 2));
+
+   
+  if ((100 * redPe < 115 * desiredPe)) {
+    correctThresh(psyOutChannel, peData->ahFlag, peData, peData->thrExp, redVal,
+                  nChannels, desiredPe - redPe);
+  }
+  else {
+    Word16 desiredPe105 = (105 * desiredPe) / 100;
+    reduceMinSnr(psyOutChannel, peData, peData->ahFlag,
+                 nChannels, desiredPe105);
+    allowMoreHoles(psyOutChannel, psyOutElement, peData, peData->ahFlag,
+                   ahParam, nChannels, desiredPe105);
+  }
+}
+
+
+/*****************************************************************************
+*
+* function name: calcBitSave
+* description:  Calculates percentage of bit save, see figure below
+* returns:
+* input:        parameters and bitres-fullness
+* output:       percentage of bit save
+*
+*****************************************************************************/
+static Word16 calcBitSave(Word16 fillLevel,
+                          const Word16 clipLow,
+                          const Word16 clipHigh,
+                          const Word16 minBitSave,
+                          const Word16 maxBitSave)
+{
+  Word16 bitsave = 0;
+
+  fillLevel = max(fillLevel, clipLow);
+  fillLevel = min(fillLevel, clipHigh);
+
+  if(clipHigh-clipLow)

+  bitsave = (maxBitSave - (((maxBitSave-minBitSave)*(fillLevel-clipLow))/
+                              (clipHigh-clipLow)));
+
+  return (bitsave);
+}
+
+
+
+/*****************************************************************************
+*
+* function name: calcBitSpend
+* description:  Calculates percentage of bit spend, see figure below
+* returns:
+* input:        parameters and bitres-fullness
+* output:       percentage of bit spend
+*
+*****************************************************************************/
+static Word16 calcBitSpend(Word16 fillLevel,
+                           const Word16 clipLow,
+                           const Word16 clipHigh,
+                           const Word16 minBitSpend,
+                           const Word16 maxBitSpend)
+{
+  Word16 bitspend = 1;
+
+  fillLevel = max(fillLevel, clipLow);
+  fillLevel = min(fillLevel, clipHigh);
+
+  if(clipHigh-clipLow)

+  bitspend = (minBitSpend + ((maxBitSpend - minBitSpend)*(fillLevel - clipLow) /
+                                (clipHigh-clipLow)));
+                            
+  return (bitspend);
+}
+
+
+/*****************************************************************************
+*
+* function name: adjustPeMinMax()
+* description:  adjusts peMin and peMax parameters over time
+* returns:
+* input:        current pe, peMin, peMax
+* output:       adjusted peMin/peMax
+*
+*****************************************************************************/
+static void adjustPeMinMax(const Word16 currPe,
+                           Word16      *peMin,
+                           Word16      *peMax)
+{
+  Word16 minFacHi, maxFacHi, minFacLo, maxFacLo;
+  Word16 diff;
+  Word16 minDiff = extract_l(currPe / 6);
+  minFacHi = 30;                                                         
+  maxFacHi = 100;                                                        
+  minFacLo = 14;                                                         
+  maxFacLo = 7;                                                          
+
+  diff = currPe - *peMax ;
+   
+  if (diff > 0) {
+    *peMin = *peMin + ((diff * minFacHi) / 100);
+    *peMax = *peMax + ((diff * maxFacHi) / 100);
+  } else {
+    diff = *peMin - currPe;
+     
+    if (diff > 0) {
+      *peMin = *peMin - ((diff * minFacLo) / 100);
+      *peMax = *peMax - ((diff * maxFacLo) / 100);
+    } else {
+      *peMin = *peMin + ((currPe - *peMin) * minFacHi / 100);
+      *peMax = *peMax - ((*peMax - currPe) * maxFacLo / 100);
+    }
+  }
+
+   
+  if ((*peMax - *peMin) < minDiff) {
+    Word16 partLo, partHi;
+
+    partLo = max(0, (currPe - *peMin));
+    partHi = max(0, (*peMax - currPe));
+
+    *peMax = currPe + ((partHi * minDiff) / (partLo + partHi));
+    *peMin = currPe - ((partLo * minDiff) / (partLo + partHi));
+    *peMin = max(0, *peMin);
+  }
+}
+
+
+/*****************************************************************************
+*
+* function name: BitresCalcBitFac
+* description:  calculates factor of spending bits for one frame
+*                1.0 : take all frame dynpart bits
+*                >1.0 : take all frame dynpart bits + bitres
+*                <1.0 : put bits in bitreservoir
+*  returns:      BitFac*100
+*  input:        bitres-fullness, pe, blockType, parameter-settings
+*  output:
+*
+*****************************************************************************/
+static Word16 bitresCalcBitFac( const Word16   bitresBits,
+                                const Word16   maxBitresBits,
+                                const Word16   pe,
+                                const Word16   windowSequence,
+                                const Word16   avgBits,
+                                const Word16   maxBitFac,
+                                ADJ_THR_STATE *AdjThr,
+                                ATS_ELEMENT   *adjThrChan)
+{
+  BRES_PARAM *bresParam;
+  Word16 pex;
+  Word16 fillLevel;
+  Word16 bitSave, bitSpend, bitresFac;
+
+  fillLevel = extract_l((100* bitresBits) / maxBitresBits);
+
+  if (windowSequence != SHORT_WINDOW)
+    bresParam = &(AdjThr->bresParamLong);
+  else
+    bresParam = &(AdjThr->bresParamShort);
+
+  pex = max(pe, adjThrChan->peMin);
+  pex = min(pex,adjThrChan->peMax);
+
+  bitSave = calcBitSave(fillLevel,
+                        bresParam->clipSaveLow, bresParam->clipSaveHigh,
+                        bresParam->minBitSave, bresParam->maxBitSave);
+
+  bitSpend = calcBitSpend(fillLevel,
+                          bresParam->clipSpendLow, bresParam->clipSpendHigh,
+                          bresParam->minBitSpend, bresParam->maxBitSpend);
+
+  if(adjThrChan->peMax != adjThrChan->peMin)

+	bitresFac = (100 - bitSave) + extract_l(((bitSpend + bitSave) * (pex - adjThrChan->peMin)) /
+                    (adjThrChan->peMax - adjThrChan->peMin));
+  else
+	bitresFac = 0x7fff;
+               
+  bitresFac = min(bitresFac,
+                    (100-30 + extract_l((100 * bitresBits) / avgBits)));
+
+  bitresFac = min(bitresFac, maxBitFac);
+
+  adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
+
+  return bitresFac;
+}
+
+/*****************************************************************************
+*
+* function name: AdjThrInit
+* description:  init thresholds parameter
+*
+*****************************************************************************/
+void AdjThrInit(ADJ_THR_STATE *hAdjThr,
+                const Word32   meanPe,
+                Word32         chBitrate)
+{
+  ATS_ELEMENT* atsElem = &hAdjThr->adjThrStateElem;
+  MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
+
+  /* common for all elements: */
+  /* parameters for bitres control */
+  hAdjThr->bresParamLong.clipSaveLow   =  20;                    
+  hAdjThr->bresParamLong.clipSaveHigh  =  95;                    
+  hAdjThr->bresParamLong.minBitSave    =  -5;                    
+  hAdjThr->bresParamLong.maxBitSave    =  30;                    
+  hAdjThr->bresParamLong.clipSpendLow  =  20;                    
+  hAdjThr->bresParamLong.clipSpendHigh =  95;                    
+  hAdjThr->bresParamLong.minBitSpend   = -10;                    
+  hAdjThr->bresParamLong.maxBitSpend   =  40;                    
+
+  hAdjThr->bresParamShort.clipSaveLow   =  20;                   
+  hAdjThr->bresParamShort.clipSaveHigh  =  75;                   
+  hAdjThr->bresParamShort.minBitSave    =   0;                   
+  hAdjThr->bresParamShort.maxBitSave    =  20;                   
+  hAdjThr->bresParamShort.clipSpendLow  =  20;                   
+  hAdjThr->bresParamShort.clipSpendHigh =  75;                   
+  hAdjThr->bresParamShort.minBitSpend   = -5;                    
+  hAdjThr->bresParamShort.maxBitSpend   =  50;                   
+
+  /* specific for each element: */
+
+  /* parameters for bitres control */
+  atsElem->peMin = extract_l(((80*meanPe) / 100));
+  atsElem->peMax = extract_l(((120*meanPe) / 100));
+
+  /* additional pe offset to correct pe2bits for low bitrates */
+  atsElem->peOffset = 0;                             
+  if (chBitrate < 32000) {
+    atsElem->peOffset = max(50, (100 - extract_l((100 * chBitrate) / 32000)));
+  }
+
+  /* avoid hole parameters */
+  if (chBitrate > 20000) {
+    atsElem->ahParam.modifyMinSnr = TRUE;
+    atsElem->ahParam.startSfbL = 15;
+    atsElem->ahParam.startSfbS = 3;
+  }
+  else {
+    atsElem->ahParam.modifyMinSnr = FALSE;
+    atsElem->ahParam.startSfbL = 0;
+    atsElem->ahParam.startSfbS = 0;
+  }
+
+  /* minSnr adaptation */
+  /* maximum reduction of minSnr goes down to minSnr^maxRed */
+  msaParam->maxRed = 0x20000000;     /* *0.25f /                        
+  /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
+  msaParam->startRatio = 0x0ccccccd; /* 10 */                        
+  /* maximum minSnr reduction to minSnr^maxRed is reached for
+     avgEn/sfbEn >= maxRatio */
+  msaParam->maxRatio =  0x0020c49c; /* 1000 */                         
+  /* helper variables to interpolate minSnr reduction for
+     avgEn/sfbEn between startRatio and maxRatio */
+
+  msaParam->redRatioFac = 0xfb333333; /* -0.75/20 */         
+
+  msaParam->redOffs = 0x30000000;  /* msaParam->redRatioFac * 10*log10(msaParam->startRatio) */  
+
+       
+  /* pe correction */
+  atsElem->peLast = 0;                                                 
+  atsElem->dynBitsLast = 0;                                            
+  atsElem->peCorrectionFactor = 100; /* 1.0 */                         
+
+}
+
+/*****************************************************************************
+*
+* function name: calcPeCorrection
+* description:  calculates the desired perceptual entropy factor
+*				It is between 0.85 and 1.15
+*
+*****************************************************************************/
+static void calcPeCorrection(Word16 *correctionFac,
+                             const Word16 peAct,
+                             const Word16 peLast, 
+                             const Word16 bitsLast) 
+{
+  Word32 peAct100 = 100 * peAct;
+  Word32 peLast100 = 100 * peLast;
+  Word16 peBitsLast = bits2pe(bitsLast);
+           
+  if ((bitsLast > 0) &&
+      (peAct100 < (150 * peLast)) &&  (peAct100 > (70 * peLast)) &&
+      ((120 * peBitsLast) > peLast100 ) && (( 65 * peBitsLast) < peLast100))
+    {
+      Word16 newFac = (100 * peLast) / peBitsLast;
+      /* dead zone */
+       
+      if (newFac < 100) {
+        newFac = min(((110 * newFac) / 100), 100);
+        newFac = max(newFac, 85);
+      }
+      else {
+        newFac = max(((90 * newFac) / 100), 100);
+        newFac = min(newFac, 115);
+      }
+         
+      if ((newFac > 100 && *correctionFac < 100) ||
+          (newFac < 100 && *correctionFac > 100)) {
+        *correctionFac = 100;                                                    
+      }
+      /* faster adaptation towards 1.0, slower in the other direction */
+             
+      if ((*correctionFac < 100 && newFac < *correctionFac) ||
+          (*correctionFac > 100 && newFac > *correctionFac))
+        *correctionFac = (85 * *correctionFac + 15 * newFac) / 100;
+      else
+        *correctionFac = (70 * *correctionFac + 30 * newFac) / 100;
+      *correctionFac = min(*correctionFac, 115);
+      *correctionFac = max(*correctionFac, 85);
+    }
+  else {
+    *correctionFac = 100;                                                        
+  }
+}
+
+/********************************************************************************
+*
+* function name: AdjustThresholds
+* description:  Adjust thresholds to the desired bitrate
+*
+**********************************************************************************/
+void AdjustThresholds(ADJ_THR_STATE   *adjThrState,
+                      ATS_ELEMENT     *AdjThrStateElement,
+                      PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
+                      PSY_OUT_ELEMENT *psyOutElement,
+                      Word16          *chBitDistribution,
+                      Word16           logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+                      Word16           sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],                      
+                      QC_OUT_ELEMENT  *qcOE,
+					  ELEMENT_BITS	  *elBits,
+					  const Word16     nChannels,
+                      const Word16     maxBitFac)
+{
+  PE_DATA peData;  
+  Word16 noRedPe, grantedPe, grantedPeCorr;
+  Word16 curWindowSequence;
+  Word16 bitFactor;
+  Word16 avgBits = (elBits->averageBits - (qcOE->staticBitsUsed + qcOE->ancBitsUsed));
+  Word16 bitresBits = elBits->bitResLevel; 
+  Word16 maxBitresBits = elBits->maxBits;
+  Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed);
+  Word16 ch;
+   
+  prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset);
+   
+  /* pe without reduction */
+  calcSfbPe(&peData, psyOutChannel, nChannels);
+  noRedPe = peData.pe;                                                   
+
+
+  curWindowSequence = LONG_WINDOW;                                       
+   
+  if (nChannels == 2) {
+       
+    if ((psyOutChannel[0].windowSequence == SHORT_WINDOW) ||
+        (psyOutChannel[1].windowSequence == SHORT_WINDOW)) {
+      curWindowSequence = SHORT_WINDOW;                                  
+    }
+  }
+  else {
+    curWindowSequence = psyOutChannel[0].windowSequence;                 
+  }
+
+
+  /* bit factor */
+  bitFactor = bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe+5*sideInfoBits,
+                               curWindowSequence, avgBits, maxBitFac,
+                               adjThrState,
+                               AdjThrStateElement);
+
+  /* desired pe */
+  grantedPe = ((bitFactor * bits2pe(avgBits)) / 100);
+
+  /* correction of pe value */
+  calcPeCorrection(&(AdjThrStateElement->peCorrectionFactor), 
+                   min(grantedPe, noRedPe),
+                   AdjThrStateElement->peLast, 
+                   AdjThrStateElement->dynBitsLast);
+  grantedPeCorr = (grantedPe * AdjThrStateElement->peCorrectionFactor) / 100;
+
+     
+  if (grantedPeCorr < noRedPe && noRedPe > peData.offset) {
+    /* calc threshold necessary for desired pe */
+    adaptThresholdsToPe(psyOutChannel,
+                        psyOutElement,
+                        logSfbEnergy,
+                        &peData,
+                        nChannels,
+                        grantedPeCorr,
+                        &AdjThrStateElement->ahParam,
+                        &AdjThrStateElement->minSnrAdaptParam);
+  }
+
+  /* calculate relative distribution */
+  for (ch=0; ch<nChannels; ch++) {
+    Word16 peOffsDiff = peData.pe - peData.offset;
+    chBitDistribution[ch] = 200;                                                 
+     
+    if (peOffsDiff > 0) {
+      Word32 temp = 1000 - (nChannels * 200);
+      chBitDistribution[ch] = chBitDistribution[ch] +

+		  (temp * peData.peChannelData[ch].pe) / peOffsDiff;
+    }
+  }
+
+  /* store pe */
+  qcOE->pe = noRedPe;                                                            
+
+  /* update last pe */
+  AdjThrStateElement->peLast = grantedPe;                                        
+}
+
+/********************************************************************************
+*
+* function name: AdjThrUpdate
+* description:  save dynBitsUsed for correction of bits2pe relation
+*
+**********************************************************************************/
+void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement,
+                  const Word16 dynBitsUsed)
+{
+  AdjThrStateElement->dynBitsLast = dynBitsUsed;                                 
+}
+
+
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s
new file mode 100644
index 0000000..48edd4f
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s
@@ -0,0 +1,167 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		AutoCorrelation_v5.s

+@

+@	Content:	AutoCorrelation function armv5 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+

+

+	.section .text	

+	.global	AutoCorrelation

+

+AutoCorrelation:

+	stmdb     sp!, {r4 - r11, lr}

+

+  sub     r13, r13, #20                     

+

+  mov     r5, r0                            

+  mov     r7, r1                            

+  mov     r9, r3                            

+  mov     r2, r2, lsl #16                      

+  mov     r0, #0          

+  mov     r4, r2, asr #16                   

+  mov     r8, #0                            

+  cmp     r4, #0                            

+  ble     L136        

+	

+	cmp     r4, #8 

+	mov		  r2, #0 

+  blt     L133   

+

+	sub     r12, r4, #8                

+L132:  

+  ldr     r6, [r5, r2]  

+	add		  r2, r2, #4

+	smulbb  r3, r6, r6

+	ldr     r1, [r5, r2] 

+	smultt	r10, r6, r6

+	mov		  r3, r3, asr #9

+	smulbb	r6, r1, r1

+	mov		  r10, r10, asr #9

+	qadd	  r0, r0, r3

+	smultt	r11, r1, r1

+	add     r2, r2, #4

+	qadd	  r0, r0, r10

+	mov		  r6, r6, asr #9

+	mov		  r11, r11, asr #9

+	ldr		  r1, [r5, r2]

+	qadd	  r0, r0, r6

+	smulbb	r10, r1, r1

+	smultt	r6, r1, r1

+	qadd	  r0, r0, r11

+	mov		  r10, r10, asr #9

+	mov		  r6, r6, asr #9

+	qadd	  r0, r0, r10

+	add     r2, r2, #4

+	add     r8, r8, #6

+

+	qadd	  r0, r0, r6

+	cmp     r8, r12                            

+  blt     L132	                  

+L133:                         

+  ldrsh   r6, [r5, r2]                      

+  mul     r10, r6, r6   

+	add     r2, r2, #2                     

+  mov     r1, r10, asr #9                    

+  qadd    r0, r0, r1

+L134:                         

+  add     r8, r8, #1                        

+  cmp     r8, r4                            

+  blt     L133                            

+L135:                        

+L136:                         

+  str     r0, [r7, #0]                      

+  cmp     r0, #0                            

+  beq     L1320                           

+L137:                         

+  mov     r2, r9, lsl #16                   

+	mov     r8, #1                                

+  mov     r2, r2, asr #16                   

+  cmp     r2, #1                            

+  ble     L1319                           

+L138:                        

+L139:                         

+  sub     r4, r4, #1                        

+  mov     r14, #0                           

+  mov     r3, #0                            

+  cmp     r4, #0                            

+  ble     L1317                           

+L1310:                       

+  cmp     r4, #6                            

+  addlt   r6, r5, r8, lsl #1                

+  blt     L1314                           

+L1311:                        

+  add     r6, r5, r8, lsl #1                

+  sub     r12, r4, #6                       

+  str     r8, [r13, #8]                     

+  str     r7, [r13, #4]                     

+L1312:                        

+  mov     r1, r3, lsl #1                    

+  ldrsh   r7, [r6, r1]                      

+  ldrsh   r10, [r5, r1]  

+  add     r8, r1, r6 

+	add     r9, r5, r1                       

+	mul     r7, r10, r7

+  ldrsh   r1, [r8, #2] 

+	ldrsh   r10, [r8, #4]   

+  add     r7, r14, r7, asr #9  	                                             

+  ldrsh   r0, [r9, #2]                          

+  ldrsh   r11, [r9, #4]                   

+  mul     r1, r0, r1                        

+  ldrsh   r14, [r8, #6]                     

+  mul     r10, r11, r10          

+	add     r7, r7, r1, asr #9            

+  ldrsh   r8, [r8, #8] 

+	add     r3, r3, #5

+	ldrsh   r11, [r9, #6]                  

+  ldrsh   r1, [r9, #8]                      

+  mul     r14, r11, r14                     

+  add     r7, r7, r10, asr #9       

+  mul     r1, r1, r8                             

+  add     r14, r7, r14, asr #9              

+	cmp     r3, r12 

+  add     r14, r14, r1, asr #9              

+  ble     L1312                           

+L1313:                        

+  ldr     r8, [r13, #8]                     

+  ldr     r7, [r13, #4]                     

+L1314:                        

+L1315:                        

+  mov     r12, r3, lsl #1                   

+  ldrsh   r9, [r6, r12]                     

+  ldrsh   r12, [r5, r12]                    

+  add     r3, r3, #1                        

+  cmp     r3, r4                            

+  mul     r12, r12, r9                      

+  add     r14, r14, r12, asr #9             

+  blt     L1315                           

+L1316:                        

+L1317:                        

+  str     r14, [r7, +r8, lsl #2]            

+  add     r8, r8, #1                        

+  cmp     r8, r2                            

+  blt     L139   

+	                         

+L1319:

+L1320:

+	add     r13, r13, #20                    

+	ldmia   sp!, {r4 - r11, pc}

+

+	@ENDP  @ |AutoCorrelation|

+	.end

diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s
new file mode 100644
index 0000000..7997e98
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s
@@ -0,0 +1,112 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		CalcWindowEnergy_v5.s

+@

+@	Content:	CalcWindowEnergy function armv5 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+

+	.section .text

+	

+	.global	CalcWindowEnergy

+

+CalcWindowEnergy:

+	stmdb   sp!, {r4 - r11, lr}

+	sub     r13, r13, #20 

+

+  mov     r3, r3, lsl #16                         

+	ldr     r10, [r0, #168]                    @ states0 = blockSwitchingControl->iirStates[0];

+  mov     r3, r3, asr #16 

+	ldr     r11, [r0, #172]                    @ states1 = blockSwitchingControl->iirStates[1];

+

+	mov     r2, r2, lsl #16

+	ldr     r12, hiPassCoeff                   @ Coeff0 = hiPassCoeff[0];      

+  mov     r2, r2, asr #16

+	ldr     r14, hiPassCoeff + 4			         @ Coeff1 = hiPassCoeff[1];

+	

+	mov			r8, #0							               @ w=0

+	mov			r5, #0							               @ wOffset = 0;

+	

+BLOCK_BEGIN:

+	mov			r6, #0                             @ accuUE = 0; 

+	mov			r7, #0								             @ accuFE = 0; 

+	mov			r4, #0							               @ i=0

+		                   

+	str			r8, [r13, #4]	

+	str			r0, [r13, #8]	

+	str			r3, [r13, #12]

+	

+ENERGY_BEG:	

+	mov     r9, r5, lsl #1  

+	ldrsh   r9, [r1, r9]											@ tempUnfiltered = timeSignal[tidx];

+

+	add			r5, r5, r2												@ tidx = tidx + chIncrement;

+	

+	smulwb	r3, r14, r9												@ accu1 = L_mpy_ls(Coeff1, tempUnfiltered);	

+	smull		r0, r8, r12, r11									@ accu2 = fixmul( Coeff0, states1 );

+	

+	mov			r3, r3, lsl #1

+	mov			r8, r8, lsl #1

+

+	sub			r0, r3, r10												@ accu3 = accu1 - states0;	

+	sub			r8,	r0, r8												@ out = accu3 - accu2;

+

+	mov		  r10, r3														@ states0 = accu1;

+	mov		  r11, r8														@ states1 = out;  

+	

+	mul		  r3, r9, r9	

+	mov     r8, r8, asr #16

+	

+	add		  r4, r4, #1

+	add     r6, r6, r3, asr #7

+

+	mul		  r9, r8, r8	

+	ldr		  r3, [r13, #12]

+

+	add		  r7, r7, r9, asr #7

+		

+	cmp     r4, r3                            

+  blt     ENERGY_BEG       

+	

+	ldr		  r0, [r13, #8]

+	ldr		  r8, [r13, #4]

+	

+ENERGY_END:

+	add		  r4, r0, r8, lsl #2

+

+	str     r6, [r4, #72]         

+	add		  r8, r8, #1	           

+  str     r7, [r4, #136]                   

+

+	cmp		  r8, #8

+	blt		  BLOCK_BEGIN                  	                        

+

+BLOCK_END:

+	str     r10, [r0, #168]                    

+  str     r11, [r0, #172]                    

+  mov     r0, #1            

+	                

+  add     r13, r13, #20   

+	ldmia   sp!, {r4 - r11, pc}                  

+

+hiPassCoeff:

+	.word 0xbec8b439

+	.word	0x609d4952

+		

+	@ENDP

+	.end

diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s
new file mode 100644
index 0000000..d4d3edb
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s
@@ -0,0 +1,131 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		PrePostMDCT_v5.s

+@

+@	Content:	premdct and postmdct function armv5 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+

+	.section .text

+	.global	PreMDCT

+

+PreMDCT:

+	stmdb       sp!, {r4 - r11, lr}

+	

+	add         r9, r0, r1, lsl #2

+	sub         r3, r9, #8

+

+	movs        r1, r1, asr #2

+	beq         PreMDCT_END

+	

+PreMDCT_LOOP:

+	ldr					r8, [r2], #4

+	ldr					r9, [r2], #4

+	

+	ldrd				r4, [r0]

+	ldrd				r6, [r3]

+	

+	smull				r14, r11, r4, r8					@ MULHIGH(tr1, cosa)

+	smull    			r10, r12, r7, r8					@ MULHIGH(ti1, cosa)

+		

+	smull				r14, r8, r7, r9						@ MULHIGH(ti1, sina)

+	smull				r7, r10, r4, r9						@ MULHIGH(tr1, sina)	

+		

+	add					r11, r11, r8						@ MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@	

+	sub					r7, r12, r10						@ MULHIGH(ti1, cosa) - MULHIGH(tr1, sina)

+	

+	ldr					r8, [r2], #4

+	ldr					r9, [r2], #4

+	

+	smull				r14, r4, r6, r8						@ MULHIGH(tr2, cosa)

+	smull    			r10, r12, r5, r8					@ MULHIGH(ti2, cosa)

+		

+	smull				r14, r8, r5, r9						@ MULHIGH(ti2, sina)

+	smull				r5, r10, r6, r9						@ MULHIGH(tr2, sina)

+	

+	add					r8, r8, r4

+	sub					r9, r12, r10

+	

+	mov					r6, r11		

+

+	strd				r6, [r0]	

+	strd				r8, [r3]

+	

+	subs				r1, r1, #1

+	sub					r3, r3, #8

+	add 				r0, r0, #8

+	bne					PreMDCT_LOOP

+

+PreMDCT_END:

+	ldmia       sp!, {r4 - r11, pc}

+	@ENDP  @ |PreMDCT|

+	

+	.section .text

+	.global	PostMDCT

+

+PostMDCT:

+	stmdb       sp!, {r4 - r11, lr}

+	

+	add         r9, r0, r1, lsl #2

+	sub         r3, r9, #8

+

+	movs        r1, r1, asr #2

+	beq         PostMDCT_END

+	

+PostMDCT_LOOP:

+	ldr					r8, [r2], #4					

+	ldr					r9, [r2], #4

+	

+	ldrd				r4, [r0]

+	ldrd				r6, [r3]

+	

+	smull				r14, r11, r4, r8					@ MULHIGH(tr1, cosa)

+	smull    			r10, r12, r5, r8					@ MULHIGH(ti1, cosa)

+		

+	smull				r14, r8, r5, r9						@ MULHIGH(ti1, sina)

+	smull				r5, r10, r4, r9						@ MULHIGH(tr1, sina)	

+		

+	add					r4, r11, r8							@ MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@	

+	sub					r11, r10, r12						@ MULHIGH(ti1, cosa) - MULHIGH(tr1, sina)@

+	

+	ldr					r8, [r2], #4						@

+	ldr					r9, [r2], #4

+	

+	smull				r14, r5, r6, r8						@ MULHIGH(tr2, cosa)

+	smull    			r10, r12, r7, r8					@ MULHIGH(ti2, cosa)

+		

+	smull				r14, r8, r7, r9						@ MULHIGH(ti2, sina)

+	smull				r7, r10, r6, r9						@ MULHIGH(tr2, sina)

+	

+	add					r6, r8, r5							@ MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2)@

+	sub					r5, r10, r12						@ MULHIGH(sinb, tr2) - MULHIGH(cosb, ti2)@

+	

+	mov					r7, r11				

+

+	strd				r4, [r0]

+	strd				r6, [r3]

+	

+	subs				r1, r1, #1

+	sub					r3, r3, #8

+	add 				r0, r0, #8

+	bne					PostMDCT_LOOP

+

+PostMDCT_END:

+	ldmia       sp!, {r4 - r11, pc}

+	@ENDP  @ |PostMDCT|

+	.end
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s
new file mode 100644
index 0000000..370daf4
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s
@@ -0,0 +1,252 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		R4R8First_v5.s

+@

+@	Content:	Radix8First and Radix4First function armv5 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+

+	.section .text

+	.global	Radix4First

+

+Radix4First:

+	stmdb       sp!, {r4 - r11, lr}

+	

+	movs				r10, r1

+	mov					r11, r0

+	beq					Radix4First_END

+		

+Radix4First_LOOP:

+	ldrd				r0, [r11]

+	ldrd				r2, [r11, #8]

+	ldrd				r4, [r11, #16]

+	ldrd				r6, [r11, #24]

+	

+	add					r8, r0, r2

+	add					r9, r1, r3

+	

+	sub					r0, r0, r2

+	sub					r1, r1, r3

+	

+	add					r2, r4, r6

+	add					r3, r5, r7

+	

+	sub					r4, r4, r6

+	sub					r5, r5, r7

+	

+	add					r6, r8, r2

+	add					r7, r9, r3

+	

+	sub					r8, r8, r2

+	sub					r9, r9, r3

+	

+	add					r2, r0, r5

+	sub					r3, r1, r4

+	

+	sub					r0, r0, r5

+	add					r1, r1, r4

+	

+	strd				r6, [r11]

+	strd				r2, [r11, #8]

+	strd				r8, [r11, #16]

+	strd				r0, [r11, #24]

+	

+	subs				r10, r10, #1

+	add					r11, r11, #32

+	bne					Radix4First_LOOP

+

+Radix4First_END:

+	ldmia       sp!, {r4 - r11, pc}

+	@ENDP  @ |Radix4First|

+	

+	.section .text

+	.global	Radix8First

+

+Radix8First:

+	stmdb       sp!, {r4 - r11, lr}

+	sub         sp, sp, #0x24

+	

+	mov				  r12, r1

+	mov					r14, r0

+	cmp					r12, #0

+	beq					Radix8First_END

+	

+Radix8First_LOOP:

+	ldrd				r0, [r14]		

+	ldrd				r2, [r14, #8]

+	ldrd				r4, [r14, #16]

+	ldrd				r6, [r14, #24]

+	

+	add					r8, r0, r2					@ r0 = buf[0] + buf[2]@

+	add					r9, r1, r3					@ i0 = buf[1] + buf[3]@

+	

+	sub					r0, r0, r2					@ r1 = buf[0] - buf[2]@

+	sub					r1, r1, r3					@ i1 = buf[1] - buf[3]@

+	

+	add					r2, r4, r6					@	r2 = buf[4] + buf[6]@

+	add					r3, r5, r7					@ i2 = buf[5] + buf[7]@

+	

+	sub					r4, r4, r6					@	r3 = buf[4] - buf[6]@

+	sub					r5, r5, r7					@ i3 = buf[5] - buf[7]@

+	

+	add					r6, r8, r2					@ r4 = (r0 + r2) >> 1@

+	add					r7, r9, r3					@ i4 = (i0 + i2) >> 1@

+	

+	sub					r8, r8, r2					@	r5 = (r0 - r2) >> 1@

+	sub					r9, r9, r3					@ i5 = (i0 - i2) >> 1@

+	

+	sub					r2, r0, r5					@ r6 = (r1 - i3) >> 1@

+	add					r3, r1, r4					@ i6 = (i1 + r3) >> 1@

+	

+	add					r0, r0, r5					@ r7 = (r1 + i3) >> 1@

+	sub					r1, r1, r4					@ i7 = (i1 - r3) >> 1@

+	

+	mov					r6, r6, asr #1			@

+	mov					r7, r7, asr #1			@

+	

+	mov					r8, r8, asr #1

+	mov					r9, r9, asr #1

+	

+	mov					r2, r2, asr #1

+	mov					r3, r3, asr #1

+	

+	mov					r0, r0, asr #1

+	mov					r1, r1, asr #1	

+	

+	str					r6, [sp]

+	str					r7, [sp, #4]

+	

+	str					r8, [sp, #8]

+	str					r9, [sp, #12]

+	

+	str					r2, [sp, #16]

+	str					r3, [sp, #20]	

+	

+	str					r0, [sp, #24]

+	str					r1, [sp, #28]	

+	

+	ldrd				r2, [r14, #32]		

+	ldrd				r4, [r14, #40]

+	ldrd				r6, [r14, #48]

+	ldrd				r8, [r14, #56]

+	

+	add					r0, r2, r4					@ r0 = buf[ 8] + buf[10]@

+	add					r1, r3, r5					@ i0 = buf[ 9] + buf[11]@

+	

+	sub					r2, r2, r4					@ r1 = buf[ 8] - buf[10]@

+	sub					r3, r3, r5					@ i1 = buf[ 9] - buf[11]@

+	

+	add					r4, r6, r8					@ r2 = buf[12] + buf[14]@

+	add					r5, r7, r9					@ i2 = buf[13] + buf[15]@

+	

+	sub					r6, r6, r8					@ r3 = buf[12] - buf[14]@

+	sub					r7, r7, r9					@	i3 = buf[13] - buf[15]@

+	

+	add					r8, r0, r4					@ t0 = (r0 + r2)

+	add					r9, r1, r5					@ t1 = (i0 + i2)

+	

+	sub					r0, r0, r4					@ t2 = (r0 - r2)

+	sub					r1, r1, r5					@ t3 = (i0 - i2)

+	

+	mov					r8, r8, asr #1

+	ldr					r4, [sp]

+	

+	mov					r9, r9, asr #1

+	ldr					r5, [sp, #4]

+	

+	mov					r0, r0, asr #1		

+	mov					r1, r1, asr #1

+	

+	add					r10, r4, r8					@ buf[ 0] = r4 + t0@

+	add					r11, r5, r9					@ buf[ 1] = i4 + t1@

+	

+	sub					r4,  r4, r8					@ buf[ 8] = r4 - t0@

+	sub					r5,  r5, r9					@	buf[ 9] = i4 - t1@

+	

+ 	strd				r10, [r14]

+ 	strd				r4,  [r14, #32]

+ 	

+ 	ldr					r10, [sp, #8]

+ 	ldr					r11, [sp, #12]

+ 	

+ 	add					r4, r10, r1					@ buf[ 4] = r5 + t3@

+ 	sub					r5, r11, r0					@	buf[ 5] = i5 - t2@

+ 	

+ 	sub					r10, r10, r1				@ buf[12] = r5 - t3@

+ 	add					r11, r11, r0				@ buf[13] = i5 + t2@

+ 	

+ 	strd				r4,  [r14, #16]

+ 	strd				r10, [r14, #48]

+ 	

+ 	sub					r0, r2, r7					@ r0 = r1 - i3@

+ 	add					r1, r3, r6					@ i0 = i1 + r3@

+ 

+  ldr					r11, DATATab

+ 	

+ 	add					r2, r2, r7					@ r2 = r1 + i3@

+ 	sub					r3, r3, r6					@ i2 = i1 - r3@

+ 	

+	sub					r4, r0, r1					@ r0 - i0

+	add					r5, r0, r1					@ r0 + i0

+	

+	sub					r0, r2, r3					@ r2 - i2

+	add					r1, r2, r3					@ r2 + i2

+	

+	smull				r8, r6, r4, r11								

+	smull				r9, r7, r5, r11								

+	

+	ldr					r2, [sp, #16]

+	ldr					r3, [sp, #20]

+	

+	smull				r8, r4, r0, r11								

+	smull				r9, r5, r1, r11								

+	

+	ldr					r10, [sp, #24]

+	ldr					r11, [sp, #28]

+	

+	sub					r8, r2, r6

+	sub					r9, r3, r7

+	

+	add					r2, r2, r6

+	add					r3, r3, r7

+	

+	add					r6, r10, r5

+	sub					r7, r11, r4

+	

+	sub					r0, r10, r5

+	add					r1, r11, r4

+	

+	strd				r6, [r14, #8]

+	strd				r8, [r14, #24]

+	strd				r0, [r14, #40]

+	strd				r2, [r14, #56]

+	

+	subs				r12, r12, #1

+	add					r14, r14, #64

+	

+	bne					Radix8First_LOOP

+	

+Radix8First_END:

+	add         sp, sp, #0x24

+	ldmia       sp!, {r4 - r11, pc}

+	

+DATATab:

+	.word       0x5a82799a

+	

+	@ENDP  @ |Radix8First|

+	.end
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s
new file mode 100644
index 0000000..db8e5d8
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s
@@ -0,0 +1,169 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		Radix4FFT_v5.s

+@

+@	Content:	Radix4FFT armv5 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+	.section .text

+	.global	Radix4FFT

+

+Radix4FFT:

+	stmdb     sp!, {r4 - r11, lr}

+	sub       sp, sp, #32                     

+

+	mov			r1, r1, asr #2

+	cmp     r1, #0       

+	beq     Radix4FFT_END                            

+                       

+Radix4FFT_LOOP1:          

+	mov     r14, r0          							@ xptr = buf@          

+	mov		r10, r1 												@ i = num@

+	mov     r9, r2, lsl #3  							@ step = 2*bgn@

+	cmp     r10, #0  

+	str		r0, [sp] 

+	str		r1, [sp, #4]      

+	str		r2, [sp, #8]

+	str		r3, [sp, #12]  

+	beq     Radix4FFT_LOOP1_END                            	    

+     

+Radix4FFT_LOOP2:                       

+	mov     r12, r3				        				@ csptr = twidTab@

+	mov		r11, r2												@ j = bgn

+	cmp     r11, #0        

+	str		r10, [sp, #16]

+	beq     Radix4FFT_LOOP2_END                         

+	 

+Radix4FFT_LOOP3:                          

+	str			r11, [sp, #20]	 

+	

+	ldrd		r0, [r14, #0]									@ r0 = xptr[0]@ r1 = xptr[1]@

+	add			r14, r14, r9 	 								@ xptr += step@

+	

+	ldrd		r10,	[r14, #0]  					 			@ r2 = xptr[0]@ r3 = xptr[1]@	

+	ldr			r8, [r12], #4									@ cosxsinx = csptr[0]@

+	

+	smulwt	r4, r10, r8										@ L_mpy_wx(cosx, t0)

+	smulwt	r3, r11, r8										@ L_mpy_wx(cosx, t1)

+	

+	smlawb	r2, r11, r8, r4								@ r2 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@

+	smulwb	r5, r10, r8										@ L_mpy_wx(sinx, t0)

+	

+	mov			r10, r0, asr #2								@ t0 = r0 >> 2@

+	mov			r11, r1, asr #2								@	t1 = r1 >> 2@

+		

+	sub			r3, r3, r5										@ r3 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@

+	add     r14, r14, r9 	 								@ xptr += step@

+	

+	sub			r0, r10, r2										@ r0 = t0 - r2@

+	sub			r1, r11, r3									  @ r1 = t1 - r3@

+	

+	add			r2, r10, r2										@ r2 = t0 + r2@

+	add			r3, r11, r3										@ r3 = t1 + r3@

+	

+	str			r2, [sp, #24]

+	str			r3, [sp, #28]

+	

+	ldrd		r10, [r14, #0]								@ r4 = xptr[0]@ r5 = xptr[1]@

+	ldr			r8, [r12], #4									@ cosxsinx = csptr[1]@

+	

+	smulwt	r6, r10, r8										@ L_mpy_wx(cosx, t0)

+	smulwt	r5, r11, r8										@ L_mpy_wx(cosx, t1)

+	

+	smlawb	r4, r11, r8, r6								@ r4 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@

+	smulwb	r7, r10, r8										@ L_mpy_wx(sinx, t0)

+	

+	add			r14, r14, r9									@ xptr += step@

+	sub			r5, r5, r7										@ r5 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@

+		

+	ldrd		r10, [r14]										@ r6 = xptr[0]@ r7 = xptr[1]@

+	ldr			r8, [r12], #4									@ cosxsinx = csptr[1]@

+	

+	smulwt	r2, r10, r8										@ L_mpy_wx(cosx, t0)

+	smulwt	r7, r11, r8										@ L_mpy_wx(cosx, t1)

+	

+	smlawb	r6, r11, r8, r2								@ r4 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@

+	smulwb	r3, r10, r8										@ L_mpy_wx(sinx, t0)

+	

+	mov			r10, r4												@ t0 = r4@

+	mov			r11, r5												@ t1 = r5@	

+	

+	sub			r7, r7, r3										@ r5 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@

+	

+

+	add			r4,  r10, r6									@	r4 = t0 + r6@	

+	sub			r5, r7, r11										@ r5 = r7 - t1@

+	

+	sub			r6, r10, r6										@ r6 = t0 - r6@

+	add			r7, r7, r11										@ r7 = r7 + t1@

+	

+	ldr			r2, [sp, #24]

+	ldr			r3, [sp, #28]

+	

+	add			r10, r0, r5										@ xptr[0] = r0 + r5@

+	add			r11, r1, r6										@ xptr[0] = r1 + r6

+	

+	strd		r10, [r14]										

+	sub			r14, r14, r9									@ xptr -= step@

+	

+	sub			r10, r2, r4										@	xptr[0] = r2 - r4@

+	sub			r11, r3, r7										@ xptr[1] = r3 - r7@

+	

+	strd		r10, [r14]				

+	sub			r14, r14, r9									@ xptr -= step@

+	

+	sub			r10, r0, r5										@ xptr[0] = r0 - r5@

+	sub			r11, r1, r6										@ xptr[0] = r1 - r6

+	

+	strd		r10, [r14]										

+	sub			r14, r14, r9									@ xptr -= step@

+	

+	add			r10, r2, r4										@	xptr[0] = r2 - r4@

+	add			r11, r3, r7										@ xptr[1] = r3 - r7@

+	

+	strd		r10, [r14]				

+	add			r14, r14, #8									@ xptr += 2@

+	

+	ldr			r11, [sp, #20]

+	subs		r11, r11, #1

+	bne			Radix4FFT_LOOP3	

+	 

+Radix4FFT_LOOP2_END:           

+	ldr			r10, [sp, #16]

+	ldr			r3, [sp, #12]

+	ldr			r2, [sp, #8]

+	rsb			r8, r9, r9, lsl #2   

+	sub			r10, r10, #1

+	add			r14, r14, r8		      

+	cmp			r10, #0  

+	bhi     Radix4FFT_LOOP2           

+                        

+Radix4FFT_LOOP1_END:               

+	ldr     r0, [sp]    

+	ldr		r1, [sp, #4]

+	add     r3, r3, r8, asr #1

+	mov     r2, r2, lsl #2 

+	movs    r1, r1, asr #2 

+	bne     Radix4FFT_LOOP1          

+                        

+Radix4FFT_END:                        

+	add     sp, sp, #32                  

+	ldmia   sp!, {r4 - r11, pc}

+		

+	@ENDP  @ |Radix4FFT|

+	.end
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s
new file mode 100644
index 0000000..a463dfd
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s
@@ -0,0 +1,204 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		band_nrg_v5.s

+@

+@	Content:	CalcBandEnergy and CalcBandEnergyMS function armv5 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+

+	.section .text

+

+	.global	CalcBandEnergy

+

+CalcBandEnergy:

+	stmdb   sp!, {r4 - r11, lr}	

+                   

+  mov     r2, r2, lsl #16                   

+	ldr     r12, [r13, #36]

+	mov			r9, #0

+  mov     r5, r2, asr #16    

+	mov			r4, #0               

+  cmp     r5, #0	

+	ble     L212 

+

+L22:

+  mov     r2, r4, lsl #1                    

+  ldrsh   r10, [r1, r2]                     

+  add     r11, r1, r2                       

+  ldrsh   r2, [r11, #2]    

+	mov     r14, #0                 

+  cmp     r10, r2                           

+  bge     L28 

+	

+L23:

+	ldr     r11, [r0, +r10, lsl #2]	

+  add     r10, r10, #1    

+	ldr     r6, [r0, +r10, lsl #2]	

+	smull   r11, r7, r11, r11

+	add     r10, r10, #1 

+	smull	  r6, r8, r6, r6

+	ldr     r11, [r0, +r10, lsl #2]

+	qadd	  r14, r14, r7

+	add     r10, r10, #1

+	smull	  r11, r7, r11, r11

+	ldr     r6, [r0, +r10, lsl #2]

+	qadd	  r14, r14, r8

+	smull	  r6, r8, r6, r6

+  add     r10, r10, #1 

+	qadd	  r14, r14, r7

+	cmp     r10, r2

+	qadd	  r14, r14, r8

+	blt     L23   

+

+L28:	

+	qadd	  r14, r14, r14

+	str     r14, [r3, +r4, lsl #2]

+	add     r4, r4, #1 

+	qadd	  r9, r9, r14

+	cmp     r4, r5                          

+

+  blt     L22       	

+

+L212:	

+	str     r9, [r12, #0]                     

+	ldmia   sp!, {r4 - r11, pc}

+	

+	@ENDP  ; |CalcBandEnergy|

+	

+	.global	CalcBandEnergyMS

+

+CalcBandEnergyMS:

+	stmdb   sp!, {r4 - r11, lr}

+	sub     r13, r13, #24

+	

+	mov     r12, #0 

+  mov     r3, r3, lsl #16  

+  mov     r14, #0 

+	mov     r3, r3, asr #16      

+	cmp     r3, #0          

+	mov		  r4, #0                  

+  ble     L315    

+	

+L32:	

+	mov		  r5, r4, lsl #1

+	mov		  r6, #0

+	ldrsh   r10, [r2, r5]

+	add     r5, r2, r5

+	mov		  r7, #0

+	ldrsh	  r11, [r5, #2]                        

+	cmp     r10, r11                          

+  bge     L39    

+

+	str		  r3, [r13, #4]

+	str		  r4, [r13, #8]

+	str		  r12, [r13, #12]

+	str		  r14, [r13, #16]

+

+L33:	

+	ldr     r8, [r0, +r10, lsl #2]                    

+	ldr     r9, [r1, +r10, lsl #2]

+	mov		  r8, r8, asr #1

+	add		  r10, r10, #1

+	mov		  r9, r9, asr #1

+

+	ldr     r12, [r0, +r10, lsl #2]          

+	add		  r5, r8, r9	          

+	ldr     r14, [r1, +r10, lsl #2]

+	sub		  r8, r8, r9

+

+	smull   r5, r3, r5, r5 

+	mov		  r12, r12, asr #1

+	smull   r8, r4, r8, r8 

+	mov		  r14, r14, asr #1

+

+	qadd	  r6, r6, r3

+	add		  r5, r12, r14

+	qadd	  r7, r7, r4

+	sub		  r8, r12, r14

+

+	smull   r5, r3, r5, r5 

+	add		  r10, r10, #1

+	smull   r8, r4, r8, r8 

+		

+	qadd	  r6, r6, r3

+	qadd	  r7, r7, r4

+

+	ldr     r8, [r0, +r10, lsl #2]                    

+	ldr     r9, [r1, +r10, lsl #2]

+	mov		  r8, r8, asr #1

+	add		  r10, r10, #1

+	mov		  r9, r9, asr #1

+

+	ldr     r12, [r0, +r10, lsl #2]          

+	add		  r5, r8, r9	          

+	ldr     r14, [r1, +r10, lsl #2]

+	sub		  r8, r8, r9

+

+	smull   r5, r3, r5, r5 

+	mov		  r12, r12, asr #1

+	smull   r8, r4, r8, r8 

+	mov		  r14, r14, asr #1

+

+	qadd	  r6, r6, r3

+	add		  r5, r12, r14

+	qadd	  r7, r7, r4

+	sub		  r8, r12, r14

+

+	smull   r5, r3, r5, r5 

+	add		  r10, r10, #1

+	smull   r8, r4, r8, r8 

+		

+	qadd	  r6, r6, r3

+	qadd	  r7, r7, r4

+

+	cmp     r10, r11

+	

+	blt		  L33

+

+	ldr		  r3, [r13, #4]

+	ldr		  r4, [r13, #8]	

+	ldr		  r12, [r13, #12]

+	ldr		  r14, [r13, #16]

+L39:	

+	qadd	  r6, r6, r6

+	qadd	  r7, r7, r7	

+	

+	ldr		  r8, [r13, #60]

+	ldr		  r9, [r13, #68]

+

+	qadd	  r12, r12, r6

+	qadd	  r14, r14, r7

+	

+	str		  r6, [r8, +r4, lsl #2]       

+	str     r7, [r9, +r4, lsl #2]    

+	

+	add		  r4, r4, #1

+	cmp		  r4, r3

+	blt     L32            

+

+L315:

+	ldr		  r8, [r13, #64]

+	ldr		  r9, [r13, #72]

+	str		  r12, [r8, #0]

+	str		  r14, [r9, #0]

+

+	add     r13, r13, #24

+	ldmia   sp!, {r4 - r11, pc}

+	@ENDP  ; |CalcBandEnergyMS|

+

+	.end

diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s
new file mode 100644
index 0000000..bf7dcba
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s
@@ -0,0 +1,135 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		PrePostMDCT_v7.s

+@

+@	Content:	premdct and postmdct function armv7 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+

+	.section .text

+	.global	PreMDCT

+

+PreMDCT:

+	stmdb     sp!, {r4 - r11, lr}

+	

+	add         r9, r0, r1, lsl #2

+	sub         r3, r9, #32

+

+	movs        r1, r1, asr #2

+	beq         PreMDCT_END	

+	

+PreMDCT_LOOP:

+	VLD4.I32			{d0, d2, d4, d6}, [r2]!				@ cosa = *csptr++@ sina = *csptr++@

+	VLD4.I32			{d1, d3, d5, d7}, [r2]!				@ cosb = *csptr++@ sinb = *csptr++@

+	VLD2.I32			{d8, d9, d10, d11}, [r0]			@ tr1 = *(buf0 + 0)@ ti2 = *(buf0 + 1)@

+	VLD2.I32			{d13, d15}, [r3]!					@ tr2 = *(buf1 - 1)@ ti1 = *(buf1 + 0)@

+	VLD2.I32			{d12, d14}, [r3]!					@ tr2 = *(buf1 - 1)@ ti1 = *(buf1 + 0)@

+		

+	VREV64.32			Q8, Q7	

+	VREV64.32			Q9, Q6

+

+	

+	VQDMULH.S32		Q10, Q0, Q4								@ MULHIGH(cosa, tr1)

+	VQDMULH.S32		Q11, Q1, Q8								@ MULHIGH(sina, ti1)

+	VQDMULH.S32		Q12, Q0, Q8								@ MULHIGH(cosa, ti1)

+	VQDMULH.S32		Q13, Q1, Q4								@ MULHIGH(sina, tr1)

+		

+	VADD.S32			Q0, Q10, Q11						@ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@

+	VSUB.S32			Q1, Q12, Q13						@ *buf0++ = MULHIGH(cosa, ti1) - MULHIGH(sina, tr1)@

+	

+	VST2.I32			{d0, d1, d2, d3}, [r0]!

+	sub						r3, r3, #32

+	

+	VQDMULH.S32		Q10, Q2, Q9										@ MULHIGH(cosb, tr2)

+	VQDMULH.S32		Q11, Q3, Q5										@ MULHIGH(sinb, ti2)

+	VQDMULH.S32		Q12, Q2, Q5										@ MULHIGH(cosb, ti2)

+	VQDMULH.S32		Q13, Q3, Q9										@ MULHIGH(sinb, tr2)

+		

+	VADD.S32			Q0, Q10, Q11									@ MULHIGH(cosa, tr2) + MULHIGH(sina, ti2)@

+	VSUB.S32			Q1, Q12, Q13									@ MULHIGH(cosa, ti2) - MULHIGH(sina, tr2)@

+	

+	VREV64.32			Q3, Q1

+	VREV64.32			Q2, Q0

+		

+	VST2.I32		{d5, d7}, [r3]!	

+	VST2.I32		{d4, d6}, [r3]! 

+	

+	subs     		r1, r1, #4

+	sub		  		r3, r3, #64	

+	bne       	PreMDCT_LOOP

+	

+PreMDCT_END:

+	ldmia     sp!, {r4 - r11, pc}

+	@ENDP  @ |PreMDCT|

+

+	.section .text

+	.global	PostMDCT

+

+PostMDCT:

+	stmdb     sp!, {r4 - r11, lr}

+	

+	add         r9, r0, r1, lsl #2

+	sub         r3, r9, #32

+

+	movs        r1, r1, asr #2

+	beq         PostMDCT_END

+	

+PostMDCT_LOOP:

+	VLD4.I32			{d0, d2, d4, d6}, [r2]!				@ cosa = *csptr++@ sina = *csptr++@

+	VLD4.I32			{d1, d3, d5, d7}, [r2]!				@ cosb = *csptr++@ sinb = *csptr++@

+	VLD2.I32			{d8, d9, d10, d11}, [r0]			@ tr1 = *(zbuf1 + 0)@ ti1 = *(zbuf1 + 1)@

+	VLD2.I32			{d13, d15}, [r3]!							@ tr2 = *(zbuf2 - 1)@ ti2 = *(zbuf2 + 0)@

+	VLD2.I32			{d12, d14}, [r3]!							@ tr2 = *(zbuf2 - 1)@ ti2 = *(zbuf2 + 0)@	

+

+	VREV64.32			Q8, Q6	

+	VREV64.32			Q9, Q7			

+	

+	VQDMULH.S32		Q10, Q0, Q4										@ MULHIGH(cosa, tr1)

+	VQDMULH.S32		Q11, Q1, Q5										@ MULHIGH(sina, ti1)

+	VQDMULH.S32		Q12, Q0, Q5										@ MULHIGH(cosa, ti1)

+	VQDMULH.S32		Q13, Q1, Q4										@ MULHIGH(sina, tr1)

+		

+	VADD.S32			Q0, Q10, Q11									@ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@

+	VSUB.S32			Q5, Q13, Q12									@ *buf1-- = MULHIGH(sina, tr1) - MULHIGH(cosa, ti1)@

+	

+	VQDMULH.S32		Q10, Q2, Q8										@ MULHIGH(cosb, tr2)

+	VQDMULH.S32		Q11, Q3, Q9										@ MULHIGH(sinb, ti2)

+	VQDMULH.S32		Q12, Q2, Q9										@ MULHIGH(cosb, ti2)

+	VQDMULH.S32		Q13, Q3, Q8										@ MULHIGH(sinb, tr2)

+		

+	VADD.S32			Q4, Q10, Q11									@ *buf1-- = MULHIGH(cosa, tr2) + MULHIGH(sina, ti2)@

+	VSUB.S32			Q1, Q13, Q12									@ *buf0++ = MULHIGH(sina, tr2) - MULHIGH(cosa, ti2)@	

+	

+	VREV64.32			Q2, Q4

+	VREV64.32			Q3, Q5	

+	

+	sub						r3, r3, #32	

+	VST2.I32			{d0, d1, d2, d3}, [r0]!

+		

+	VST2.I32			{d5, d7}, [r3]!	

+	VST2.I32			{d4, d6}, [r3]! 

+	

+	subs     			r1, r1, #4

+	sub		  			r3, r3, #64		

+	bne       	PostMDCT_LOOP

+

+PostMDCT_END:

+	ldmia     sp!, {r4 - r11, pc}

+

+	@ENDP  		@ |PostMDCT|

+	.end
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s
new file mode 100644
index 0000000..99ee68b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s
@@ -0,0 +1,146 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		R4R8First_v7.s

+@

+@	Content:	Radix8First and Radix4First function armv7 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+

+	.section .text

+	.global	Radix8First

+

+Radix8First:

+	stmdb     		sp!, {r4 - r11, lr}

+

+	ldr       		r3, SQRT1_2

+	cmp       		r1, #0

+	

+	VDUP.I32  		Q15, r3	

+	beq       		Radix8First_END

+	

+Radix8First_LOOP:

+	VLD1.I32			{d0, d1, d2, d3},	[r0]!

+	VLD1.I32			{d8, d9, d10, d11},	[r0]!

+		

+	VADD.S32			d4, d0, d1		@ r0 = buf[0] + buf[2]@i0 = buf[1] + buf[3]@

+	VSUB.S32			d5, d0, d1		@ r1 = buf[0] - buf[2]@i1 = buf[1] - buf[3]@	

+	VSUB.S32			d7, d2, d3		@ r2 = buf[4] - buf[6]@i2 = buf[5] - buf[7]@	

+	VADD.S32			d6, d2, d3		@ r3 = buf[4] + buf[6]@i3 = buf[5] + buf[7]@

+	VREV64.I32			d7, d7	

+	

+	VADD.S32			Q0, Q2, Q3		@ r4 = (r0 + r2)@i4 = (i0 + i2)@i6 = (i1 + r3)@r7 = (r1 + i3)

+	VSUB.S32			Q1, Q2, Q3		@ r5 = (r0 - r2)@i5 = (i0 - i2)@r6 = (r1 - i3)@i7 = (i1 - r3)@

+

+	VREV64.I32			d3, d3	

+

+	VADD.S32			d4, d8, d9		@ r0 = buf[ 8] + buf[10]@i0 = buf[ 9] + buf[11]@

+	VSUB.S32			d7, d10, d11	@ r1 = buf[12] - buf[14]@i1 = buf[13] - buf[15]@	

+	VADD.S32			d6, d10, d11	@ r2 = buf[12] + buf[14]@i2 = buf[13] + buf[15]@

+	VREV64.I32			d7, d7	

+	VSUB.S32			d5, d8, d9		@ r3 = buf[ 8] - buf[10]@i3 = buf[ 9] - buf[11]@

+	

+	VTRN.32				d1, d3	

+	

+	VADD.S32			Q4, Q2, Q3		@ t0 = (r0 + r2) >> 1@t1 = (i0 + i2) >> 1@i0 = i1 + r3@r2 = r1 + i3@

+	VSUB.S32			Q5, Q2, Q3		@ t2 = (r0 - r2) >> 1@t3 = (i0 - i2) >> 1@r0 = r1 - i3@i2 = i1 - r3@

+	

+	VREV64.I32			d3, d3

+	

+	VSHR.S32			d8, d8, #1		 

+	VSHR.S32			Q0, Q0, #1

+	VREV64.I32			d10, d10

+	VTRN.32				d11, d9

+	VSHR.S32			Q1, Q1, #1

+	VSHR.S32			d10, d10, #1

+	VREV64.I32			d9, d9

+	

+	sub       			r0, r0, #0x40

+	

+	VADD.S32			d12, d0, d8

+	VSUB.S32			d16, d0, d8	

+	VADD.S32			d14, d2, d10

+	VSUB.S32			d18, d2, d10

+	

+	VSUB.S32			d4, d11, d9

+	VADD.S32			d5, d11, d9

+	

+	VREV64.I32			d18, d18

+	

+	VQDMULH.S32			Q3, Q2, Q15

+	VTRN.32				d14, d18

+	VTRN.32				d6, d7

+	VREV64.I32			d18, d18	

+	

+	VSUB.S32			d15, d3, d6

+	VREV64.I32			d7, d7

+	VADD.S32			d19, d3, d6

+	VADD.S32			d13, d1, d7

+	VSUB.S32			d17, d1, d7

+	

+	VREV64.I32			d17, d17

+	VTRN.32				d13, d17

+	VREV64.I32			d17, d17

+	

+	subs       			r1, r1, #1	

+	

+	VST1.I32			{d12, d13, d14, d15}, [r0]!

+	VST1.I32			{d16, d17, d18, d19}, [r0]!	

+	bne       			Radix8First_LOOP

+	

+Radix8First_END:

+	ldmia     sp!, {r4 - r11, pc}	

+SQRT1_2:

+	.word      0x2d413ccd

+	

+	@ENDP  @ |Radix8First|

+	

+	.section .text

+	.global	Radix4First

+

+Radix4First:

+	stmdb     	sp!, {r4 - r11, lr}

+

+	cmp       	r1, #0

+	beq       	Radix4First_END

+	

+Radix4First_LOOP:

+	VLD1.I32			{d0, d1, d2, d3}, [r0]					

+	

+	VADD.S32			d4, d0, d1							@ r0 = buf[0] + buf[2]@ r1 = buf[1] + buf[3]@		

+	VSUB.S32			d5, d0, d1							@ r2 = buf[0] - buf[2]@ r3 = buf[1] - buf[3]@

+	VSUB.S32			d7, d2, d3							@ r4 = buf[4] + buf[6]@ r5 = buf[5] + buf[7]@

+	VADD.S32			d6, d2, d3							@ r6 = buf[4] - buf[6]@ r7 = buf[5] - buf[7]@

+	

+	VREV64.I32		d7, d7									@ 

+	

+	VADD.S32			Q4, Q2, Q3

+	VSUB.S32			Q5, Q2, Q3

+	

+	VREV64.I32		d11, d11

+	VTRN.32				d9, d11

+	subs       		r1, r1, #1	

+	VREV64.I32		d11, d11

+	VST1.I32			{d8, d9, d10, d11}, [r0]!

+

+	bne       		Radix4First_LOOP

+	

+Radix4First_END:

+	ldmia    		sp!, {r4 - r11, pc}

+

+	@ENDP  @ |Radix4First|

+	.end
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s
new file mode 100644
index 0000000..e1a8438
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s
@@ -0,0 +1,143 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+@	File:		Radix4FFT_v7.s

+@

+@	Content:	Radix4FFT armv7 assemble

+@

+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

+

+	.section .text

+	.global	Radix4FFT

+

+Radix4FFT:

+	stmdb    sp!, {r4 - r11, lr}

+

+	mov			r1, r1, asr #2

+	cmp     	r1, #0                            

+	beq     	Radix4FFT_END                            

+                        

+Radix4FFT_LOOP1:                         

+	mov     	r5, r2, lsl #1  

+	mov     	r8, r0          

+	mov     	r7, r1  

+	mov     	r5, r5, lsl #2   

+	cmp     	r1, #0          

+	rsbeq   	r12, r5, r5, lsl #2 

+	beq     	Radix4FFT_LOOP1_END              

+                         

+	rsb     	r12, r5, r5, lsl #2   

+	 

+Radix4FFT_LOOP2:                        

+	mov     	r6, r3 

+	mov     	r4, r2  

+	cmp     	r2, #0        

+	beq     	Radix4FFT_LOOP2_END         

+  

+Radix4FFT_LOOP3:                          

+	@r0 = xptr[0]@

+	@r1 = xptr[1]@

+	VLD2.I32			{D0, D1, D2, D3}, [r8]				

+	VLD2.I32			{D28, D29, D30, D31}, [r6]!		@ cosx = csptr[0]@ sinx = csptr[1]@

+	

+	add					r8, r8, r5										@ xptr += step@	

+	VLD2.I32			{D4, D5, D6,D7}, [r8]					@ r2 = xptr[0]@ r3 = xptr[1]@

+	

+	VQDMULH.S32		Q10, Q2, Q14									@ MULHIGH(cosx, t0)

+	VQDMULH.S32		Q11, Q3, Q15									@ MULHIGH(sinx, t1)

+	VQDMULH.S32		Q12, Q3, Q14									@ MULHIGH(cosx, t1)

+	VQDMULH.S32		Q13, Q2, Q15									@ MULHIGH(sinx, t0)

+		

+	VADD.S32			Q2, Q10, Q11									@ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)

+	VSUB.S32			Q3, Q12, Q13									@ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)

+	

+	add					r8, r8, r5										@ xptr += step@

+	VSHR.S32			Q10, Q0, #2										@ t0 = r0 >> 2@

+	VSHR.S32			Q11, Q1, #2										@ t1 = r1 >> 2@

+	

+	VSUB.S32			Q0,	Q10, Q2										@ r0 = t0 - r2@

+	VSUB.S32			Q1,	Q11, Q3										@ r1 = t1 - r3@

+	VADD.S32			Q2, Q10, Q2										@ r2 = t0 + r2@

+	VADD.S32			Q3, Q11, Q3										@ r3 = t1 + r3@

+		

+	VLD2.I32			{D8, D9, D10, D11}, [r8]	

+	VLD2.I32			{D28, D29, D30, D31}, [r6]!	

+	add						r8, r8, r5

+

+	VQDMULH.S32		Q10, Q4, Q14									@ MULHIGH(cosx, t0)

+	VQDMULH.S32		Q11, Q5, Q15									@ MULHIGH(sinx, t1)

+	VQDMULH.S32		Q12, Q5, Q14									@ MULHIGH(cosx, t1)

+	VQDMULH.S32		Q13, Q4, Q15									@ MULHIGH(sinx, t0)

+		

+	VADD.S32			Q8, Q10, Q11									@ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)

+	VSUB.S32			Q9, Q12, Q13									@ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)	

+	

+	VLD2.I32		{D12, D13, D14, D15}, [r8]	

+	VLD2.I32		{D28, D29, D30, D31}, [r6]!

+	

+	VQDMULH.S32		Q10, Q6, Q14									@ MULHIGH(cosx, t0)

+	VQDMULH.S32		Q11, Q7, Q15									@ MULHIGH(sinx, t1)

+	VQDMULH.S32		Q12, Q7, Q14									@ MULHIGH(cosx, t1)

+	VQDMULH.S32		Q13, Q6, Q15									@ MULHIGH(sinx, t0)

+		

+	VADD.S32			Q6, Q10, Q11									@ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)

+	VSUB.S32			Q7, Q12, Q13									@ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)		

+	

+	VADD.S32			Q4, Q8, Q6										@ r4 = t0 + r6@

+	VSUB.S32			Q5, Q7, Q9										@ r5 = r7 - t1@

+	VSUB.S32			Q6, Q8, Q6										@ r6 = t0 - r6@

+	VADD.S32			Q7, Q7, Q9										@ r7 = r7 + t1@

+	

+	VADD.S32			Q8, Q0, Q5										@ xptr[0] = r0 + r5@

+	VADD.S32			Q9, Q1, Q6										@ xptr[1] = r1 + r6@

+	VST2.I32			{D16, D17, D18, D19}, [r8]

+	

+	VSUB.S32			Q10, Q2, Q4										@ xptr[0] = r2 - r4@

+	sub					r8, r8, r5										@ xptr -= step@

+	VSUB.S32			Q11, Q3, Q7										@ xptr[1] = r3 - r7@

+	VST2.I32			{D20, D21, D22, D23}, [r8]

+		

+	VSUB.S32			Q8, Q0, Q5										@ xptr[0] = r0 - r5@

+	sub					r8, r8, r5										@ xptr -= step@

+	VSUB.S32			Q9, Q1, Q6										@ xptr[1] = r1 - r6@

+	VST2.I32			{D16, D17, D18, D19}, [r8]

+		

+	VADD.S32			Q10, Q2, Q4										@ xptr[0] = r2 + r4@

+	sub					r8, r8, r5										@ xptr -= step@

+	VADD.S32			Q11, Q3, Q7										@ xptr[1] = r3 + r7@

+	VST2.I32			{D20, D21, D22, D23}, [r8]!

+		

+	subs    			r4, r4, #4 

+	bne     			Radix4FFT_LOOP3 

+	                         

+Radix4FFT_LOOP2_END:                         

+	add     			r8, r8, r12    

+	sub    				r7, r7, #1     

+	cmp					r7, #0

+	bhi     			Radix4FFT_LOOP2           

+                        

+Radix4FFT_LOOP1_END:                        

+	add     			r3, r12, r3    

+	mov     			r2, r2, lsl #2 

+	movs    			r1, r1, asr #2 

+	bne     			Radix4FFT_LOOP1          

+                        

+Radix4FFT_END:        

+	ldmia   			sp!, {r4 - r11, pc}

+		

+	@ENDP  @ |Radix4FFT|

+	.end
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/band_nrg.c b/media/libstagefright/codecs/aacenc/src/band_nrg.c
new file mode 100644
index 0000000..666c4ca
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/band_nrg.c
@@ -0,0 +1,102 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		band_nrg.c

+

+	Content:	Band/Line energy calculations functions

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "band_nrg.h"
+
+#ifndef ARMV5E

+/********************************************************************************
+*
+* function name: CalcBandEnergy
+* description:   Calc sfb-bandwise mdct-energies for left and right channel
+*
+**********************************************************************************/

+void CalcBandEnergy(const Word32 *mdctSpectrum,
+                    const Word16 *bandOffset,
+                    const Word16  numBands,
+                    Word32       *bandEnergy,
+                    Word32       *bandEnergySum)
+{
+  Word32 i, j;
+  Word32 accuSum = 0;                                            
+
+  for (i=0; i<numBands; i++) {
+    Word32 accu = 0;                                             
+    for (j=bandOffset[i]; j<bandOffset[i+1]; j++)
+      accu = L_add(accu, MULHIGH(mdctSpectrum[j], mdctSpectrum[j]));

+

+	accu = L_add(accu, accu);
+    accuSum = L_add(accuSum, accu);
+    bandEnergy[i] = accu;                                        
+  }
+  *bandEnergySum = accuSum;                                      
+}
+
+/********************************************************************************
+*
+* function name: CalcBandEnergyMS
+* description:   Calc sfb-bandwise mdct-energies for left add or minus right channel
+*
+**********************************************************************************/
+void CalcBandEnergyMS(const Word32 *mdctSpectrumLeft,
+                      const Word32 *mdctSpectrumRight,
+                      const Word16 *bandOffset,
+                      const Word16  numBands,
+                      Word32       *bandEnergyMid,
+                      Word32       *bandEnergyMidSum,
+                      Word32       *bandEnergySide,
+                      Word32       *bandEnergySideSum)
+{
+
+  Word32 i, j;
+  Word32 accuMidSum = 0;        
+  Word32 accuSideSum = 0;                                          
+ 
+
+  for(i=0; i<numBands; i++) {
+    Word32 accuMid = 0;
+    Word32 accuSide = 0;                                           
+    for (j=bandOffset[i]; j<bandOffset[i+1]; j++) {
+      Word32 specm, specs; 
+      Word32 l, r;
+
+      l = mdctSpectrumLeft[j] >> 1;
+      r = mdctSpectrumRight[j] >> 1;
+      specm = l + r;
+      specs = l - r;
+      accuMid = L_add(accuMid, MULHIGH(specm, specm));
+      accuSide = L_add(accuSide, MULHIGH(specs, specs));
+    }
+    

+	accuMid = L_add(accuMid, accuMid);

+	accuSide = L_add(accuSide, accuSide);

+	bandEnergyMid[i] = accuMid;                                  
+    accuMidSum = L_add(accuMidSum, accuMid);
+    bandEnergySide[i] = accuSide;                                
+    accuSideSum = L_add(accuSideSum, accuSide);
+    
+  }
+  *bandEnergyMidSum = accuMidSum;                                
+  *bandEnergySideSum = accuSideSum;                              
+}
+
+#endif
\ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/bit_cnt.c b/media/libstagefright/codecs/aacenc/src/bit_cnt.c
new file mode 100644
index 0000000..24837e8
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/bit_cnt.c
@@ -0,0 +1,885 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		bit_cnt.c

+

+	Content:	Huffman Bitcounter & coder functions

+

+*******************************************************************************/
+
+#include "bit_cnt.h"
+#include "aac_rom.h"
+
+#define HI_LTAB(a) (a>>8)
+#define LO_LTAB(a) (a & 0xff)
+
+#define EXPAND(a)  ((((Word32)(a&0xff00)) << 8)|(Word32)(a&0xff)) 
+
+
+/*****************************************************************************
+*
+* function name: count1_2_3_4_5_6_7_8_9_10_11
+* description:  counts tables 1-11 
+* returns:      
+* input:        quantized spectrum
+* output:       bitCount for tables 1-11
+*
+*****************************************************************************/
+
+static void count1_2_3_4_5_6_7_8_9_10_11(const Word16 *values,
+                                         const Word16  width,
+                                         Word16       *bitCount)
+{
+  Word32 t0,t1,t2,t3,i;
+  Word32 bc1_2,bc3_4,bc5_6,bc7_8,bc9_10;
+  Word16 bc11,sc;

+  
+  bc1_2=0;                               
+  bc3_4=0;                               
+  bc5_6=0;                               
+  bc7_8=0;                               
+  bc9_10=0;                              
+  bc11=0;                                
+  sc=0;                                  
+
+  for(i=0;i<width;i+=4){
+    
+    t0= values[i+0];                     
+    t1= values[i+1];                     
+    t2= values[i+2];                     
+    t3= values[i+3];                     
+  
+    /* 1,2 */
+
+    bc1_2 = bc1_2 + EXPAND(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);              
+
+    /* 5,6 */
+    bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);                          
+    bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t2+4][t3+4]);                          
+
+    t0=ABS(t0);
+    t1=ABS(t1);
+    t2=ABS(t2);
+    t3=ABS(t3);
+
+    
+    bc3_4 = bc3_4 + EXPAND(huff_ltab3_4[t0][t1][t2][t3]);                      
+    
+    bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);                              
+    bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t2][t3]);                              
+    
+    bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);                           
+    bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t2][t3]);                           
+    
+    bc11 = bc11 + huff_ltab11[t0][t1];
+    bc11 = bc11 + huff_ltab11[t2][t3];
+   
+           
+    sc = sc + (t0>0) + (t1>0) + (t2>0) + (t3>0);
+  }
+  
+  bitCount[1]=extract_h(bc1_2);
+  bitCount[2]=extract_l(bc1_2);
+  bitCount[3]=extract_h(bc3_4) + sc;
+  bitCount[4]=extract_l(bc3_4) + sc;
+  bitCount[5]=extract_h(bc5_6);
+  bitCount[6]=extract_l(bc5_6);
+  bitCount[7]=extract_h(bc7_8) + sc;
+  bitCount[8]=extract_l(bc7_8) + sc;
+  bitCount[9]=extract_h(bc9_10) + sc;
+  bitCount[10]=extract_l(bc9_10) + sc;
+  bitCount[11]=bc11 + sc;
+}
+
+
+/*****************************************************************************
+*
+* function name: count3_4_5_6_7_8_9_10_11
+* description:  counts tables 3-11 
+* returns:      
+* input:        quantized spectrum
+* output:       bitCount for tables 3-11
+*
+*****************************************************************************/
+
+static void count3_4_5_6_7_8_9_10_11(const Word16 *values,
+                                     const Word16  width,
+                                     Word16       *bitCount)
+{
+  Word32 t0,t1,t2,t3, i;
+  Word32 bc3_4,bc5_6,bc7_8,bc9_10;
+  Word16 bc11,sc;
+    
+  bc3_4=0;                               
+  bc5_6=0;                               
+  bc7_8=0;                               
+  bc9_10=0;                              
+  bc11=0;                                
+  sc=0;                                  
+
+  for(i=0;i<width;i+=4){
+
+    t0= values[i+0];                     
+    t1= values[i+1];                     
+    t2= values[i+2];                     
+    t3= values[i+3];                     
+    
+    /*
+      5,6
+    */
+    bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);                          
+    bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t2+4][t3+4]);                          
+
+    t0=ABS(t0);
+    t1=ABS(t1);
+    t2=ABS(t2);
+    t3=ABS(t3);
+
+
+    bc3_4 = bc3_4 + EXPAND(huff_ltab3_4[t0][t1][t2][t3]);                      
+                                                                                                                
+    bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);                              
+    bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t2][t3]);                              
+    
+    bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);                           
+    bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t2][t3]);                           
+                                                                                                                
+    bc11 = bc11 + huff_ltab11[t0][t1];
+    bc11 = bc11 + huff_ltab11[t2][t3];
+
+           
+    sc = sc + (t0>0) + (t1>0) + (t2>0) + (t3>0);   
+  }

+  
+  bitCount[1]=INVALID_BITCOUNT;                          
+  bitCount[2]=INVALID_BITCOUNT;                          
+  bitCount[3]=extract_h(bc3_4) + sc;
+  bitCount[4]=extract_l(bc3_4) + sc;
+  bitCount[5]=extract_h(bc5_6);
+  bitCount[6]=extract_l(bc5_6);
+  bitCount[7]=extract_h(bc7_8) + sc;
+  bitCount[8]=extract_l(bc7_8) + sc;
+  bitCount[9]=extract_h(bc9_10) + sc;
+  bitCount[10]=extract_l(bc9_10) + sc;
+  bitCount[11]=bc11 + sc;
+  
+}
+
+
+
+/*****************************************************************************
+*
+* function name: count5_6_7_8_9_10_11
+* description:  counts tables 5-11 
+* returns:      
+* input:        quantized spectrum
+* output:       bitCount for tables 5-11
+*
+*****************************************************************************/
+static void count5_6_7_8_9_10_11(const Word16 *values,
+                                 const Word16  width,
+                                 Word16       *bitCount)
+{
+
+  Word32 t0,t1,i;
+  Word32 bc5_6,bc7_8,bc9_10;
+  Word16 bc11,sc;

+
+  bc5_6=0;                               
+  bc7_8=0;                               
+  bc9_10=0;                              
+  bc11=0;                                
+  sc=0;                                  
+
+  for(i=0;i<width;i+=2){
+
+    t0 = values[i+0];                    
+    t1 = values[i+1];                    
+
+    bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);                  
+
+    t0=ABS(t0);
+    t1=ABS(t1);
+     
+    bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);                      
+    bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);                   
+    bc11 = bc11 + huff_ltab11[t0][t1];
+    
+       
+    sc = sc + (t0>0) + (t1>0);
+  }
+  bitCount[1]=INVALID_BITCOUNT;                          
+  bitCount[2]=INVALID_BITCOUNT;                          
+  bitCount[3]=INVALID_BITCOUNT;                          
+  bitCount[4]=INVALID_BITCOUNT;                          
+  bitCount[5]=extract_h(bc5_6);
+  bitCount[6]=extract_l(bc5_6);
+  bitCount[7]=extract_h(bc7_8) + sc;
+  bitCount[8]=extract_l(bc7_8) + sc;
+  bitCount[9]=extract_h(bc9_10) + sc;
+  bitCount[10]=extract_l(bc9_10) + sc;
+  bitCount[11]=bc11 + sc;
+  
+}
+
+
+/*****************************************************************************
+*
+* function name: count7_8_9_10_11
+* description:  counts tables 7-11 
+* returns:      
+* input:        quantized spectrum
+* output:       bitCount for tables 7-11
+*
+*****************************************************************************/
+
+static void count7_8_9_10_11(const Word16 *values,
+                             const Word16  width,
+                             Word16       *bitCount)
+{
+  Word32 t0,t1, i;
+  Word32 bc7_8,bc9_10;
+  Word16 bc11,sc;
+    
+  bc7_8=0;                       
+  bc9_10=0;                      
+  bc11=0;                        
+  sc=0;                          
+
+  for(i=0;i<width;i+=2){
+
+    t0=ABS(values[i+0]);
+    t1=ABS(values[i+1]);
+
+    bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);                      
+    bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);                   
+    bc11 = bc11 + huff_ltab11[t0][t1];
+   
+       
+    sc = sc + (t0>0) + (t1>0);
+  }
+  bitCount[1]=INVALID_BITCOUNT;                  
+  bitCount[2]=INVALID_BITCOUNT;                  
+  bitCount[3]=INVALID_BITCOUNT;                  
+  bitCount[4]=INVALID_BITCOUNT;                  
+  bitCount[5]=INVALID_BITCOUNT;                  
+  bitCount[6]=INVALID_BITCOUNT;                  
+  bitCount[7]=extract_h(bc7_8) + sc;
+  bitCount[8]=extract_l(bc7_8) + sc;
+  bitCount[9]=extract_h(bc9_10) + sc;
+  bitCount[10]=extract_l(bc9_10) + sc;
+  bitCount[11]=bc11 + sc;
+  
+}
+
+/*****************************************************************************
+*
+* function name: count9_10_11
+* description:  counts tables 9-11 
+* returns:      
+* input:        quantized spectrum
+* output:       bitCount for tables 9-11
+*
+*****************************************************************************/
+static void count9_10_11(const Word16 *values,

+                         const Word16  width,

+                         Word16       *bitCount)

+{

+

+  Word32 t0,t1,i;  

+  Word32 bc9_10;

+  Word16 bc11,sc;

+

+  bc9_10=0;                              

+  bc11=0;                                

+  sc=0;                                  

+

+  for(i=0;i<width;i+=2){

+

+    t0=ABS(values[i+0]);

+    t1=ABS(values[i+1]);

+    

+

+    bc9_10 += EXPAND(huff_ltab9_10[t0][t1]);           

+    bc11 = bc11 + huff_ltab11[t0][t1];

+

+       

+    sc = sc + (t0>0) + (t1>0);

+  }

+  bitCount[1]=INVALID_BITCOUNT;          

+  bitCount[2]=INVALID_BITCOUNT;          

+  bitCount[3]=INVALID_BITCOUNT;          

+  bitCount[4]=INVALID_BITCOUNT;          

+  bitCount[5]=INVALID_BITCOUNT;          

+  bitCount[6]=INVALID_BITCOUNT;          

+  bitCount[7]=INVALID_BITCOUNT;          

+  bitCount[8]=INVALID_BITCOUNT;          

+  bitCount[9]=extract_h(bc9_10) + sc;

+  bitCount[10]=extract_l(bc9_10) + sc;

+  bitCount[11]=bc11 + sc;

+  

+}
+ 
+/*****************************************************************************
+*
+* function name: count11
+* description:  counts table 11 
+* returns:      
+* input:        quantized spectrum
+* output:       bitCount for table 11
+*
+*****************************************************************************/
+ static void count11(const Word16 *values,

+                    const Word16  width,

+                    Word16        *bitCount)

+{

+  Word32 t0,t1,i;

+  Word16 bc11,sc;  

+

+  bc11=0;                        

+  sc=0;                          

+  for(i=0;i<width;i+=2){

+    t0=ABS(values[i+0]);

+    t1=ABS(values[i+1]);

+    bc11 = bc11 + huff_ltab11[t0][t1];

+

+       

+    sc = sc + (t0>0) + (t1>0);

+  }

+

+  bitCount[1]=INVALID_BITCOUNT;                  

+  bitCount[2]=INVALID_BITCOUNT;                  

+  bitCount[3]=INVALID_BITCOUNT;                  

+  bitCount[4]=INVALID_BITCOUNT;                  

+  bitCount[5]=INVALID_BITCOUNT;                  

+  bitCount[6]=INVALID_BITCOUNT;                  

+  bitCount[7]=INVALID_BITCOUNT;                  

+  bitCount[8]=INVALID_BITCOUNT;                  

+  bitCount[9]=INVALID_BITCOUNT;                  

+  bitCount[10]=INVALID_BITCOUNT;                 

+  bitCount[11]=bc11 + sc;

+}
+
+/*****************************************************************************
+*
+* function name: countEsc
+* description:  counts table 11 (with Esc) 
+* returns:      
+* input:        quantized spectrum
+* output:       bitCount for tables 11 (with Esc)
+*
+*****************************************************************************/
+
+static void countEsc(const Word16 *values,

+                     const Word16  width,

+                     Word16       *bitCount)

+{

+  Word32 t0,t1,t00,t01,i;

+  Word16 bc11,ec,sc;  

+

+  bc11=0;                                

+  sc=0;                                  

+  ec=0;                                  

+  for(i=0;i<width;i+=2){

+    t0=ABS(values[i+0]);

+    t1=ABS(values[i+1]);

+    

+       

+    sc = sc + (t0>0) + (t1>0);

+

+    t00 = min(t0,16);

+    t01 = min(t1,16);

+    bc11 = bc11 + huff_ltab11[t00][t01];

+    

+     

+    if(t0 >= 16){

+      ec = ec + 5;

+      while(sub(t0=(t0 >> 1), 16) >= 0) {

+        ec = ec + 2;

+      }

+    }

+    

+     

+    if(t1 >= 16){

+      ec = ec + 5;

+      while(sub(t1=(t1 >> 1), 16) >= 0) {

+        ec = ec + 2;

+      }

+    }

+  }

+  bitCount[1]=INVALID_BITCOUNT;          

+  bitCount[2]=INVALID_BITCOUNT;          

+  bitCount[3]=INVALID_BITCOUNT;          

+  bitCount[4]=INVALID_BITCOUNT;          

+  bitCount[5]=INVALID_BITCOUNT;          

+  bitCount[6]=INVALID_BITCOUNT;          

+  bitCount[7]=INVALID_BITCOUNT;          

+  bitCount[8]=INVALID_BITCOUNT;          

+  bitCount[9]=INVALID_BITCOUNT;          

+  bitCount[10]=INVALID_BITCOUNT;         

+  bitCount[11]=bc11 + sc + ec;

+}
+
+
+typedef void (*COUNT_FUNCTION)(const Word16 *values,
+                               const Word16  width,
+                               Word16       *bitCount);
+
+static COUNT_FUNCTION countFuncTable[CODE_BOOK_ESC_LAV+1] =
+  {
+
+    count1_2_3_4_5_6_7_8_9_10_11,  /* 0  */
+    count1_2_3_4_5_6_7_8_9_10_11,  /* 1  */
+    count3_4_5_6_7_8_9_10_11,      /* 2  */
+    count5_6_7_8_9_10_11,          /* 3  */
+    count5_6_7_8_9_10_11,          /* 4  */
+    count7_8_9_10_11,              /* 5  */
+    count7_8_9_10_11,              /* 6  */
+    count7_8_9_10_11,              /* 7  */
+    count9_10_11,                  /* 8  */
+    count9_10_11,                  /* 9  */
+    count9_10_11,                  /* 10 */
+    count9_10_11,                  /* 11 */
+    count9_10_11,                  /* 12 */
+    count11,                       /* 13 */
+    count11,                       /* 14 */
+    count11,                       /* 15 */
+    countEsc                       /* 16 */
+  };
+
+/*****************************************************************************
+*
+* function name: bitCount
+* description:  count bits 
+*
+*****************************************************************************/
+Word16 bitCount(const Word16 *values,
+                const Word16  width,
+                Word16        maxVal,
+                Word16       *bitCount)
+{
+  /*
+    check if we can use codebook 0
+  */
+     
+  if(maxVal == 0)
+    bitCount[0] = 0;
+  else
+    bitCount[0] = INVALID_BITCOUNT;
+
+  maxVal = min(maxVal, CODE_BOOK_ESC_LAV);
+  countFuncTable[maxVal](values,width,bitCount);
+
+  return(0);
+}
+
+/*****************************************************************************
+*
+* function name: codeValues
+* description:  write huffum bits 
+*
+*****************************************************************************/
+Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF hBitstream)

+{

+

+  Word32 i, t0, t1, t2, t3, t00, t01;

+  Word16 codeWord, codeLength;

+  Word16 sign, signLength;

+

+   

+  switch (codeBook) {

+    case CODE_BOOK_ZERO_NO:

+      break;

+

+    case CODE_BOOK_1_NO:

+      for(i=0; i<width; i+=4) {

+        t0         = values[i+0];                                        

+        t1         = values[i+1];                                        

+        t2         = values[i+2];                                        

+        t3         = values[i+3];                                        

+        codeWord   = huff_ctab1[t0+1][t1+1][t2+1][t3+1];                 

+        codeLength = HI_LTAB(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);      

+        WriteBits(hBitstream, codeWord, codeLength);        

+      }

+      break;

+

+    case CODE_BOOK_2_NO:

+      for(i=0; i<width; i+=4) {

+        t0         = values[i+0];                                        

+        t1         = values[i+1];                                        

+        t2         = values[i+2];                                        

+        t3         = values[i+3];                                        

+        codeWord   = huff_ctab2[t0+1][t1+1][t2+1][t3+1];                 

+        codeLength = LO_LTAB(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);      

+        WriteBits(hBitstream,codeWord,codeLength);

+      }

+      break;

+

+    case CODE_BOOK_3_NO:

+      for(i=0; i<width; i+=4) {

+        sign=0;                                                          

+        signLength=0;                                                    

+        t0 = values[i+0];                                                

+         

+        if(t0 != 0){

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t0 < 0){

+            sign|=1;                                                     

+            t0=-t0;

+          }

+        }

+        t1 = values[i+1];                                                

+         

+        if(t1 != 0){

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t1 < 0){

+            sign|=1;                                                     

+            t1=-t1;

+          }

+        }

+        t2 = values[i+2];                                                

+         

+        if(t2 != 0){

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t2 < 0){

+            sign|=1;                                                     

+            t2=-t2;

+          }

+        }

+        t3 = values[i+3];                                                

+        if(t3 != 0){

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t3 < 0){

+            sign|=1;                                                     

+            t3=-t3;

+          }

+        }

+

+        codeWord   = huff_ctab3[t0][t1][t2][t3];                         

+        codeLength = HI_LTAB(huff_ltab3_4[t0][t1][t2][t3]);              

+        WriteBits(hBitstream,codeWord,codeLength);

+        WriteBits(hBitstream,sign,signLength);

+      }

+      break;

+

+    case CODE_BOOK_4_NO:

+      for(i=0; i<width; i+=4) {

+        sign=0;                                                          

+        signLength=0;                                                    

+        t0 = values[i+0];                                                

+         

+        if(t0 != 0){                                                             

+          signLength = signLength + 1;

+          sign = sign << 1; 

+          if(t0 < 0){                                                            

+            sign|=1;                                                     

+            t0=-t0;                                                          

+          }

+        }                                                                        

+        t1 = values[i+1];                                                

+         

+        if(t1 != 0){                                                             

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t1 < 0){                                                            

+            sign|=1;                                                     

+            t1=-t1;                                                          

+          }                                                                      

+        }                                                                        

+        t2 = values[i+2];                                                

+         

+        if(t2 != 0){                                                    

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t2 < 0){                                                   

+            sign|=1;                                                     

+            t2=-t2;                                                 

+          }                                                             

+        }                                                               

+        t3 = values[i+3];                                                

+         

+        if(t3 != 0){                                                    

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t3 < 0){                                                   

+            sign|=1;                                                     

+            t3=-t3;                                                 

+          }                                                             

+        }                                                               

+        codeWord   = huff_ctab4[t0][t1][t2][t3];                         

+        codeLength = LO_LTAB(huff_ltab3_4[t0][t1][t2][t3]);              

+        WriteBits(hBitstream,codeWord,codeLength);                      

+        WriteBits(hBitstream,sign,signLength);                          

+      }                                                                 

+      break;                                                            

+                                                                        

+    case CODE_BOOK_5_NO:                                                

+      for(i=0; i<width; i+=2) {                                         

+        t0         = values[i+0];                                         

+        t1         = values[i+1];                                        

+        codeWord   = huff_ctab5[t0+4][t1+4];                             

+        codeLength = HI_LTAB(huff_ltab5_6[t0+4][t1+4]);                  

+        WriteBits(hBitstream,codeWord,codeLength);

+      }

+      break;

+

+    case CODE_BOOK_6_NO:

+      for(i=0; i<width; i+=2) {

+        t0         = values[i+0];                                        

+        t1         = values[i+1];                                        

+        codeWord   = huff_ctab6[t0+4][t1+4];                             

+        codeLength = LO_LTAB(huff_ltab5_6[t0+4][t1+4]);                  

+        WriteBits(hBitstream,codeWord,codeLength);

+      }

+      break;

+

+    case CODE_BOOK_7_NO:

+      for(i=0; i<width; i+=2){

+        sign=0;                                                          

+        signLength=0;                                                    

+        t0 = values[i+0];                                                

+         

+        if(t0 != 0){

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t0 < 0){

+            sign|=1;                                                     

+            t0=-t0;

+          }

+        }

+

+        t1 = values[i+1];                                                

+         

+        if(t1 != 0){

+          signLength = signLength + 1;

+          sign = sign << 1; 

+           

+          if(t1 < 0){

+            sign|=1;                                                     

+            t1=-t1;

+          }

+        }

+        codeWord   = huff_ctab7[t0][t1];                                 

+        codeLength = HI_LTAB(huff_ltab7_8[t0][t1]);                      

+        WriteBits(hBitstream,codeWord,codeLength);

+        WriteBits(hBitstream,sign,signLength);

+      }

+      break;

+

+    case CODE_BOOK_8_NO:

+      for(i=0; i<width; i+=2) {

+        sign=0;                                                          

+        signLength=0;                                                    

+        t0 = values[i+0];                                                

+                                                                           

+        if(t0 != 0){                                                             

+          signLength = signLength + 1;                                       

+          sign = sign << 1;                                                   

+                                                                           

+          if(t0 < 0){                                                            

+            sign|=1;                                                     

+            t0=-t0;                                                        

+          }                                                                      

+        }                                                                        

+                                                                                 

+        t1 = values[i+1];                                                

+                                                                           

+        if(t1 != 0){                                                             

+          signLength = signLength + 1;                                       

+          sign = sign << 1;                                                   

+                                                                           

+          if(t1 < 0){                                                            

+            sign|=1;                                                     

+            t1=-t1;                                                        

+          }                                                                      

+        }                                                                        

+        codeWord   = huff_ctab8[t0][t1];                                 

+        codeLength = LO_LTAB(huff_ltab7_8[t0][t1]);                      

+        WriteBits(hBitstream,codeWord,codeLength);

+        WriteBits(hBitstream,sign,signLength);

+      }

+      break;

+

+    case CODE_BOOK_9_NO:

+      for(i=0; i<width; i+=2) {

+        sign=0;                                                          

+        signLength=0;                                                    

+        t0 = values[i+0];                                                

+                                                                           

+        if(t0 != 0){                                                             

+          signLength = signLength + 1;                                       

+          sign = sign << 1;                                                   

+                                                                           

+          if(t0 < 0){                                                            

+            sign|=1;                                                     

+            t0=-t0;                                                        

+          }                                                                      

+        }                                                                        

+                                                                                 

+        t1 = values[i+1];                                                

+                                                                           

+        if(t1 != 0){                                                             

+          signLength = signLength + 1;                                       

+          sign = sign << 1;                                                   

+                                                                           

+          if(t1 < 0){                                                            

+            sign|=1;                                                     

+            t1=-t1;                                                        

+          }                                                                      

+        }                                                                        

+        codeWord   = huff_ctab9[t0][t1];                                 

+        codeLength = HI_LTAB(huff_ltab9_10[t0][t1]);                     

+        WriteBits(hBitstream,codeWord,codeLength);

+        WriteBits(hBitstream,sign,signLength);

+      }

+      break;

+

+    case CODE_BOOK_10_NO:

+      for(i=0; i<width; i+=2) {

+        sign=0;                                                          

+        signLength=0;                                                    

+        t0 = values[i+0];                                                

+                                                                           

+        if(t0 != 0){                                                             

+          signLength = signLength + 1;                                       

+          sign = sign << 1;                                                   

+                                                                           

+          if(t0 < 0){                                                            

+            sign|=1;                                                     

+            t0=-t0;                                                        

+          }                                                                      

+        }                                                                        

+                                                                                 

+        t1 = values[i+1];                                                

+                                                                           

+        if(t1 != 0){                                                             

+          signLength = signLength + 1;                                       

+          sign = sign << 1;                                                   

+                                                                           

+          if(t1 < 0){                                                            

+            sign|=1;                                                     

+            t1=-t1;                                                        

+          }                                                                      

+        }                                                                        

+        codeWord   = huff_ctab10[t0][t1];                                

+        codeLength = LO_LTAB(huff_ltab9_10[t0][t1]);                     

+        WriteBits(hBitstream,codeWord,codeLength);

+        WriteBits(hBitstream,sign,signLength);

+      }

+      break;

+

+    case CODE_BOOK_ESC_NO:

+      for(i=0; i<width; i+=2) {

+        sign=0;                                                  

+        signLength=0;                                            

+        t0 = values[i+0];                                        

+                                                                   

+        if(t0 != 0){                                                     

+          signLength = signLength + 1;                               

+          sign = sign << 1;                                           

+                                                                   

+          if(t0 < 0){                                                    

+            sign|=1;                                             

+            t0=-t0;                                                

+          }                                                              

+        }                                                                

+                                                                         

+        t1 = values[i+1];                                        

+                                                                   

+        if(t1 != 0){                                                     

+          signLength = signLength + 1;                               

+          sign = sign << 1;                                           

+                                                                   

+          if(t1 < 0){                                                    

+            sign|=1;                                             

+            t1=-t1;                                                

+          }                                                              

+        }                                                                

+        t00 = min(t0,16);

+        t01 = min(t1,16);

+

+        codeWord   = huff_ctab11[t00][t01];                      

+        codeLength = huff_ltab11[t00][t01];                      

+        WriteBits(hBitstream,codeWord,codeLength);

+        WriteBits(hBitstream,sign,signLength);

+         

+        if(t0 >= 16){

+          Word16 n, p;

+          n=0;                                                   

+          p=t0;                                                  

+          while(sub(p=(p >> 1), 16) >= 0){

+             

+            WriteBits(hBitstream,1,1);

+            n = n + 1;

+          }

+          WriteBits(hBitstream,0,1);

+          n = n + 4;

+          WriteBits(hBitstream,(t0 - (1 << n)),n);

+        }

+         

+        if(t1 >= 16){

+          Word16 n, p;

+          n=0;                                                   

+          p=t1;                                                  

+          while(sub(p=(p >> 1), 16) >= 0){

+             

+            WriteBits(hBitstream,1,1);

+            n = n + 1;

+          }

+          WriteBits(hBitstream,0,1);

+          n = n + 4;

+          WriteBits(hBitstream,(t1 - (1 << n)),n);

+        }

+      }

+      break;

+

+    default:

+      break;

+  }

+  return(0);

+}
+
+Word16 bitCountScalefactorDelta(Word16 delta)
+{
+  return(huff_ltabscf[delta+CODE_BOOK_SCF_LAV]);
+}
+
+Word16 codeScalefactorDelta(Word16 delta, HANDLE_BIT_BUF hBitstream)
+{
+  Word32 codeWord; 
+  Word16 codeLength;
+  
+   
+  if(delta > CODE_BOOK_SCF_LAV || delta < -CODE_BOOK_SCF_LAV)
+    return(1);
+  
+  codeWord   = huff_ctabscf[delta + CODE_BOOK_SCF_LAV];            
+  codeLength = huff_ltabscf[delta + CODE_BOOK_SCF_LAV];            
+  WriteBits(hBitstream,codeWord,codeLength);
+  return(0);
+}
diff --git a/media/libstagefright/codecs/aacenc/src/bitbuffer.c b/media/libstagefright/codecs/aacenc/src/bitbuffer.c
new file mode 100644
index 0000000..3248f0b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/bitbuffer.c
@@ -0,0 +1,172 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		bitbuffer.c

+

+	Content:	Bit Buffer Management functions

+

+*******************************************************************************/
+
+#include "bitbuffer.h"
+
+/*****************************************************************************
+*
+* function name: updateBitBufWordPtr
+* description:  update Bit Buffer pointer
+*
+*****************************************************************************/
+static void updateBitBufWordPtr(HANDLE_BIT_BUF hBitBuf,
+                                UWord8 **pBitBufWord,
+                                Word16   cnt)
+{
+  *pBitBufWord += cnt;                                                                  
+
+                                                                                        
+  if(*pBitBufWord > hBitBuf->pBitBufEnd) {
+    *pBitBufWord -= (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);                   
+  }
+                                                                                        
+  if(*pBitBufWord < hBitBuf->pBitBufBase) {
+    *pBitBufWord += (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);                   
+  }
+}
+
+
+/*****************************************************************************
+*
+* function name: CreateBitBuffer
+* description:  create and init Bit Buffer Management
+*
+*****************************************************************************/
+HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf,
+                               UWord8 *pBitBufBase,
+                               Word16  bitBufSize)
+{
+  assert(bitBufSize*8 <= 32768);
+
+  hBitBuf->pBitBufBase = pBitBufBase;                                                    
+  hBitBuf->pBitBufEnd  = pBitBufBase + bitBufSize - 1;                                  
+
+  hBitBuf->pWriteNext  = pBitBufBase;                                                    
+
+  hBitBuf->cache       = 0;
+  
+  hBitBuf->wBitPos     = 0;                                                              
+  hBitBuf->cntBits     = 0;   
+  
+  hBitBuf->size        = (bitBufSize << 3);                                             
+  hBitBuf->isValid     = 1;                                                              
+
+  return hBitBuf;
+}
+
+/*****************************************************************************
+*
+* function name: DeleteBitBuffer
+* description:  uninit Bit Buffer Management
+*
+*****************************************************************************/
+void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf)
+{
+  if(*hBitBuf)

+	(*hBitBuf)->isValid = 0;                                                               
+  *hBitBuf = NULL;                                                                       
+}
+
+/*****************************************************************************
+*
+* function name: ResetBitBuf
+* description:  reset Bit Buffer Management
+*
+*****************************************************************************/
+void ResetBitBuf(HANDLE_BIT_BUF hBitBuf,
+                 UWord8 *pBitBufBase,
+                 Word16  bitBufSize)
+{
+  hBitBuf->pBitBufBase = pBitBufBase;                                                    
+  hBitBuf->pBitBufEnd  = pBitBufBase + bitBufSize - 1;                                  
+
+                                                 
+  hBitBuf->pWriteNext  = pBitBufBase;                                                    
+
+  hBitBuf->wBitPos     = 0;    
+  hBitBuf->cntBits     = 0;    
+  
+  hBitBuf->cache	   = 0;
+}
+
+/*****************************************************************************
+*
+* function name: CopyBitBuf
+* description:  copy Bit Buffer Management
+*
+*****************************************************************************/
+void CopyBitBuf(HANDLE_BIT_BUF hBitBufSrc,
+                HANDLE_BIT_BUF hBitBufDst)
+{
+  *hBitBufDst = *hBitBufSrc;                                                             
+}
+
+/*****************************************************************************
+*
+* function name: GetBitsAvail
+* description:  get available bits
+*
+*****************************************************************************/
+Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf)
+{
+  return hBitBuf->cntBits;
+}
+
+/*****************************************************************************
+*
+* function name: WriteBits
+* description:  write bits to the buffer
+*
+*****************************************************************************/
+Word16 WriteBits(HANDLE_BIT_BUF hBitBuf,
+                 Word32 writeValue,
+                 Word16 noBitsToWrite)
+{
+  Word16 wBitPos;
+
+  assert(noBitsToWrite <= (Word16)sizeof(Word32)*8);
+
+  if(noBitsToWrite == 0)
+	  return noBitsToWrite;
+
+  hBitBuf->cntBits += noBitsToWrite;   
+
+  wBitPos = hBitBuf->wBitPos;
+  wBitPos += noBitsToWrite;
+  writeValue <<= 32 - wBitPos;	
+  writeValue |= hBitBuf->cache;
+  
+  while (wBitPos >= 8) 
+  {
+	  UWord8 tmp;
+	  tmp = (UWord8)((writeValue >> 24) & 0xFF);
+	  
+	  *hBitBuf->pWriteNext++ = tmp;		
+	  writeValue <<= 8;
+	  wBitPos -= 8;
+  }
+  
+  hBitBuf->wBitPos = wBitPos;
+  hBitBuf->cache = writeValue;
+                                                                                     
+  return noBitsToWrite;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/bitenc.c b/media/libstagefright/codecs/aacenc/src/bitenc.c
new file mode 100644
index 0000000..588c2da
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/bitenc.c
@@ -0,0 +1,690 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		bitenc.c

+

+	Content:	Bitstream encoder functions

+

+*******************************************************************************/
+
+#include "bitenc.h"
+#include "bit_cnt.h"
+#include "dyn_bits.h"
+#include "qc_data.h"
+#include "interface.h"
+
+
+static const  Word16 globalGainOffset = 100;
+static const  Word16 icsReservedBit   = 0;
+
+
+/*****************************************************************************
+*
+* function name: encodeSpectralData
+* description:  encode spectral data
+* returns:      spectral bits used
+*
+*****************************************************************************/
+static Word32 encodeSpectralData(Word16             *sfbOffset,
+                                 SECTION_DATA       *sectionData,
+                                 Word16             *quantSpectrum,
+                                 HANDLE_BIT_BUF      hBitStream)
+{
+  Word16 i,sfb;
+  Word16 dbgVal;
+  SECTION_INFO* psectioninfo;
+  dbgVal = GetBitsAvail(hBitStream);                                     
+
+  for(i=0; i<sectionData->noOfSections; i++) {
+    psectioninfo = &(sectionData->sectionInfo[i]);

+	/*
+       huffencode spectral data for this section
+    */
+    for(sfb=psectioninfo->sfbStart;
+        sfb<psectioninfo->sfbStart+psectioninfo->sfbCnt;
+        sfb++) {
+      codeValues(quantSpectrum+sfbOffset[sfb],
+                 sfbOffset[sfb+1] - sfbOffset[sfb],
+                 psectioninfo->codeBook,
+                 hBitStream);
+    }
+  }
+
+  return(GetBitsAvail(hBitStream)-dbgVal);
+}
+
+/*****************************************************************************
+*
+* function name:encodeGlobalGain
+* description: encodes Global Gain (common scale factor)
+* returns:     none
+*
+*****************************************************************************/
+static void encodeGlobalGain(Word16 globalGain,
+                             Word16 logNorm,
+                             Word16 scalefac,
+                             HANDLE_BIT_BUF hBitStream)
+{
+  WriteBits(hBitStream, ((globalGain - scalefac) + globalGainOffset-(logNorm << 2)), 8);
+}
+
+
+/*****************************************************************************
+*
+* function name:encodeIcsInfo
+* description: encodes Ics Info
+* returns:     none
+*
+*****************************************************************************/
+
+static void encodeIcsInfo(Word16 blockType,
+                          Word16 windowShape,
+                          Word16 groupingMask,
+                          SECTION_DATA *sectionData,
+                          HANDLE_BIT_BUF  hBitStream)
+{
+  WriteBits(hBitStream,icsReservedBit,1);
+  WriteBits(hBitStream,blockType,2);
+  WriteBits(hBitStream,windowShape,1);
+
+   
+  switch(blockType){
+    case LONG_WINDOW:
+    case START_WINDOW:
+    case STOP_WINDOW:
+      WriteBits(hBitStream,sectionData->maxSfbPerGroup,6);
+
+      /* No predictor data present */
+      WriteBits(hBitStream, 0, 1);
+      break;
+
+    case SHORT_WINDOW:
+      WriteBits(hBitStream,sectionData->maxSfbPerGroup,4);
+
+      /*
+      Write grouping bits
+      */
+      WriteBits(hBitStream,groupingMask,TRANS_FAC-1);
+      break;
+  }
+}
+
+/*****************************************************************************
+*
+* function name: encodeSectionData
+* description:  encode section data (common Huffman codebooks for adjacent
+*               SFB's)
+* returns:      none
+*
+*****************************************************************************/
+static Word32 encodeSectionData(SECTION_DATA *sectionData,
+                                HANDLE_BIT_BUF hBitStream)
+{
+  Word16 sectEscapeVal=0,sectLenBits=0;
+  Word16 sectLen;
+  Word16 i;
+  Word16 dbgVal=GetBitsAvail(hBitStream);
+       
+
+   
+  switch(sectionData->blockType)
+  {
+    case LONG_WINDOW:
+    case START_WINDOW:
+    case STOP_WINDOW:
+      sectEscapeVal = SECT_ESC_VAL_LONG;                 
+      sectLenBits   = SECT_BITS_LONG;                    
+      break;
+
+    case SHORT_WINDOW:
+      sectEscapeVal = SECT_ESC_VAL_SHORT;                
+      sectLenBits   = SECT_BITS_SHORT;                   
+      break;
+  }
+
+  for(i=0;i<sectionData->noOfSections;i++) {
+    WriteBits(hBitStream,sectionData->sectionInfo[i].codeBook,4);
+    sectLen = sectionData->sectionInfo[i].sfbCnt;        
+
+    while(sectLen >= sectEscapeVal) {
+       
+      WriteBits(hBitStream,sectEscapeVal,sectLenBits);
+      sectLen = sectLen - sectEscapeVal;
+    }
+    WriteBits(hBitStream,sectLen,sectLenBits);
+  }
+  return(GetBitsAvail(hBitStream)-dbgVal);
+}
+
+/*****************************************************************************
+*
+* function name: encodeScaleFactorData
+* description:  encode DPCM coded scale factors
+* returns:      none
+*
+*****************************************************************************/
+static Word32 encodeScaleFactorData(UWord16        *maxValueInSfb,
+                                    SECTION_DATA   *sectionData,
+                                    Word16         *scalefac,
+                                    HANDLE_BIT_BUF  hBitStream)
+{
+  Word16 i,j,lastValScf,deltaScf;
+  Word16 dbgVal = GetBitsAvail(hBitStream);
+  SECTION_INFO* psectioninfo; 
+
+  lastValScf=scalefac[sectionData->firstScf];                    
+
+  for(i=0;i<sectionData->noOfSections;i++){
+    psectioninfo = &(sectionData->sectionInfo[i]); 
+    if (psectioninfo->codeBook != CODE_BOOK_ZERO_NO){
+      for (j=psectioninfo->sfbStart;
+           j<psectioninfo->sfbStart+psectioninfo->sfbCnt; j++){
+         
+        if(maxValueInSfb[j] == 0) {
+          deltaScf = 0;                                          
+        }
+        else {
+          deltaScf = lastValScf - scalefac[j];
+          lastValScf = scalefac[j];                              
+        }
+         
+        if(codeScalefactorDelta(deltaScf,hBitStream)){
+          return(1);
+        }
+      }
+    }
+
+  }
+  return(GetBitsAvail(hBitStream)-dbgVal);
+}
+
+/*****************************************************************************
+*
+* function name:encodeMsInfo
+* description: encodes MS-Stereo Info
+* returns:     none
+*
+*****************************************************************************/
+static void encodeMSInfo(Word16          sfbCnt,
+                         Word16          grpSfb,
+                         Word16          maxSfb,
+                         Word16          msDigest,
+                         Word16         *jsFlags,
+                         HANDLE_BIT_BUF  hBitStream)
+{
+  Word16 sfb, sfbOff;
+
+   
+  switch(msDigest)
+  {
+    case MS_NONE:
+      WriteBits(hBitStream,SI_MS_MASK_NONE,2);
+      break;
+
+    case MS_ALL:
+      WriteBits(hBitStream,SI_MS_MASK_ALL,2);
+      break;
+
+    case MS_SOME:
+      WriteBits(hBitStream,SI_MS_MASK_SOME,2);
+      for(sfbOff = 0; sfbOff < sfbCnt; sfbOff+=grpSfb) {
+        for(sfb=0; sfb<maxSfb; sfb++) {
+             
+          if(jsFlags[sfbOff+sfb] & MS_ON) {
+            WriteBits(hBitStream,1,1);
+          }
+          else{
+            WriteBits(hBitStream,0,1);
+          }
+        }
+      }
+      break;
+  }
+
+}
+
+/*****************************************************************************
+*
+* function name: encodeTnsData
+* description:  encode TNS data (filter order, coeffs, ..)
+* returns:      none
+*
+*****************************************************************************/
+static void encodeTnsData(TNS_INFO tnsInfo,
+                          Word16 blockType,
+                          HANDLE_BIT_BUF hBitStream) {
+  Word16 i,k;
+  Flag tnsPresent;
+  Word16 numOfWindows;
+  Word16 coefBits;
+  Flag isShort;
+
+       
+  if (blockType==2) {
+    isShort = 1;
+    numOfWindows = TRANS_FAC;
+  }
+  else {
+    isShort = 0;
+    numOfWindows = 1;
+  }
+
+  tnsPresent=0;                                                  
+  for (i=0; i<numOfWindows; i++) {
+     
+    if (tnsInfo.tnsActive[i]) {
+      tnsPresent=1;                                              
+    }
+  }
+   
+  if (tnsPresent==0) {
+    WriteBits(hBitStream,0,1);
+  }
+  else{ /* there is data to be written*/
+    WriteBits(hBitStream,1,1); /*data_present */
+    for (i=0; i<numOfWindows; i++) {
+       
+      WriteBits(hBitStream,tnsInfo.tnsActive[i],(isShort?1:2));
+       
+      if (tnsInfo.tnsActive[i]) {
+         
+        WriteBits(hBitStream,((tnsInfo.coefRes[i] - 4)==0?1:0),1);
+         
+        WriteBits(hBitStream,tnsInfo.length[i],(isShort?4:6));
+         
+        WriteBits(hBitStream,tnsInfo.order[i],(isShort?3:5));
+         
+        if (tnsInfo.order[i]){
+          WriteBits(hBitStream, FILTER_DIRECTION, 1);
+           
+          if(tnsInfo.coefRes[i] == 4) {
+            coefBits = 3;                                                
+            for(k=0; k<tnsInfo.order[i]; k++) {
+                 
+              if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 3 ||
+                  tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -4) {
+                coefBits = 4;                                            
+                break;
+              }
+            }
+          }
+          else {
+            coefBits = 2;                                                
+            for(k=0; k<tnsInfo.order[i]; k++) {
+                 
+              if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 1 ||
+                  tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -2) {
+                coefBits = 3;                                            
+                break;
+              }
+            }
+          }
+          WriteBits(hBitStream, tnsInfo.coefRes[i] - coefBits, 1); /*coef_compres*/
+          for (k=0; k<tnsInfo.order[i]; k++ ) {
+            static const Word16 rmask[] = {0,1,3,7,15};
+             
+            WriteBits(hBitStream,tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] & rmask[coefBits],coefBits);
+          }
+        }
+      }
+    }
+  }
+
+}
+
+/*****************************************************************************
+*
+* function name: encodeGainControlData
+* description:  unsupported
+* returns:      none
+*
+*****************************************************************************/
+static void encodeGainControlData(HANDLE_BIT_BUF hBitStream)
+{
+  WriteBits(hBitStream,0,1);
+}
+
+/*****************************************************************************
+*
+* function name: encodePulseData
+* description:  not supported yet (dummy)
+* returns:      none
+*
+*****************************************************************************/
+static void encodePulseData(HANDLE_BIT_BUF hBitStream)
+{
+  WriteBits(hBitStream,0,1);
+}
+
+
+/*****************************************************************************
+*
+* function name: WriteIndividualChannelStream
+* description:  management of write process of individual channel stream
+* returns:      none
+*
+*****************************************************************************/
+static void
+writeIndividualChannelStream(Flag   commonWindow,
+                             Word16 mdctScale,
+                             Word16 windowShape,
+                             Word16 groupingMask,
+                             Word16 *sfbOffset,
+                             Word16 scf[],
+                             UWord16 *maxValueInSfb,
+                             Word16 globalGain,
+                             Word16 quantSpec[],
+                             SECTION_DATA *sectionData,
+                             HANDLE_BIT_BUF hBitStream,
+                             TNS_INFO tnsInfo)
+{
+  Word16 logNorm;
+
+  logNorm = LOG_NORM_PCM - (mdctScale + 1);
+
+  encodeGlobalGain(globalGain, logNorm,scf[sectionData->firstScf], hBitStream);
+
+   
+  if(!commonWindow) {
+    encodeIcsInfo(sectionData->blockType, windowShape, groupingMask, sectionData, hBitStream);
+  }
+
+  encodeSectionData(sectionData, hBitStream);
+
+  encodeScaleFactorData(maxValueInSfb,
+                        sectionData,
+                        scf,
+                        hBitStream);
+
+  encodePulseData(hBitStream);
+
+  encodeTnsData(tnsInfo, sectionData->blockType, hBitStream);
+
+  encodeGainControlData(hBitStream);
+
+  encodeSpectralData(sfbOffset,
+                     sectionData,
+                     quantSpec,
+                     hBitStream);
+
+}
+
+/*****************************************************************************
+*
+* function name: writeSingleChannelElement
+* description:  write single channel element to bitstream
+* returns:      none
+*
+*****************************************************************************/
+static Word16 writeSingleChannelElement(Word16 instanceTag,
+                                        Word16 *sfbOffset,
+                                        QC_OUT_CHANNEL* qcOutChannel,
+                                        HANDLE_BIT_BUF hBitStream,
+                                        TNS_INFO tnsInfo)
+{
+  WriteBits(hBitStream,ID_SCE,3);
+  WriteBits(hBitStream,instanceTag,4);
+  writeIndividualChannelStream(0,
+                               qcOutChannel->mdctScale,
+                               qcOutChannel->windowShape,
+                               qcOutChannel->groupingMask,
+                               sfbOffset,
+                               qcOutChannel->scf,
+                               qcOutChannel->maxValueInSfb,
+                               qcOutChannel->globalGain,
+                               qcOutChannel->quantSpec,
+                               &(qcOutChannel->sectionData),
+                               hBitStream,
+                               tnsInfo
+                               );
+  return(0);
+}
+
+
+
+/*****************************************************************************
+*
+* function name: writeChannelPairElement
+* description:
+* returns:      none
+*
+*****************************************************************************/
+static Word16 writeChannelPairElement(Word16 instanceTag,
+                                      Word16 msDigest,
+                                      Word16 msFlags[MAX_GROUPED_SFB],
+                                      Word16 *sfbOffset[2],
+                                      QC_OUT_CHANNEL qcOutChannel[2],
+                                      HANDLE_BIT_BUF hBitStream,
+                                      TNS_INFO tnsInfo[2])
+{
+  WriteBits(hBitStream,ID_CPE,3);
+  WriteBits(hBitStream,instanceTag,4);
+  WriteBits(hBitStream,1,1); /* common window */
+
+  encodeIcsInfo(qcOutChannel[0].sectionData.blockType,
+                qcOutChannel[0].windowShape,
+                qcOutChannel[0].groupingMask,
+                &(qcOutChannel[0].sectionData),
+                hBitStream);
+
+  encodeMSInfo(qcOutChannel[0].sectionData.sfbCnt,
+               qcOutChannel[0].sectionData.sfbPerGroup,
+               qcOutChannel[0].sectionData.maxSfbPerGroup,
+               msDigest,
+               msFlags,
+               hBitStream);
+
+  writeIndividualChannelStream(1,
+                               qcOutChannel[0].mdctScale,
+                               qcOutChannel[0].windowShape,
+                               qcOutChannel[0].groupingMask,
+                               sfbOffset[0],
+                               qcOutChannel[0].scf,
+                               qcOutChannel[0].maxValueInSfb,
+                               qcOutChannel[0].globalGain,
+                               qcOutChannel[0].quantSpec,
+                               &(qcOutChannel[0].sectionData),
+                               hBitStream,
+                               tnsInfo[0]);
+
+  writeIndividualChannelStream(1,
+                               qcOutChannel[1].mdctScale,
+                               qcOutChannel[1].windowShape,
+                               qcOutChannel[1].groupingMask,
+                               sfbOffset[1],
+                               qcOutChannel[1].scf,
+                               qcOutChannel[1].maxValueInSfb,
+                               qcOutChannel[1].globalGain,
+                               qcOutChannel[1].quantSpec,
+                               &(qcOutChannel[1].sectionData),
+                               hBitStream,
+                               tnsInfo[1]);
+
+  return(0);
+}
+
+
+
+/*****************************************************************************
+*
+* function name: writeFillElement
+* description:  write fill elements to bitstream
+* returns:      none
+*
+*****************************************************************************/
+static void writeFillElement( const UWord8 *ancBytes,
+                              Word16 totFillBits,
+                              HANDLE_BIT_BUF hBitStream)
+{
+  Word16 i;
+  Word16 cnt,esc_count;
+
+  /*
+    Write fill Element(s):
+    amount of a fill element can be 7+X*8 Bits, X element of [0..270]
+  */
+    
+  while(totFillBits >= (3+4)) {
+    cnt = min(((totFillBits - (3+4)) >> 3), ((1<<4)-1));
+
+    WriteBits(hBitStream,ID_FIL,3);
+    WriteBits(hBitStream,cnt,4);
+
+    totFillBits = totFillBits - (3+4);
+
+     
+    if ((cnt == (1<<4)-1)) {
+
+      esc_count = min( ((totFillBits >> 3) - ((1<<4)-1)), (1<<8)-1);
+      WriteBits(hBitStream,esc_count,8);
+      totFillBits = (totFillBits - 8);
+      cnt = cnt + (esc_count - 1);
+    }
+
+    for(i=0;i<cnt;i++) {
+       
+      if(ancBytes)
+        WriteBits(hBitStream, *ancBytes++,8);
+      else
+        WriteBits(hBitStream,0,8);
+      totFillBits = totFillBits - 8;
+    }
+  }
+}
+

+/*****************************************************************************
+*
+* function name: WriteBitStream
+* description:  main function of write bitsteam process
+* returns:      0 if success
+*
+*****************************************************************************/
+Word16 WriteBitstream (HANDLE_BIT_BUF hBitStream,
+                       ELEMENT_INFO elInfo,
+                       QC_OUT *qcOut,
+                       PSY_OUT *psyOut,
+                       Word16 *globUsedBits,					   
+                       const UWord8 *ancBytes,

+					   Word16 sampindex
+                       ) /* returns error code */
+{
+  Word16 bitMarkUp;
+  Word16 elementUsedBits;
+  Word16 frameBits=0;

+

+  /*   struct bitbuffer bsWriteCopy; */

+  bitMarkUp = GetBitsAvail(hBitStream); 

+  if(qcOut->qcElement.adtsUsed)  /*  write adts header*/

+  {

+	  WriteBits(hBitStream, 0xFFF, 12); /* 12 bit Syncword */

+	  WriteBits(hBitStream, 1, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */

+	  WriteBits(hBitStream, 0, 2); /* layer == 0 */

+	  WriteBits(hBitStream, 1, 1); /* protection absent */

+	  WriteBits(hBitStream, 1, 2); /* profile */

+	  WriteBits(hBitStream, sampindex, 4); /* sampling rate */

+	  WriteBits(hBitStream, 0, 1); /* private bit */

+	  WriteBits(hBitStream, elInfo.nChannelsInEl, 3); /* ch. config (must be > 0) */

+								   /* simply using numChannels only works for

+									6 channels or less, else a channel

+									configuration should be written */

+	  WriteBits(hBitStream, 0, 1); /* original/copy */

+	  WriteBits(hBitStream, 0, 1); /* home */	  

+	  

+	  /* Variable ADTS header */

+	  WriteBits(hBitStream, 0, 1); /* copyr. id. bit */

+	  WriteBits(hBitStream, 0, 1); /* copyr. id. start */

+	  WriteBits(hBitStream, *globUsedBits >> 3, 13);

+	  WriteBits(hBitStream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */

+	  WriteBits(hBitStream, 0, 2); /* raw data blocks (0+1=1) */  

+  }

+
+  *globUsedBits=0;                                               
+
+  {
+
+    Word16 *sfbOffset[2];
+    TNS_INFO tnsInfo[2];
+    elementUsedBits = 0;                                         
+
+    switch (elInfo.elType) {
+
+      case ID_SCE:      /* single channel */
+        sfbOffset[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets;
+        tnsInfo[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo;
+
+        writeSingleChannelElement(elInfo.instanceTag,
+                                  sfbOffset[0],
+                                  &qcOut->qcChannel[elInfo.ChannelIndex[0]],
+                                  hBitStream,
+                                  tnsInfo[0]);
+        break;
+
+      case ID_CPE:     /* channel pair */
+        {
+          Word16 msDigest;
+          Word16 *msFlags = psyOut->psyOutElement.toolsInfo.msMask;
+          msDigest = psyOut->psyOutElement.toolsInfo.msDigest;                        
+          sfbOffset[0] =
+            psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets;
+          sfbOffset[1] =
+            psyOut->psyOutChannel[elInfo.ChannelIndex[1]].sfbOffsets;
+
+          tnsInfo[0]=
+            psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo;
+          tnsInfo[1]=
+            psyOut->psyOutChannel[elInfo.ChannelIndex[1]].tnsInfo;
+          writeChannelPairElement(elInfo.instanceTag,
+                                  msDigest,
+                                  msFlags,
+                                  sfbOffset,
+                                  &qcOut->qcChannel[elInfo.ChannelIndex[0]],
+                                  hBitStream,
+                                  tnsInfo);
+        }
+        break;
+
+      default:
+        return(1);
+
+      }   /* switch */
+
+    elementUsedBits = elementUsedBits - bitMarkUp;
+    bitMarkUp = GetBitsAvail(hBitStream);
+    frameBits = frameBits + elementUsedBits + bitMarkUp;
+
+  }
+
+  writeFillElement(NULL,
+                   qcOut->totFillBits, 
+                   hBitStream);
+
+  WriteBits(hBitStream,ID_END,3);
+
+  /* byte alignement */
+  WriteBits(hBitStream,0, (8 - (hBitStream->cntBits & 7)) & 7);          
+  
+  *globUsedBits = *globUsedBits- bitMarkUp;
+  bitMarkUp = GetBitsAvail(hBitStream);                                  
+  *globUsedBits = *globUsedBits + bitMarkUp;
+  frameBits = frameBits + *globUsedBits;
+
+   
+  if (frameBits !=  (qcOut->totStaticBitsUsed+qcOut->totDynBitsUsed + qcOut->totAncBitsUsed +
+                     qcOut->totFillBits + qcOut->alignBits)) {
+    return(-1);
+  }
+  return(0);
+}
diff --git a/media/libstagefright/codecs/aacenc/src/block_switch.c b/media/libstagefright/codecs/aacenc/src/block_switch.c
new file mode 100644
index 0000000..c0054f7
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/block_switch.c
@@ -0,0 +1,431 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		block_switch.c

+

+	Content:	Block switching functions

+

+*******************************************************************************/
+
+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"
+#include "psy_const.h"
+#include "block_switch.h"
+
+
+#define ENERGY_SHIFT (8 - 1)
+
+/**************** internal function prototypes ***********/
+static Word16
+IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]);
+
+static Word32
+SrchMaxWithIndex(const Word32 *in, Word16 *index, Word16 n);
+
+
+Word32
+CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+                 Word16 *timeSignal,
+                 Word16 chIncrement,
+                 Word16 windowLen);
+
+
+
+/****************** Constants *****************************/
+
+
+/*
+  IIR high pass coeffs
+*/
+Word32 hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = {
+  0xbec8b439, 0x609d4952  /* -0.5095f, 0.7548f */ 
+};
+
+static const Word32 accWindowNrgFac = 0x26666666;                   /* factor for accumulating filtered window energies 0.3 */
+static const Word32 oneMinusAccWindowNrgFac = 0x5999999a;			/* 0.7 */
+static const Word32 invAttackRatioHighBr = 0x0ccccccd;              /* inverted lower ratio limit for attacks 0.1*/
+static const Word32 invAttackRatioLowBr =  0x072b020c;              /* 0.056 */
+static const Word32 minAttackNrg = 0x00001e84;                      /* minimum energy for attacks 1e+6 */
+
+
+/****************** Routines ****************************/
+
+
+/*****************************************************************************
+*
+* function name: InitBlockSwitching
+* description:  init Block Switching parameter.
+* returns:      TRUE if success
+*
+**********************************************************************************/
+Word16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+                          const Word32 bitRate, const Word16 nChannels)
+{
+  /* select attackRatio */
+           
+  if ((sub(nChannels,1)==0 && L_sub(bitRate, 24000) > 0) || 
+      (sub(nChannels,1)>0 && bitRate > (nChannels * 16000))) {
+    blockSwitchingControl->invAttackRatio = invAttackRatioHighBr;
+  }
+  else  {
+    blockSwitchingControl->invAttackRatio = invAttackRatioLowBr;
+  }
+
+  return(TRUE);
+}
+
+static Word16 suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = {
+  /* Attack in Window 0 */ {1,  3,  3,  1},
+  /* Attack in Window 1 */ {1,  1,  3,  3},
+  /* Attack in Window 2 */ {2,  1,  3,  2},
+  /* Attack in Window 3 */ {3,  1,  3,  1},
+  /* Attack in Window 4 */ {3,  1,  1,  3},
+  /* Attack in Window 5 */ {3,  2,  1,  2},
+  /* Attack in Window 6 */ {3,  3,  1,  1},
+  /* Attack in Window 7 */ {3,  3,  1,  1}
+};
+
+/*****************************************************************************
+*
+* function name: BlockSwitching
+* description:  detect this frame whether there is an attack
+* returns:      TRUE if success
+*
+**********************************************************************************/
+Word16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+                      Word16 *timeSignal,
+					  Word32 sampleRate,
+                      Word16 chIncrement)
+{
+  Word32 i, w;
+  Word32 enM1, enMax;
+
+  /* Reset grouping info */
+  for (i=0; i<TRANS_FAC; i++) {
+    blockSwitchingControl->groupLen[i] = 0;                                      
+  }
+
+
+  /* Search for position and amplitude of attack in last frame (1 windows delay) */
+  blockSwitchingControl->maxWindowNrg = SrchMaxWithIndex( &blockSwitchingControl->windowNrg[0][BLOCK_SWITCH_WINDOWS-1],
+                                                          &blockSwitchingControl->attackIndex,
+                                                          BLOCK_SWITCH_WINDOWS);
+
+  blockSwitchingControl->attackIndex = blockSwitchingControl->lastAttackIndex;   
+
+  /* Set grouping info */
+  blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;                          
+
+  for (i=0; i<MAX_NO_OF_GROUPS; i++) {
+    blockSwitchingControl->groupLen[i] = suggestedGroupingTable[blockSwitchingControl->attackIndex][i];  
+  }

+	
+  /* if the samplerate is less than 16000, it should be all the short block, avoid pre&post echo */
+  if(sampleRate >= 16000) {
+	  /* Save current window energy as last window energy */
+	  for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
+		  blockSwitchingControl->windowNrg[0][w] = blockSwitchingControl->windowNrg[1][w];             
+		  blockSwitchingControl->windowNrgF[0][w] = blockSwitchingControl->windowNrgF[1][w];           
+	  }
+
+
+	  /* Calculate unfiltered and filtered energies in subwindows and combine to segments */
+	  CalcWindowEnergy(blockSwitchingControl, timeSignal, chIncrement, BLOCK_SWITCH_WINDOW_LEN);
+
+	  /* reset attack */
+	  blockSwitchingControl->attack = FALSE;                                         
+
+	  enMax = 0;                                                                     
+	  enM1 = blockSwitchingControl->windowNrgF[0][BLOCK_SWITCH_WINDOWS-1];           
+
+	  for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
+		  Word32 enM1_Tmp, accWindowNrg_Tmp, windowNrgF_Tmp;
+		  Word16 enM1_Shf, accWindowNrg_Shf, windowNrgF_Shf;
+
+		  accWindowNrg_Shf = norm_l(blockSwitchingControl->accWindowNrg);
+		  enM1_Shf = norm_l(enM1);
+		  windowNrgF_Shf = norm_l(blockSwitchingControl->windowNrgF[1][w]);
+
+		  accWindowNrg_Tmp = blockSwitchingControl->accWindowNrg << accWindowNrg_Shf;
+		  enM1_Tmp = enM1 << enM1_Shf;
+		  windowNrgF_Tmp = blockSwitchingControl->windowNrgF[1][w] << windowNrgF_Shf;
+
+		  /* a sliding average of the previous energies */
+		  blockSwitchingControl->accWindowNrg = (fixmul(oneMinusAccWindowNrgFac, accWindowNrg_Tmp) >> accWindowNrg_Shf) +
+			  (fixmul(accWindowNrgFac, enM1_Tmp) >> enM1_Shf);
+
+
+		  /* if the energy with the ratio is bigger than the average, and the attack and short block  */
+		  if ((fixmul(windowNrgF_Tmp, blockSwitchingControl->invAttackRatio) >> windowNrgF_Shf) >
+			  blockSwitchingControl->accWindowNrg ) {
+				  blockSwitchingControl->attack = TRUE;                                      
+				  blockSwitchingControl->lastAttackIndex = w;                                
+		  }
+		  enM1 = blockSwitchingControl->windowNrgF[1][w];                              
+		  enMax = max(enMax, enM1);
+	  }
+
+	  if (enMax < minAttackNrg) {
+		  blockSwitchingControl->attack = FALSE;                                       
+	  }
+  }
+  else
+  {
+	  blockSwitchingControl->attack = TRUE;
+  }
+
+  /* Check if attack spreads over frame border */     
+  if ((!blockSwitchingControl->attack) && (blockSwitchingControl->lastattack)) {
+     
+    if (blockSwitchingControl->attackIndex == TRANS_FAC-1) {
+      blockSwitchingControl->attack = TRUE;                                      
+    }
+
+    blockSwitchingControl->lastattack = FALSE;                                   
+  }
+  else {
+    blockSwitchingControl->lastattack = blockSwitchingControl->attack;           
+  }
+
+  blockSwitchingControl->windowSequence =  blockSwitchingControl->nextwindowSequence;    
+
+     
+  if (blockSwitchingControl->attack) {
+    blockSwitchingControl->nextwindowSequence = SHORT_WINDOW;
+  }
+  else {
+    blockSwitchingControl->nextwindowSequence = LONG_WINDOW;
+  }
+
+  /* update short block group */ 
+  if (blockSwitchingControl->nextwindowSequence == SHORT_WINDOW) {
+     
+    if (blockSwitchingControl->windowSequence== LONG_WINDOW) {
+      blockSwitchingControl->windowSequence = START_WINDOW;                      
+    }
+     
+    if (blockSwitchingControl->windowSequence == STOP_WINDOW) {
+      blockSwitchingControl->windowSequence = SHORT_WINDOW;                      
+      blockSwitchingControl->noOfGroups = 3;                                     
+      blockSwitchingControl->groupLen[0] = 3;                                    
+      blockSwitchingControl->groupLen[1] = 3;                                    
+      blockSwitchingControl->groupLen[2] = 2;                                    
+    }
+  }
+
+  /* update block type */  
+  if (blockSwitchingControl->nextwindowSequence == LONG_WINDOW) {
+     
+    if (blockSwitchingControl->windowSequence == SHORT_WINDOW) {
+      blockSwitchingControl->nextwindowSequence = STOP_WINDOW;                   
+    }
+  }
+
+  return(TRUE);
+}
+
+
+/*****************************************************************************
+*
+* function name: SrchMaxWithIndex
+* description:  search for the biggest value in an array
+* returns:      the max value
+*
+**********************************************************************************/
+static Word32 SrchMaxWithIndex(const Word32 in[], Word16 *index, Word16 n)
+{
+  Word32 max;
+  Word32 i, idx;
+
+  /* Search maximum value in array and return index and value */
+  max = 0;                                                       
+  idx = 0;                                                       
+
+  for (i = 0; i < n; i++) {
+     
+    if (in[i+1]  > max) {
+      max = in[i+1];                                             
+      idx = i;                                                   
+    }
+  }
+  *index = idx;                                                  
+
+  return(max);
+}
+
+/*****************************************************************************
+*
+* function name: CalcWindowEnergy
+* description:  calculate the energy before iir-filter and after irr-filter
+* returns:      TRUE if success
+*
+**********************************************************************************/
+#ifndef ARMV5E

+Word32 CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+                        Word16 *timeSignal,
+                        Word16 chIncrement,
+                        Word16 windowLen)
+{
+  Word32 w, i, wOffset, tidx, ch;
+  Word32 accuUE, accuFE;
+  Word32 tempUnfiltered;
+  Word32 tempFiltered;

+  Word32 states0, states1;

+  Word32 Coeff0, Coeff1;

+

+
+  states0 = blockSwitchingControl->iirStates[0];

+  states1 = blockSwitchingControl->iirStates[1];

+  Coeff0 = hiPassCoeff[0];

+  Coeff1 = hiPassCoeff[1];
+  tidx = 0;                                                   
+  for (w=0; w < BLOCK_SWITCH_WINDOWS; w++) {
+
+    accuUE = 0;                                                  
+    accuFE = 0;                                                  
+
+    for(i=0; i<windowLen; i++) {
+	  Word32 accu1, accu2, accu3;

+	  Word32 out;

+	  tempUnfiltered = timeSignal[tidx];
+      tidx = tidx + chIncrement;
+

+	  accu1 = L_mpy_ls(Coeff1, tempUnfiltered);

+	  accu2 = fixmul( Coeff0, states1 );

+	  accu3 = accu1 - states0;

+	  out = accu3 - accu2;

+

+	  states0 = accu1;             

+	  states1 = out;               

+

+      tempFiltered = extract_h(out);	  
+      accuUE += (tempUnfiltered * tempUnfiltered) >> ENERGY_SHIFT;
+      accuFE += (tempFiltered * tempFiltered) >> ENERGY_SHIFT;
+    }
+
+    blockSwitchingControl->windowNrg[1][w] = accuUE;             
+    blockSwitchingControl->windowNrgF[1][w] = accuFE;            
+
+  }

+

+  blockSwitchingControl->iirStates[0] = states0;

+  blockSwitchingControl->iirStates[1] = states1;
+
+  return(TRUE);
+}
+#endif
+
+/*****************************************************************************
+*
+* function name: IIRFilter
+* description:  calculate the iir-filter for an array
+* returns:      the result after iir-filter
+*
+**********************************************************************************/
+static Word16 IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[])
+{
+  Word32 accu1, accu2, accu3;
+  Word32 out;
+
+  accu1 = L_mpy_ls(coeff[1], in);
+  accu3 = accu1 - states[0];
+  accu2 = fixmul( coeff[0], states[1] );
+  out = accu3 - accu2;
+
+  states[0] = accu1;             
+  states[1] = out;               
+
+  return round16(out);
+}
+
+
+static Word16 synchronizedBlockTypeTable[4][4] = {
+  /*                 LONG_WINDOW   START_WINDOW  SHORT_WINDOW  STOP_WINDOW */
+  /* LONG_WINDOW  */{LONG_WINDOW,  START_WINDOW, SHORT_WINDOW, STOP_WINDOW},
+  /* START_WINDOW */{START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
+  /* SHORT_WINDOW */{SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
+  /* STOP_WINDOW  */{STOP_WINDOW,  SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW}
+};
+
+
+/*****************************************************************************
+*
+* function name: SyncBlockSwitching
+* description:  update block type and group value
+* returns:      TRUE if success
+*
+**********************************************************************************/
+Word16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
+                          BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
+                          const Word16 nChannels)
+{
+  Word16 i;
+  Word16 patchType = LONG_WINDOW;                
+
+   
+  if (nChannels == 1) { /* Mono */
+    if (blockSwitchingControlLeft->windowSequence != SHORT_WINDOW) {
+      blockSwitchingControlLeft->noOfGroups = 1;                         
+      blockSwitchingControlLeft->groupLen[0] = 1;                        
+
+      for (i=1; i<TRANS_FAC; i++) {
+        blockSwitchingControlLeft->groupLen[i] = 0;                      
+      }
+    }
+  }
+  else { /* Stereo common Window */
+    patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->windowSequence];        
+    patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->windowSequence];       
+
+    /* Set synchronized Blocktype */
+    blockSwitchingControlLeft->windowSequence = patchType;               
+    blockSwitchingControlRight->windowSequence = patchType;              
+
+    /* Synchronize grouping info */     
+    if(patchType != SHORT_WINDOW) { /* Long Blocks */
+      /* Set grouping info */
+      blockSwitchingControlLeft->noOfGroups = 1;                         
+      blockSwitchingControlRight->noOfGroups = 1;                        
+      blockSwitchingControlLeft->groupLen[0] = 1;                        
+      blockSwitchingControlRight->groupLen[0] = 1;                       
+
+      for (i=1; i<TRANS_FAC; i++) {
+        blockSwitchingControlLeft->groupLen[i] = 0;                      
+        blockSwitchingControlRight->groupLen[i] = 0;                     
+      }
+    }
+    else {
+       
+      if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) {
+        /* Left Channel wins */
+        blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups;          
+        for (i=0; i<TRANS_FAC; i++) {
+          blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i];      
+        }
+      }
+      else {
+        /* Right Channel wins */
+        blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups;          
+        for (i=0; i<TRANS_FAC; i++) {
+          blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i];      
+        }
+      }
+    }
+  } /*endif Mono or Stereo */
+
+  return(TRUE);
+}
diff --git a/media/libstagefright/codecs/aacenc/src/channel_map.c b/media/libstagefright/codecs/aacenc/src/channel_map.c
new file mode 100644
index 0000000..247293b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/channel_map.c
@@ -0,0 +1,123 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		channel_map.c

+

+	Content:	channel mapping functions

+

+*******************************************************************************/
+
+#include "channel_map.h"
+#include "bitenc.h"
+#include "psy_const.h"
+#include "qc_data.h"
+
+static const Word16 maxChannelBits = MAXBITS_COEF;
+
+static Word16 initElement(ELEMENT_INFO* elInfo, ELEMENT_TYPE elType)
+{
+  Word16 error=0;                                    
+
+  elInfo->elType=elType;                             
+
+  switch(elInfo->elType) {
+
+    case ID_SCE:
+      elInfo->nChannelsInEl=1;                       
+
+      elInfo->ChannelIndex[0]=0;                     
+
+      elInfo->instanceTag=0;                         
+      break;
+
+    case ID_CPE:
+
+      elInfo->nChannelsInEl=2;                        
+
+      elInfo->ChannelIndex[0]=0;                      
+      elInfo->ChannelIndex[1]=1;                      
+
+      elInfo->instanceTag=0;                    
+      break;
+
+    default:
+      error=1;                                  
+  }
+
+  return error;
+}
+
+
+Word16 InitElementInfo (Word16 nChannels, ELEMENT_INFO* elInfo)
+{
+  Word16 error;
+  error = 0;                                        
+
+  switch(nChannels) {
+
+    case 1: 
+      initElement(elInfo, ID_SCE);
+      break;
+
+    case 2:
+      initElement(elInfo, ID_CPE);
+      break;
+
+    default:
+      error=4;                                         
+  }
+
+  return error;
+}
+
+
+Word16 InitElementBits(ELEMENT_BITS *elementBits,
+                       ELEMENT_INFO elInfo,
+                       Word32 bitrateTot,
+                       Word16 averageBitsTot,
+                       Word16 staticBitsTot)
+{
+  Word16 error;
+  error = 0;                                    
+
+   switch(elInfo.nChannelsInEl) {
+    case 1:
+      elementBits->chBitrate = bitrateTot;                     
+      elementBits->averageBits = averageBitsTot - staticBitsTot;
+      elementBits->maxBits = maxChannelBits;                   
+
+      elementBits->maxBitResBits = maxChannelBits - averageBitsTot;
+      elementBits->maxBitResBits = elementBits->maxBitResBits - (elementBits->maxBitResBits & 7); 
+      elementBits->bitResLevel = elementBits->maxBitResBits;   
+      elementBits->relativeBits  = 0x4000; /* 1.0f/2 */        
+      break;
+
+    case 2:
+      elementBits->chBitrate   = bitrateTot >> 1;
+      elementBits->averageBits = averageBitsTot - staticBitsTot;
+      elementBits->maxBits     = maxChannelBits << 1;
+
+      elementBits->maxBitResBits = (maxChannelBits << 1) - averageBitsTot;
+      elementBits->maxBitResBits = elementBits->maxBitResBits - (elementBits->maxBitResBits & 7);   
+      elementBits->bitResLevel = elementBits->maxBitResBits;     
+      elementBits->relativeBits = 0x4000; /* 1.0f/2 */           
+      break;
+
+    default:
+      error = 1;                                                 
+  }
+  return error;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/dyn_bits.c b/media/libstagefright/codecs/aacenc/src/dyn_bits.c
new file mode 100644
index 0000000..3deacca
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/dyn_bits.c
@@ -0,0 +1,545 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		dyn_bits.c

+

+	Content:	Noiseless coder module functions

+

+*******************************************************************************/
+
+#include "aac_rom.h"
+#include "dyn_bits.h"
+#include "bit_cnt.h"
+#include "psy_const.h"
+
+
+/*****************************************************************************
+*
+* function name: buildBitLookUp
+* description:  count bits using all possible tables
+*
+*****************************************************************************/
+static void
+buildBitLookUp(const Word16 *quantSpectrum,
+               const Word16 maxSfb,
+               const Word16 *sfbOffset,
+               const UWord16 *sfbMax,
+               Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+               SECTION_INFO * sectionInfo)
+{
+  Word32 i;
+
+  for (i=0; i<maxSfb; i++) {
+    Word16 sfbWidth, maxVal;
+
+    sectionInfo[i].sfbCnt = 1;                                   
+    sectionInfo[i].sfbStart = i;                                 
+    sectionInfo[i].sectionBits = INVALID_BITCOUNT;               
+    sectionInfo[i].codeBook = -1;                                
+    sfbWidth = sfbOffset[i + 1] - sfbOffset[i];              
+    maxVal = sfbMax[i];                                          
+    bitCount(quantSpectrum + sfbOffset[i], sfbWidth, maxVal, bitLookUp[i]);
+  }
+}
+
+
+/*****************************************************************************
+*
+* function name: findBestBook
+* description:  essential helper functions
+*
+*****************************************************************************/
+static Word16
+findBestBook(const Word16 *bc, Word16 *book)
+{
+  Word32 minBits, j;
+  minBits = INVALID_BITCOUNT;                                    
+
+  for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
+     
+    if (bc[j] < minBits) {
+      minBits = bc[j];                                           
+      *book = j;                                                 
+    }
+  }
+  return extract_l(minBits);
+}
+
+static Word16
+findMinMergeBits(const Word16 *bc1, const Word16 *bc2)
+{
+  Word32 minBits, j, sum;
+  minBits = INVALID_BITCOUNT;                                    
+
+  for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
+    sum = bc1[j] + bc2[j];
+    if (sum < minBits) {
+      minBits = sum;                                             
+    }
+  }
+  return extract_l(minBits);
+}
+
+static void
+mergeBitLookUp(Word16 *bc1, const Word16 *bc2)
+{
+  Word32 j;
+
+  for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
+    bc1[j] = min(bc1[j] + bc2[j], INVALID_BITCOUNT);
+  }
+}
+
+static Word16
+findMaxMerge(const Word16 mergeGainLookUp[MAX_SFB_LONG],
+             const SECTION_INFO *sectionInfo,
+             const Word16 maxSfb, Word16 *maxNdx)
+{
+  Word32 i, maxMergeGain;
+  maxMergeGain = 0;                                              
+
+  for (i=0; i+sectionInfo[i].sfbCnt < maxSfb; i += sectionInfo[i].sfbCnt) {
+     
+    if (mergeGainLookUp[i] > maxMergeGain) {
+      maxMergeGain = mergeGainLookUp[i];                         
+      *maxNdx = i;                                               
+    }
+  }
+  return extract_l(maxMergeGain);
+}
+
+
+
+static Word16
+CalcMergeGain(const SECTION_INFO *sectionInfo,
+              Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+              const Word16 *sideInfoTab,
+              const Word16 ndx1,
+              const Word16 ndx2)
+{
+  Word32 SplitBits;
+  Word32 MergeBits;
+  Word32 MergeGain;
+
+  /*
+    Bit amount for splitted sections
+  */
+  SplitBits = sectionInfo[ndx1].sectionBits + sectionInfo[ndx2].sectionBits;
+
+  MergeBits = sideInfoTab[sectionInfo[ndx1].sfbCnt + sectionInfo[ndx2].sfbCnt] +
+                  findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2]);
+  MergeGain = (SplitBits - MergeBits);
+
+  return extract_l(MergeGain);
+}
+
+/*
+  sectioning Stage 0:find minimum codbooks
+*/
+
+static void
+gmStage0(SECTION_INFO * sectionInfo,
+         Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+         const Word16 maxSfb)
+{
+  Word32 i;
+
+  for (i=0; i<maxSfb; i++) {
+    /* Side-Info bits will be calculated in Stage 1!  */
+     
+    if (sectionInfo[i].sectionBits == INVALID_BITCOUNT) {
+      sectionInfo[i].sectionBits = findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook));
+    }
+  }
+}
+
+/*
+  sectioning Stage 1:merge all connected regions with the same code book and
+  calculate side info
+*/
+
+static void
+gmStage1(SECTION_INFO * sectionInfo,
+         Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+         const Word16 maxSfb,
+         const Word16 *sideInfoTab)
+{
+  SECTION_INFO * sectionInfo_s;

+  SECTION_INFO * sectionInfo_e;

+  Word32 mergeStart, mergeEnd;
+  mergeStart = 0;                                                        
+
+  do {
+
+    sectionInfo_s = sectionInfo + mergeStart;

+	for (mergeEnd=mergeStart+1; mergeEnd<maxSfb; mergeEnd++) {
+      sectionInfo_e = sectionInfo + mergeEnd; 
+      if (sectionInfo_s->codeBook != sectionInfo_e->codeBook)
+        break;
+      sectionInfo_s->sfbCnt += 1;
+      sectionInfo_s->sectionBits += sectionInfo_e->sectionBits;
+
+      mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]);
+    }
+
+    sectionInfo_s->sectionBits += sideInfoTab[sectionInfo_s->sfbCnt];
+    sectionInfo[mergeEnd - 1].sfbStart = sectionInfo_s->sfbStart;      /* speed up prev search */  
+
+    mergeStart = mergeEnd;                                               
+
+     
+  } while (mergeStart - maxSfb < 0);
+}
+
+/*
+  sectioning Stage 2:greedy merge algorithm, merge connected sections with
+  maximum bit gain until no more gain is possible
+*/
+static void
+gmStage2(SECTION_INFO *sectionInfo,
+         Word16 mergeGainLookUp[MAX_SFB_LONG],
+         Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+         const Word16 maxSfb,
+         const Word16 *sideInfoTab)
+{
+  Word16 i;
+
+  for (i=0; i+sectionInfo[i].sfbCnt<maxSfb; i+=sectionInfo[i].sfbCnt) {
+    mergeGainLookUp[i] = CalcMergeGain(sectionInfo,
+                                       bitLookUp,
+                                       sideInfoTab,
+                                       i,
+                                       (i + sectionInfo[i].sfbCnt));
+  }
+
+  while (TRUE) {
+    Word16 maxMergeGain, maxNdx, maxNdxNext, maxNdxLast;
+
+    maxMergeGain = findMaxMerge(mergeGainLookUp, sectionInfo, maxSfb, &maxNdx);
+
+     
+    if (maxMergeGain <= 0)
+      break;
+
+
+    maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt;
+
+    sectionInfo[maxNdx].sfbCnt = sectionInfo[maxNdx].sfbCnt + sectionInfo[maxNdxNext].sfbCnt;
+    sectionInfo[maxNdx].sectionBits = sectionInfo[maxNdx].sectionBits +
+                                          (sectionInfo[maxNdxNext].sectionBits - maxMergeGain);
+
+
+    mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]);
+
+     
+    if (maxNdx != 0) {
+      maxNdxLast = sectionInfo[maxNdx - 1].sfbStart;
+      mergeGainLookUp[maxNdxLast] = CalcMergeGain(sectionInfo,
+                                                  bitLookUp,
+                                                  sideInfoTab,
+                                                  maxNdxLast,
+                                                  maxNdx);
+    }
+    maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt;
+
+    sectionInfo[maxNdxNext - 1].sfbStart = sectionInfo[maxNdx].sfbStart;             
+
+     
+    if (maxNdxNext - maxSfb < 0) {
+      mergeGainLookUp[maxNdx] = CalcMergeGain(sectionInfo,
+                                              bitLookUp,
+                                              sideInfoTab,
+                                              maxNdx,
+                                              maxNdxNext);
+    }
+  }
+}
+
+/*
+  count bits used by the noiseless coder
+*/
+static void
+noiselessCounter(SECTION_DATA *sectionData,
+                 Word16 mergeGainLookUp[MAX_SFB_LONG],
+                 Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+                 const Word16 *quantSpectrum,
+                 const UWord16 *maxValueInSfb,
+                 const Word16 *sfbOffset,
+                 const Word32 blockType)
+{
+  Word32 grpNdx, i;
+  Word16 *sideInfoTab = NULL;
+  SECTION_INFO *sectionInfo;
+
+  /*
+    use appropriate side info table
+  */   
+  switch (blockType)
+  {
+    case LONG_WINDOW:
+    case START_WINDOW:
+    case STOP_WINDOW:
+      sideInfoTab = sideInfoTabLong;
+      break;
+    case SHORT_WINDOW:
+      sideInfoTab = sideInfoTabShort;
+      break;
+  }
+
+
+  sectionData->noOfSections = 0;                                         
+  sectionData->huffmanBits = 0;                                          
+  sectionData->sideInfoBits = 0;                                         
+
+   
+  if (sectionData->maxSfbPerGroup == 0)
+    return;
+
+  /*
+    loop trough groups
+  */
+  for (grpNdx=0; grpNdx<sectionData->sfbCnt; grpNdx+=sectionData->sfbPerGroup) {
+
+    sectionInfo = sectionData->sectionInfo + sectionData->noOfSections;
+
+    buildBitLookUp(quantSpectrum,
+                   sectionData->maxSfbPerGroup,
+                   sfbOffset + grpNdx,
+                   maxValueInSfb + grpNdx,
+                   bitLookUp,
+                   sectionInfo);
+
+    /*
+       0.Stage
+    */
+    gmStage0(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup);
+
+    /*
+       1.Stage
+    */
+    gmStage1(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab);
+
+
+    /*
+       2.Stage
+    */
+    gmStage2(sectionInfo,
+             mergeGainLookUp,
+             bitLookUp,
+             sectionData->maxSfbPerGroup,
+             sideInfoTab);
+
+
+    /*
+       compress output, calculate total huff and side bits
+    */
+    for (i=0; i<sectionData->maxSfbPerGroup; i+=sectionInfo[i].sfbCnt) {
+      findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook));
+      sectionInfo[i].sfbStart = sectionInfo[i].sfbStart + grpNdx;
+
+      sectionData->huffmanBits = (sectionData->huffmanBits +
+                                     (sectionInfo[i].sectionBits - sideInfoTab[sectionInfo[i].sfbCnt]));
+      sectionData->sideInfoBits = (sectionData->sideInfoBits + sideInfoTab[sectionInfo[i].sfbCnt]);
+      sectionData->sectionInfo[sectionData->noOfSections] = sectionInfo[i];             
+      sectionData->noOfSections = sectionData->noOfSections + 1;
+    }
+  }
+}
+
+
+/*******************************************************************************
+*
+* functionname: scfCount
+* returns     : ---
+* description : count bits used by scalefactors.
+*
+********************************************************************************/
+static void scfCount(const Word16 *scalefacGain,
+                     const UWord16 *maxValueInSfb,
+                     SECTION_DATA * sectionData)
+
+{
+  SECTION_INFO *psectionInfo;

+  SECTION_INFO *psectionInfom;

+

+  /* counter */
+  Word32 i = 0; /* section counter */
+  Word32 j = 0; /* sfb counter */
+  Word32 k = 0; /* current section auxiliary counter */
+  Word32 m = 0; /* other section auxiliary counter */
+  Word32 n = 0; /* other sfb auxiliary counter */
+
+  /* further variables */
+  Word32 lastValScf     = 0;
+  Word32 deltaScf       = 0;
+  Flag found            = 0;
+  Word32 scfSkipCounter = 0;           
+         
+
+  sectionData->scalefacBits = 0;                                 
+
+   
+  if (scalefacGain == NULL) {
+    return;
+  }
+
+  lastValScf = 0;                                                
+  sectionData->firstScf = 0;        

+  
+  psectionInfo = sectionData->sectionInfo;
+  for (i=0; i<sectionData->noOfSections; i++) {
+     
+    if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO) {
+      sectionData->firstScf = psectionInfo->sfbStart;      
+      lastValScf = scalefacGain[sectionData->firstScf];                  
+      break;
+    }

+	psectionInfo += 1;
+  }

+
+  psectionInfo = sectionData->sectionInfo;
+  for (i=0; i<sectionData->noOfSections; i++, psectionInfo += 1) {
+       
+    if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO
+        && psectionInfo->codeBook != CODE_BOOK_PNS_NO) {
+      for (j = psectionInfo->sfbStart;
+           j < (psectionInfo->sfbStart + psectionInfo->sfbCnt); j++) {
+        /* check if we can repeat the last value to save bits */
+         
+        if (maxValueInSfb[j] == 0) {
+          found = 0;                                                     
+           
+          if (scfSkipCounter == 0) {
+            /* end of section */
+             
+            if (j - ((psectionInfo->sfbStart + psectionInfo->sfbCnt) - 1) == 0) {
+              found = 0;                                                 
+            }
+            else {
+              for (k = j + 1; k < psectionInfo->sfbStart + psectionInfo->sfbCnt; k++) {
+                 
+                if (maxValueInSfb[k] != 0) {
+                  int tmp = L_abs(scalefacGain[k] - lastValScf);
+				  found = 1;                                             
+                   
+                  if ( tmp < CODE_BOOK_SCF_LAV) {
+                    /* save bits */
+                    deltaScf = 0;                                        
+                  }
+                  else {
+                    /* do not save bits */
+                    deltaScf = lastValScf - scalefacGain[j];
+                    lastValScf = scalefacGain[j];                        
+                    scfSkipCounter = 0;                                  
+                  }
+                  break;
+                }
+                /* count scalefactor skip */
+                scfSkipCounter = scfSkipCounter + 1;
+              }
+            }
+			

+			psectionInfom = psectionInfo + 1;
+            /* search for the next maxValueInSfb[] != 0 in all other sections */
+            for (m = i + 1; (m < sectionData->noOfSections) && (found == 0); m++) {
+                 
+              if ((psectionInfom->codeBook != CODE_BOOK_ZERO_NO) &&
+                  (psectionInfom->codeBook != CODE_BOOK_PNS_NO)) {
+                for (n = psectionInfom->sfbStart;
+                     n < (psectionInfom->sfbStart + psectionInfom->sfbCnt); n++) {
+                   
+                  if (maxValueInSfb[n] != 0) {
+                    found = 1;                                           
+                     
+                    if ( (abs_s(scalefacGain[n] - lastValScf) < CODE_BOOK_SCF_LAV)) {
+                      deltaScf = 0;                                      
+                    }
+                    else {
+                      deltaScf = (lastValScf - scalefacGain[j]);
+                      lastValScf = scalefacGain[j];                      
+                      scfSkipCounter = 0;                                
+                    }
+                    break;
+                  }
+                  /* count scalefactor skip */
+                  scfSkipCounter = scfSkipCounter + 1;
+                }
+              }

+

+			  psectionInfom += 1;
+            }
+             
+            if (found == 0) {
+              deltaScf = 0;                                              
+              scfSkipCounter = 0;                                        
+            }
+          }
+          else {
+            deltaScf = 0;                                                
+            scfSkipCounter = scfSkipCounter - 1;
+          }

+        }
+        else {
+          deltaScf = lastValScf - scalefacGain[j];
+          lastValScf = scalefacGain[j];                                  
+        }
+        sectionData->scalefacBits += bitCountScalefactorDelta(deltaScf);
+      }
+    }
+  }
+}
+
+
+typedef Word16 (*lookUpTable)[CODE_BOOK_ESC_NDX + 1];
+
+
+Word16
+dynBitCount(const Word16  *quantSpectrum,
+            const UWord16 *maxValueInSfb,
+            const Word16  *scalefac,
+            const Word16   blockType,
+            const Word16   sfbCnt,
+            const Word16   maxSfbPerGroup,
+            const Word16   sfbPerGroup,
+            const Word16  *sfbOffset,
+            SECTION_DATA  *sectionData)
+{
+  sectionData->blockType      = blockType;                       
+  sectionData->sfbCnt         = sfbCnt;                          
+  sectionData->sfbPerGroup    = sfbPerGroup;           
+  if(sfbPerGroup)
+	sectionData->noOfGroups   = sfbCnt/sfbPerGroup; 
+  else
+	sectionData->noOfGroups   = 0x7fff;
+  sectionData->maxSfbPerGroup = maxSfbPerGroup;                  
+
+  noiselessCounter(sectionData,
+                   sectionData->mergeGainLookUp,
+                   (lookUpTable)sectionData->bitLookUp,
+                   quantSpectrum,
+                   maxValueInSfb,
+                   sfbOffset,
+                   blockType);
+
+  scfCount(scalefac,
+           maxValueInSfb,
+           sectionData);
+
+
+  return (sectionData->huffmanBits + sectionData->sideInfoBits + 

+	      sectionData->scalefacBits);
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/grp_data.c b/media/libstagefright/codecs/aacenc/src/grp_data.c
new file mode 100644
index 0000000..08d9a76
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/grp_data.c
@@ -0,0 +1,188 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		grp_data.c

+

+	Content:	Short block grouping function

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "psy_const.h"
+#include "interface.h"
+#include "grp_data.h"
+
+/*****************************************************************************
+*
+* function name: groupShortData
+* description:  group short data for next quantization and coding
+*
+**********************************************************************************/
+void
+groupShortData(Word32        *mdctSpectrum,
+               Word32        *tmpSpectrum,
+               SFB_THRESHOLD *sfbThreshold,
+               SFB_ENERGY    *sfbEnergy,
+               SFB_ENERGY    *sfbEnergyMS,
+               SFB_ENERGY    *sfbSpreadedEnergy,
+               const Word16   sfbCnt,
+               const Word16  *sfbOffset,
+               const Word16  *sfbMinSnr,
+               Word16        *groupedSfbOffset,
+               Word16        *maxSfbPerGroup,
+               Word16        *groupedSfbMinSnr,
+               const Word16   noOfGroups,
+               const Word16  *groupLen)
+{
+  Word32 i, j;
+  Word32 line;
+  Word32 sfb;
+  Word32 grp;
+  Word32 wnd;
+  Word32 offset;
+  Word32 highestSfb;
+
+  /* for short: regroup and  */
+  /* cumulate energies und thresholds group-wise . */
+  
+  /* calculate sfbCnt */
+  highestSfb = 0;                                        
+  for (wnd=0; wnd<TRANS_FAC; wnd++) {
+    for (sfb=sfbCnt - 1; sfb>=highestSfb; sfb--) {
+      for (line=(sfbOffset[sfb + 1] - 1); line>=sfbOffset[sfb]; line--) {
+        
+        if (mdctSpectrum[wnd*FRAME_LEN_SHORT+line] != 0) break; 
+      }
+      
+      if (line >= sfbOffset[sfb]) break;
+    }
+    highestSfb = max(highestSfb, sfb);
+  }
+  
+  if (highestSfb < 0) {
+    highestSfb = 0;                                      
+  }
+  *maxSfbPerGroup = highestSfb + 1;
+
+  /* calculate sfbOffset */
+  i = 0;                                                 
+  offset = 0;                                            
+  for (grp = 0; grp < noOfGroups; grp++) {
+    for (sfb = 0; sfb < sfbCnt; sfb++) {
+      groupedSfbOffset[i] = offset + sfbOffset[sfb] * groupLen[grp];
+      i += 1;
+    }
+    offset += groupLen[grp] * FRAME_LEN_SHORT;
+  }
+  groupedSfbOffset[i] = FRAME_LEN_LONG;                  
+  i += 1;
+
+  /* calculate minSnr */
+  i = 0;                                                 
+  offset = 0;                                            
+  for (grp = 0; grp < noOfGroups; grp++) {
+    for (sfb = 0; sfb < sfbCnt; sfb++) {
+      groupedSfbMinSnr[i] = sfbMinSnr[sfb];              
+      i += 1;
+    }
+    offset += groupLen[grp] * FRAME_LEN_SHORT;
+  }
+
+
+  /* sum up sfbThresholds */
+  wnd = 0;                                                       
+  i = 0;                                                         
+  for (grp = 0; grp < noOfGroups; grp++) {
+    for (sfb = 0; sfb < sfbCnt; sfb++) {
+      Word32 thresh = sfbThreshold->sfbShort[wnd][sfb];          
+      for (j=1; j<groupLen[grp]; j++) {
+        thresh = L_add(thresh, sfbThreshold->sfbShort[wnd+j][sfb]);
+      }
+      sfbThreshold->sfbLong[i] = thresh;                         
+      i += 1;
+    }
+    wnd += groupLen[grp];
+  }
+
+  /* sum up sfbEnergies left/right */
+  wnd = 0;                                                       
+  i = 0;                                                         
+  for (grp = 0; grp < noOfGroups; grp++) {
+    for (sfb = 0; sfb < sfbCnt; sfb++) {
+      Word32 energy = sfbEnergy->sfbShort[wnd][sfb];             
+      for (j=1; j<groupLen[grp]; j++) {
+        energy = L_add(energy, sfbEnergy->sfbShort[wnd+j][sfb]);
+      }
+      sfbEnergy->sfbLong[i] = energy;                            
+      i += 1;
+    }
+    wnd += groupLen[grp];
+  }
+
+  /* sum up sfbEnergies mid/side */
+  wnd = 0;                                                       
+  i = 0;                                                         
+  for (grp = 0; grp < noOfGroups; grp++) {
+    for (sfb = 0; sfb < sfbCnt; sfb++) {
+      Word32 energy = sfbEnergyMS->sfbShort[wnd][sfb];           
+      for (j=1; j<groupLen[grp]; j++) {
+        energy = L_add(energy, sfbEnergyMS->sfbShort[wnd+j][sfb]);
+      }
+      sfbEnergyMS->sfbLong[i] = energy;                          
+      i += 1;
+    }
+    wnd += groupLen[grp];
+  }
+
+  /* sum up sfbSpreadedEnergies */
+  wnd = 0;                                                       
+  i = 0;                                                         
+  for (grp = 0; grp < noOfGroups; grp++) {
+    for (sfb = 0; sfb < sfbCnt; sfb++) {
+      Word32 energy = sfbSpreadedEnergy->sfbShort[wnd][sfb];     
+      for (j=1; j<groupLen[grp]; j++) {
+        energy = L_add(energy, sfbSpreadedEnergy->sfbShort[wnd+j][sfb]);
+      }
+      sfbSpreadedEnergy->sfbLong[i] = energy;                    
+      i += 1;
+    }
+    wnd += groupLen[grp];
+  }
+
+  /* re-group spectrum */
+  wnd = 0;                                                       
+  i = 0;                                                         
+  for (grp = 0; grp < noOfGroups; grp++) {
+    for (sfb = 0; sfb < sfbCnt; sfb++) {
+      for (j = 0; j < groupLen[grp]; j++) {
+        Word16 lineOffset = FRAME_LEN_SHORT * (wnd + j);
+        for (line = lineOffset + sfbOffset[sfb]; line < lineOffset + sfbOffset[sfb+1]; line++) {
+          tmpSpectrum[i] = mdctSpectrum[line];                   
+          i = i + 1;
+        }
+      }
+    }
+    wnd += groupLen[grp];
+  }
+
+  for(i=0;i<FRAME_LEN_LONG;i+=4) {
+    mdctSpectrum[i] = tmpSpectrum[i];  

+	mdctSpectrum[i+1] = tmpSpectrum[i+1];  

+	mdctSpectrum[i+2] = tmpSpectrum[i+2];  

+	mdctSpectrum[i+3] = tmpSpectrum[i+3];  	
+  }
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/interface.c b/media/libstagefright/codecs/aacenc/src/interface.c
new file mode 100644
index 0000000..304b1d4
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/interface.c
@@ -0,0 +1,112 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		interface.c

+

+	Content:	Interface psychoaccoustic/quantizer functions

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "oper_32b.h"

+#include "psy_const.h"
+#include "interface.h"
+
+/*****************************************************************************
+*
+* function name: BuildInterface
+* description:  update output parameter
+*
+**********************************************************************************/
+void BuildInterface(Word32                  *groupedMdctSpectrum,
+                    const Word16             mdctScale,
+                    SFB_THRESHOLD           *groupedSfbThreshold,
+                    SFB_ENERGY              *groupedSfbEnergy,
+                    SFB_ENERGY              *groupedSfbSpreadedEnergy,
+                    const SFB_ENERGY_SUM     sfbEnergySumLR,
+                    const SFB_ENERGY_SUM     sfbEnergySumMS,
+                    const Word16             windowSequence,
+                    const Word16             windowShape,
+                    const Word16             groupedSfbCnt,
+                    const Word16            *groupedSfbOffset,
+                    const Word16             maxSfbPerGroup,
+                    const Word16            *groupedSfbMinSnr,
+                    const Word16             noOfGroups,
+                    const Word16            *groupLen,
+                    PSY_OUT_CHANNEL         *psyOutCh)
+{
+  Word32 j;
+  Word32 grp; 
+  Word32 mask;

+  Word16 *tmpV;
+
+  /*
+  copy values to psyOut
+  */
+  psyOutCh->maxSfbPerGroup    = maxSfbPerGroup;                             
+  psyOutCh->sfbCnt            = groupedSfbCnt;   
+  if(noOfGroups)
+	psyOutCh->sfbPerGroup     = groupedSfbCnt/ noOfGroups;
+  else
+	psyOutCh->sfbPerGroup     = 0x7fff;
+  psyOutCh->windowSequence    = windowSequence;                             
+  psyOutCh->windowShape       = windowShape;                                
+  psyOutCh->mdctScale         = mdctScale;                                  
+  psyOutCh->mdctSpectrum      = groupedMdctSpectrum;
+  psyOutCh->sfbEnergy         = groupedSfbEnergy->sfbLong;
+  psyOutCh->sfbThreshold      = groupedSfbThreshold->sfbLong;
+  psyOutCh->sfbSpreadedEnergy = groupedSfbSpreadedEnergy->sfbLong;
+  
+  tmpV = psyOutCh->sfbOffsets;

+  for(j=0; j<groupedSfbCnt + 1; j++) {
+      *tmpV++ = groupedSfbOffset[j];
+  }
+  

+  tmpV = psyOutCh->sfbMinSnr;
+  for(j=0;j<groupedSfbCnt; j++) {
+	  *tmpV++ =   groupedSfbMinSnr[j];
+  }
+  
+  /* generate grouping mask */
+  mask = 0;                                                                      
+  for (grp = 0; grp < noOfGroups; grp++) {
+    mask = mask << 1;
+    for (j=1; j<groupLen[grp]; j++) {
+      mask = mask << 1;
+      mask |= 1;                                                                 
+    }
+  }
+  psyOutCh->groupingMask = mask; 
+  
+  if (windowSequence != SHORT_WINDOW) {
+    psyOutCh->sfbEnSumLR =  sfbEnergySumLR.sfbLong;                              
+    psyOutCh->sfbEnSumMS =  sfbEnergySumMS.sfbLong;                              
+  }
+  else {
+    Word32 i;
+    Word32 accuSumMS=0;
+    Word32 accuSumLR=0;        

+	Word32 *pSumMS = sfbEnergySumMS.sfbShort;

+	Word32 *pSumLR = sfbEnergySumLR.sfbShort;
+
+    for (i=TRANS_FAC; i; i--) {
+      accuSumLR = L_add(accuSumLR, *pSumLR); pSumLR++;
+      accuSumMS = L_add(accuSumMS, *pSumMS); pSumMS++;
+    }
+    psyOutCh->sfbEnSumMS = accuSumMS;                                            
+    psyOutCh->sfbEnSumLR = accuSumLR;                                            
+  }
+}
diff --git a/media/libstagefright/codecs/aacenc/src/line_pe.c b/media/libstagefright/codecs/aacenc/src/line_pe.c
new file mode 100644
index 0000000..da57647
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/line_pe.c
@@ -0,0 +1,145 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		line_pe.c

+

+	Content:	Perceptual entropie module functions

+

+*******************************************************************************/

+
+#include "basic_op.h"

+#include "oper_32b.h"
+#include "typedef.h"
+#include "line_pe.h"
+
+
+static const Word16  C1_I = 12;    /* log(8.0)/log(2) *4         */
+static const Word32  C2_I = 10830; /* log(2.5)/log(2) * 1024 * 4 * 2 */
+static const Word16  C3_I = 573;   /* (1-C2/C1) *1024            */
+
+
+/*****************************************************************************
+*
+* function name: prepareSfbPe
+* description:  constants that do not change during successive pe calculations
+*
+**********************************************************************************/
+void prepareSfbPe(PE_DATA *peData,
+                  PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],
+                  Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+                  Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+                  const Word16 nChannels,
+                  const Word16 peOffset)
+{
+  Word32 sfbGrp, sfb;
+  Word32 ch;     
+
+  for(ch=0; ch<nChannels; ch++) {
+    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+    PE_CHANNEL_DATA *peChanData=&peData->peChannelData[ch];
+    for(sfbGrp=0;sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup){
+      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+	    peChanData->sfbNLines4[sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb];          
+        sfbNRelevantLines[ch][sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb] >> 2;    
+	    peChanData->sfbLdEnergy[sfbGrp+sfb] = logSfbEnergy[ch][sfbGrp+sfb];              
+      }
+    }
+  }
+  peData->offset = peOffset;                                                             
+}
+
+
+/*****************************************************************************
+*
+* function name: calcSfbPe
+* description:  constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr)
+*
+**********************************************************************************/
+void calcSfbPe(PE_DATA *peData,
+               PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+               const Word16 nChannels)
+{
+  Word32 ch;
+  Word32 sfbGrp, sfb;
+  Word32 nLines4;
+  Word32 ldThr, ldRatio;

+  Word32 pe, constPart, nActiveLines;
+
+  peData->pe = peData->offset;                                           
+  peData->constPart = 0;                                                 
+  peData->nActiveLines = 0;                                              
+  for(ch=0; ch<nChannels; ch++) {
+    PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+    PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
+    const Word32 *sfbEnergy = psyOutChan->sfbEnergy;
+    const Word32 *sfbThreshold = psyOutChan->sfbThreshold;
+
+    pe = 0;                                                  
+    constPart = 0;                                           
+    nActiveLines = 0;                                        
+
+    for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) {
+      for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+        Word32 nrg = sfbEnergy[sfbGrp+sfb];                             
+        Word32 thres = sfbThreshold[sfbGrp+sfb];                           
+        Word32 sfbLDEn = peChanData->sfbLdEnergy[sfbGrp+sfb];

+
+        if (nrg > thres) {
+          ldThr = iLog4(thres);
+
+          ldRatio = sfbLDEn - ldThr;
+
+          nLines4 = peChanData->sfbNLines4[sfbGrp+sfb];                    
+           
+          /* sfbPe = nl*log2(en/thr)*/
+		  if (ldRatio >= C1_I) {
+            peChanData->sfbPe[sfbGrp+sfb] = (nLines4*ldRatio + 8) >> 4;
+            peChanData->sfbConstPart[sfbGrp+sfb] = ((nLines4*sfbLDEn)) >> 4;
+          }
+          else {
+		  /* sfbPe = nl*(c2 + c3*log2(en/thr))*/
+            peChanData->sfbPe[sfbGrp+sfb] = extract_l((L_mpy_wx(

+                    (C2_I + C3_I * ldRatio * 2) << 4, nLines4) + 4) >> 3);

+            peChanData->sfbConstPart[sfbGrp+sfb] = extract_l(( L_mpy_wx(

+                    (C2_I + C3_I * sfbLDEn * 2) << 4, nLines4) + 4) >> 3);

+            nLines4 = (nLines4 * C3_I + (1024<<1)) >> 10;
+          }
+          peChanData->sfbNActiveLines[sfbGrp+sfb] = nLines4 >> 2;
+        }
+        else {
+          peChanData->sfbPe[sfbGrp+sfb] = 0;                             
+          peChanData->sfbConstPart[sfbGrp+sfb] = 0;                      
+          peChanData->sfbNActiveLines[sfbGrp+sfb] = 0;                   
+        }
+        pe = pe + peChanData->sfbPe[sfbGrp+sfb];
+        constPart = constPart + peChanData->sfbConstPart[sfbGrp+sfb];
+        nActiveLines = nActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb];
+      }
+    }
+	

+	peChanData->pe = saturate(pe);                                                  

+    peChanData->constPart = saturate(constPart);                                           

+    peChanData->nActiveLines = saturate(nActiveLines);                                        

+
+    
+	pe += peData->pe;
+	peData->pe = saturate(pe); 
+    constPart += peData->constPart;
+	peData->constPart = saturate(constPart); 
+    nActiveLines += peData->nActiveLines;
+	peData->nActiveLines = saturate(nActiveLines);
+  } 
+}
diff --git a/media/libstagefright/codecs/aacenc/src/memalign.c b/media/libstagefright/codecs/aacenc/src/memalign.c
new file mode 100644
index 0000000..7d20352
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/memalign.c
@@ -0,0 +1,107 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** 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.
+ */
+
+/*******************************************************************************
+	File:		mem_align.c
+
+	Content:	Memory alloc alignments functions
+
+*******************************************************************************/
+
+
+#include	"memalign.h"
+
+/*****************************************************************************
+*
+* function name: mem_malloc
+* description:  malloc the alignments memory 
+* returns:      the point of the memory
+*
+**********************************************************************************/
+void *
+mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID)
+{
+	int ret;
+	unsigned char *mem_ptr;
+	VO_MEM_INFO MemInfo;
+
+	if (!alignment) {
+
+		MemInfo.Flag = 0;
+		MemInfo.Size = size + 1;
+		ret = pMemop->Alloc(CodecID, &MemInfo);
+		if(ret != 0)
+			return 0;
+		mem_ptr = (unsigned char *)MemInfo.VBuffer;
+
+		pMemop->Set(CodecID, mem_ptr, 0, size + 1);
+
+		*mem_ptr = (unsigned char)1;
+
+		return ((void *)(mem_ptr+1));
+	} else {
+		unsigned char *tmp;
+
+		MemInfo.Flag = 0;
+		MemInfo.Size = size + alignment;
+		ret = pMemop->Alloc(CodecID, &MemInfo);
+		if(ret != 0)
+			return 0;
+
+		tmp = (unsigned char *)MemInfo.VBuffer;
+
+		pMemop->Set(CodecID, tmp, 0, size + alignment);
+
+		mem_ptr =
+			(unsigned char *) ((unsigned int) (tmp + alignment - 1) &
+					(~((unsigned int) (alignment - 1))));
+
+		if (mem_ptr == tmp)
+			mem_ptr += alignment;
+
+		*(mem_ptr - 1) = (unsigned char) (mem_ptr - tmp);
+
+		return ((void *)mem_ptr);
+	}
+
+	return(0);
+}
+
+
+/*****************************************************************************
+*
+* function name: mem_free
+* description:  free the memory
+*
+*******************************************************************************/
+void
+mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID)
+{
+
+	unsigned char *ptr;
+
+	if (mem_ptr == 0)
+		return;
+
+	ptr = mem_ptr;
+
+	ptr -= *(ptr - 1);
+
+	pMemop->Free(CodecID, ptr);
+}
+
+
+
diff --git a/media/libstagefright/codecs/aacenc/src/ms_stereo.c b/media/libstagefright/codecs/aacenc/src/ms_stereo.c
new file mode 100644
index 0000000..c83d07b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/ms_stereo.c
@@ -0,0 +1,139 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		ms_stereo.c

+

+	Content:	MS stereo processing function

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "oper_32b.h"
+#include "psy_const.h"
+#include "ms_stereo.h"
+
+
+/********************************************************************************
+*
+* function name: MsStereoProcessing
+* description:  detect use ms stereo or not
+*				if ((min(thrLn, thrRn)*min(thrLn, thrRn))/(enMn*enSn)) 
+*				>= ((thrLn *thrRn)/(enLn*enRn)) then ms stereo
+*
+**********************************************************************************/
+void MsStereoProcessing(Word32       *sfbEnergyLeft,
+                        Word32       *sfbEnergyRight,
+                        const Word32 *sfbEnergyMid,
+                        const Word32 *sfbEnergySide,
+                        Word32       *mdctSpectrumLeft,
+                        Word32       *mdctSpectrumRight,
+                        Word32       *sfbThresholdLeft,
+                        Word32       *sfbThresholdRight,
+                        Word32       *sfbSpreadedEnLeft,
+                        Word32       *sfbSpreadedEnRight,
+                        Word16       *msDigest,
+                        Word16       *msMask,
+                        const Word16  sfbCnt,
+                        const Word16  sfbPerGroup,
+                        const Word16  maxSfbPerGroup,
+                        const Word16 *sfbOffset) {
+  Word32 temp;
+  Word32 sfb,sfboffs, j; 
+  Word32 msMaskTrueSomewhere = 0;
+  Word32 msMaskFalseSomewhere = 0;
+
+  for (sfb=0; sfb<sfbCnt; sfb+=sfbPerGroup) {
+    for (sfboffs=0;sfboffs<maxSfbPerGroup;sfboffs++) {
+
+      Word32 temp;
+      Word32 pnlr,pnms;
+      Word32 minThreshold;
+      Word32 thrL, thrR, nrgL, nrgR;
+      Word32 idx, shift;
+
+      idx = sfb + sfboffs;                                                                       
+
+      thrL = sfbThresholdLeft[idx];                                                                 
+      thrR = sfbThresholdRight[idx];                                                                
+      nrgL = sfbEnergyLeft[idx];                                                                    
+      nrgR = sfbEnergyRight[idx];                                                                   
+
+      minThreshold = min(thrL, thrR);
+
+      nrgL = max(nrgL,thrL) + 1;
+      shift = norm_l(nrgL);

+	  nrgL = Div_32(thrL << shift, nrgL << shift);
+      nrgR = max(nrgR,thrR) + 1;
+      shift = norm_l(nrgR);

+	  nrgR = Div_32(thrR << shift, nrgR << shift);
+
+	  pnlr = fixmul(nrgL, nrgR);
+
+      nrgL = sfbEnergyMid[idx];                                                                     
+      nrgR = sfbEnergySide[idx];                                                                    
+
+      nrgL = max(nrgL,minThreshold) + 1;
+      shift = norm_l(nrgL);

+	  nrgL = Div_32(minThreshold << shift, nrgL << shift);
+
+      nrgR = max(nrgR,minThreshold) + 1;
+      shift = norm_l(nrgR);

+	  nrgR = Div_32(minThreshold << shift, nrgR << shift);
+
+      pnms = fixmul(nrgL, nrgR);
+
+      temp = (pnlr + 1) / ((pnms >> 8) + 1);
+
+      temp = pnms - pnlr;                                                                     
+      if( temp > 0 ){
+
+        msMask[idx] = 1;                                                                            
+        msMaskTrueSomewhere = 1;                                                                    
+
+        for (j=sfbOffset[idx]; j<sfbOffset[idx+1]; j++) {
+          Word32 left, right;
+          left  = (mdctSpectrumLeft[j] >>  1);
+          right = (mdctSpectrumRight[j] >> 1);
+          mdctSpectrumLeft[j] =  left + right;                                               
+          mdctSpectrumRight[j] =  left - right;                                              
+        }
+        
+        sfbThresholdLeft[idx] = minThreshold;                                                       
+        sfbThresholdRight[idx] = minThreshold;                                                      
+        sfbEnergyLeft[idx] = sfbEnergyMid[idx];                                                     
+        sfbEnergyRight[idx] = sfbEnergySide[idx];                                                   
+
+        sfbSpreadedEnRight[idx] = min(sfbSpreadedEnLeft[idx],sfbSpreadedEnRight[idx]) >> 1;  
+        sfbSpreadedEnLeft[idx] = sfbSpreadedEnRight[idx];                                           
+        
+      }
+      else {
+        msMask[idx]  = 0;                                                                           
+        msMaskFalseSomewhere = 1;                                                                   
+      }
+    }                                                                                               
+    if ( msMaskTrueSomewhere ) {                                                                    
+      if(msMaskFalseSomewhere ) {
+        *msDigest = SI_MS_MASK_SOME;                                                                
+      } else {
+        *msDigest = SI_MS_MASK_ALL;                                                                 
+      }
+    } else {
+      *msDigest = SI_MS_MASK_NONE;                                                                  
+    }
+  }
+
+}
diff --git a/media/libstagefright/codecs/aacenc/src/pre_echo_control.c b/media/libstagefright/codecs/aacenc/src/pre_echo_control.c
new file mode 100644
index 0000000..f59216e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/pre_echo_control.c
@@ -0,0 +1,113 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		pre_echo_control.c

+

+	Content:	Pre echo control functions

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "oper_32b.h"

+
+#include "oper_32b.h"
+#include "pre_echo_control.h"
+
+
+/*****************************************************************************
+*
+* function name:InitPreEchoControl 
+* description: init pre echo control parameter
+*
+*****************************************************************************/
+void InitPreEchoControl(Word32 *pbThresholdNm1,
+                        Word16  numPb,
+                        Word32 *pbThresholdQuiet)
+{
+  Word16 pb;
+
+  for(pb=0; pb<numPb; pb++) {
+    pbThresholdNm1[pb] = pbThresholdQuiet[pb];                                   
+  }
+}
+
+/*****************************************************************************
+*
+* function name:PreEchoControl 
+* description: update shreshold to avoid pre echo
+*			   thr(n) = max(rpmin*thrq(n), min(thrq(n), rpelev*thrq1(n)))
+*
+*
+*****************************************************************************/
+void PreEchoControl(Word32 *pbThresholdNm1,
+                    Word16  numPb,
+                    Word32  maxAllowedIncreaseFactor,
+                    Word16  minRemainingThresholdFactor,
+                    Word32 *pbThreshold,
+                    Word16  mdctScale,
+                    Word16  mdctScalenm1)
+{
+  Word32 i;
+  Word32 tmpThreshold1, tmpThreshold2;
+  Word32 scaling;
+
+  /* maxAllowedIncreaseFactor is hard coded to 2 */
+  (void)maxAllowedIncreaseFactor;
+
+  scaling = ((mdctScale - mdctScalenm1) << 1);
+   
+  if ( scaling > 0 ) {
+    for(i = 0; i < numPb; i++) {
+      tmpThreshold1 = pbThresholdNm1[i] >> (scaling-1);
+      tmpThreshold2 = L_mpy_ls(pbThreshold[i], minRemainingThresholdFactor);
+
+      /* copy thresholds to internal memory */
+      pbThresholdNm1[i] = pbThreshold[i];                                        
+
+       
+      if(pbThreshold[i] > tmpThreshold1) {
+        pbThreshold[i] = tmpThreshold1;                                          
+      }
+       
+      if(tmpThreshold2 > pbThreshold[i]) {
+        pbThreshold[i] = tmpThreshold2;                                          
+      }
+
+    }
+  }
+  else {
+    scaling = -scaling;
+    for(i = 0; i < numPb; i++) {
+
+      tmpThreshold1 = pbThresholdNm1[i] << 1;
+      tmpThreshold2 = L_mpy_ls(pbThreshold[i], minRemainingThresholdFactor);
+
+      /* copy thresholds to internal memory */
+      pbThresholdNm1[i] = pbThreshold[i];                                        
+
+       
+      if(((pbThreshold[i] >> scaling) > tmpThreshold1)) {
+        pbThreshold[i] = tmpThreshold1 << scaling;
+      }
+       
+      if(tmpThreshold2 > pbThreshold[i]) {
+        pbThreshold[i] = tmpThreshold2;                                          
+      }
+
+    }
+  }
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/psy_configuration.c b/media/libstagefright/codecs/aacenc/src/psy_configuration.c
new file mode 100644
index 0000000..586e00f
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/psy_configuration.c
@@ -0,0 +1,505 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		psy_configuration.c

+

+	Content:	Psychoaccoustic configuration functions

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "oper_32b.h"
+#include "psy_configuration.h"
+#include "adj_thr.h"
+#include "aac_rom.h"
+
+
+
+#define BARC_SCALE	100 /* integer barc values are scaled with 100 */
+#define LOG2_1000	301 /* log2*1000 */

+#define PI2_1000	1571 /* pi/2*1000*/

+#define ATAN_COEF1	3560 /* 1000/0.280872f*/

+#define ATAN_COEF2	281 /* 1000*0.280872f*/

+
+
+typedef struct{
+  Word32 sampleRate;
+  const UWord8 *paramLong;
+  const UWord8 *paramShort;
+}SFB_INFO_TAB;
+
+static const Word16 ABS_LEV = 20;
+static const Word16 BARC_THR_QUIET[] = {15, 10,  7,  2,  0,  0,  0,  0,  0,  0,
+                                         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                                         3,  5, 10, 20, 30};
+
+
+
+static const Word16 max_bark = 24; /* maximum bark-value */
+static const Word16 maskLow  = 30; /* in 1dB/bark */
+static const Word16 maskHigh = 15; /* in 1*dB/bark */
+static const Word16 c_ratio  = 0x0029; /* pow(10.0f, -(29.0f/10.0f)) */
+
+static const Word16 maskLowSprEnLong = 30;       /* in 1dB/bark */
+static const Word16 maskHighSprEnLong = 20;      /* in 1dB/bark */
+static const Word16 maskHighSprEnLongLowBr = 15; /* in 1dB/bark */
+static const Word16 maskLowSprEnShort = 20;      /* in 1dB/bark */
+static const Word16 maskHighSprEnShort = 15;     /* in 1dB/bark */

+static const Word16 c_minRemainingThresholdFactor = 0x0148;    /* 0.01 *(1 << 15)*/

+static const Word32 c_maxsnr = 0x66666666;		 /* upper limit is -1 dB */

+static const Word32 c_minsnr = 0x00624dd3;		 /* lower limit is -25 dB */

+

+static const Word32 c_maxClipEnergyLong = 0x77359400;  /* 2.0e9f*/

+static const Word32 c_maxClipEnergyShort = 0x01dcd650; /* 2.0e9f/(AACENC_TRANS_FAC*AACENC_TRANS_FAC)*/

+

+

+Word32 GetSRIndex(Word32 sampleRate)

+{

+    if (92017 <= sampleRate) return 0;

+    if (75132 <= sampleRate) return 1;

+    if (55426 <= sampleRate) return 2;

+    if (46009 <= sampleRate) return 3;

+    if (37566 <= sampleRate) return 4;

+    if (27713 <= sampleRate) return 5;

+    if (23004 <= sampleRate) return 6;

+    if (18783 <= sampleRate) return 7;

+    if (13856 <= sampleRate) return 8;

+    if (11502 <= sampleRate) return 9;

+    if (9391 <= sampleRate) return 10;

+

+    return 11;

+}
+
+
+/*********************************************************************************
+*
+* function name: atan_1000
+* description:  calculates 1000*atan(x/1000)
+*               based on atan approx for x > 0				
+*				atan(x) = x/((float)1.0f+(float)0.280872f*x*x)  if x < 1

+*						= pi/2 - x/((float)0.280872f +x*x)	    if x >= 1

+* return:       1000*atan(x/1000)
+*
+**********************************************************************************/
+static Word16 atan_1000(Word32 val) 
+{
+  Word32 y;
+
+   
+  if(L_sub(val, 1000) < 0) {
+    y = extract_l(((1000 * val) / (1000 + ((val * val) / ATAN_COEF1))));
+  }
+  else {
+    y = PI2_1000 - ((1000 * val) / (ATAN_COEF2 + ((val * val) / 1000)));
+  }
+
+  return extract_l(y);
+}
+
+
+/*****************************************************************************
+*
+* function name: BarcLineValue
+* description:  Calculates barc value for one frequency line
+* returns:      barc value of line * BARC_SCALE
+* input:        number of lines in transform, index of line to check, Fs
+* output:
+*
+*****************************************************************************/
+static Word16 BarcLineValue(Word16 noOfLines, Word16 fftLine, Word32 samplingFreq)
+{
+  Word32 center_freq, temp, bvalFFTLine;
+
+  /* center frequency of fft line */
+  center_freq = (fftLine * samplingFreq) / (noOfLines << 1);
+  temp =  atan_1000((center_freq << 2) / (3*10));
+  bvalFFTLine = 
+    (26600 * atan_1000((center_freq*76) / 100) + 7*temp*temp) / (2*1000*1000 / BARC_SCALE);
+  
+  return saturate(bvalFFTLine);
+}
+
+/*****************************************************************************
+*
+* function name: initThrQuiet
+* description:  init thredhold in quiet
+*
+*****************************************************************************/
+static void initThrQuiet(Word16  numPb,
+                         Word16 *pbOffset,
+                         Word16 *pbBarcVal,
+                         Word32 *pbThresholdQuiet) {
+  Word16 i;
+  Word16 barcThrQuiet;
+
+  for(i=0; i<numPb; i++) {
+    Word16 bv1, bv2;
+
+     
+    if (i>0)
+      bv1 = (pbBarcVal[i] + pbBarcVal[i-1]) >> 1;
+    else
+      bv1 = pbBarcVal[i] >> 1;
+
+     
+    if (i < (numPb - 1))
+      bv2 = (pbBarcVal[i] + pbBarcVal[i+1]) >> 1;
+    else {
+      bv2 = pbBarcVal[i];                                        
+    }
+
+    bv1 = min((bv1 / BARC_SCALE), max_bark);
+    bv2 = min((bv2 / BARC_SCALE), max_bark);
+
+    barcThrQuiet = min(BARC_THR_QUIET[bv1], BARC_THR_QUIET[bv2]);
+
+    
+    /*
+      we calculate 
+      pow(10.0f,(float)(barcThrQuiet - ABS_LEV)*0.1)*(float)ABS_LOW*(pbOffset[i+1] - pbOffset[i]);
+    */
+
+    pbThresholdQuiet[i] = pow2_xy((((barcThrQuiet - ABS_LEV) * 100) +
+                          LOG2_1000*(14+2*LOG_NORM_PCM)), LOG2_1000) * (pbOffset[i+1] - pbOffset[i]);
+  }
+}
+
+
+/*****************************************************************************
+*
+* function name: initSpreading
+* description:  init energy spreading parameter
+*
+*****************************************************************************/
+static void initSpreading(Word16  numPb,
+                          Word16 *pbBarcValue,
+                          Word16 *pbMaskLoFactor,
+                          Word16 *pbMaskHiFactor,
+                          Word16 *pbMaskLoFactorSprEn,
+                          Word16 *pbMaskHiFactorSprEn,
+                          const Word32 bitrate,
+                          const Word16 blockType)
+{
+  Word16 i;
+  Word16 maskLowSprEn, maskHighSprEn;
+
+   
+  if (sub(blockType, SHORT_WINDOW) != 0) {
+    maskLowSprEn = maskLowSprEnLong;                                     
+       
+    if (bitrate > 22000)
+      maskHighSprEn = maskHighSprEnLong;
+    else
+      maskHighSprEn = maskHighSprEnLongLowBr;
+  }
+  else {
+    maskLowSprEn = maskLowSprEnShort;            
+    maskHighSprEn = maskHighSprEnShort;          
+  }
+
+  for(i=0; i<numPb; i++) {
+     
+    if (i > 0) {
+      Word32 dbVal;
+      Word16 dbark = pbBarcValue[i] - pbBarcValue[i-1];
+
+      /*
+        we calulate pow(10.0f, -0.1*dbVal/BARC_SCALE) 
+      */
+      dbVal = (maskHigh * dbark);
+      pbMaskHiFactor[i] = round16(pow2_xy(L_negate(dbVal), (Word32)LOG2_1000));             /* 0.301 log10(2) */
+       
+      dbVal = (maskLow * dbark);
+      pbMaskLoFactor[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000)); 
+       
+      
+      dbVal = (maskHighSprEn * dbark);
+      pbMaskHiFactorSprEn[i] =  round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000)); 
+      dbVal = (maskLowSprEn * dbark);
+      pbMaskLoFactorSprEn[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000));
+    }
+    else {
+      pbMaskHiFactor[i] = 0;                     
+      pbMaskLoFactor[numPb-1] = 0;               
+
+      pbMaskHiFactorSprEn[i] = 0;                
+      pbMaskLoFactorSprEn[numPb-1] = 0;          
+    }
+  }
+
+}
+
+
+/*****************************************************************************
+*
+* function name: initBarcValues
+* description:  init bark value
+*
+*****************************************************************************/
+static void initBarcValues(Word16  numPb,
+                           Word16 *pbOffset,
+                           Word16  numLines,
+                           Word32  samplingFrequency,
+                           Word16 *pbBval)
+{
+  Word16 i;
+  Word16 pbBval0, pbBval1;
+
+  pbBval0 = 0;                                       
+
+  for(i=0; i<numPb; i++){
+    pbBval1 = BarcLineValue(numLines, pbOffset[i+1], samplingFrequency);
+    pbBval[i] = (pbBval0 + pbBval1) >> 1;
+    pbBval0 = pbBval1;                              
+  }
+}
+
+
+/*****************************************************************************
+*
+* function name: initMinSnr
+* description:  calculate min snr parameter
+*				minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5)

+*
+*****************************************************************************/
+static void initMinSnr(const Word32  bitrate,
+                       const Word32  samplerate,
+                       const Word16  numLines,
+                       const Word16 *sfbOffset,
+                       const Word16 *pbBarcVal,
+                       const Word16  sfbActive,
+                       Word16       *sfbMinSnr)
+{
+  Word16 sfb;
+  Word16 barcWidth;
+  Word16 pePerWindow;
+  Word32 pePart;
+  Word32 snr;
+  Word16 pbVal0, pbVal1, shift;
+
+  /* relative number of active barks */
+
+
+  pePerWindow = bits2pe(extract_l((bitrate * numLines) / samplerate));
+
+  pbVal0 = 0;                                                    
+
+  for (sfb=0; sfb<sfbActive; sfb++) {
+
+    pbVal1 = (pbBarcVal[sfb] << 1) - pbVal0;
+    barcWidth = pbVal1 - pbVal0;
+    pbVal0 = pbVal1;                                             
+
+    /* allow at least 2.4% of pe for each active barc */

+	pePart = ((pePerWindow * 24) * (max_bark * barcWidth)) /
+        (pbBarcVal[sfbActive-1] * (sfbOffset[sfb+1] - sfbOffset[sfb]));
+   
+      
+    pePart = min(pePart, 8400); 
+    pePart = max(pePart, 1400);
+
+    /* minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5)*/

+	/* we add an offset of 2^16 to the pow functions */
+	/* 0xc000 = 1.5*(1 << 15)*/

+      
+    snr = pow2_xy((pePart - 16*1000),1000) - 0x0000c000;
+      
+    if(snr > 0x00008000)

+	{

+		shift = norm_l(snr);

+		snr = Div_32(0x00008000 << shift, snr << shift);  
+	}
+	else
+	{
+		snr = 0x7fffffff;
+	}
+      
+    /* upper limit is -1 dB */
+    snr = min(snr, c_maxsnr);
+    /* lower limit is -25 dB */
+    snr = max(snr, c_minsnr);
+    sfbMinSnr[sfb] = round16(snr);
+  }
+
+}
+
+/*****************************************************************************
+*
+* function name: InitPsyConfigurationLong
+* description:  init long block psychoacoustic configuration
+*
+*****************************************************************************/
+Word16 InitPsyConfigurationLong(Word32 bitrate,
+                                Word32 samplerate,
+                                Word16 bandwidth,
+                                PSY_CONFIGURATION_LONG *psyConf)
+{
+  Word32 samplerateindex;

+  Word16 sfbBarcVal[MAX_SFB_LONG];

+  Word16 sfb;
+
+  /*
+    init sfb table
+  */

+  samplerateindex = GetSRIndex(samplerate);  

+  psyConf->sfbCnt = sfBandTotalLong[samplerateindex];

+  psyConf->sfbOffset = sfBandTabLong + sfBandTabLongOffset[samplerateindex];

+  psyConf->sampRateIdx = samplerateindex;
+
+  /*
+    calculate barc values for each pb
+  */
+  initBarcValues(psyConf->sfbCnt,
+                 psyConf->sfbOffset,
+                 psyConf->sfbOffset[psyConf->sfbCnt],
+                 samplerate,
+                 sfbBarcVal);
+
+  /*
+    init thresholds in quiet
+  */
+  initThrQuiet(psyConf->sfbCnt,
+               psyConf->sfbOffset,
+               sfbBarcVal,
+               psyConf->sfbThresholdQuiet);
+
+  /*
+    calculate spreading function
+  */
+  initSpreading(psyConf->sfbCnt,
+                sfbBarcVal,
+                psyConf->sfbMaskLowFactor,
+                psyConf->sfbMaskHighFactor,
+                psyConf->sfbMaskLowFactorSprEn,
+                psyConf->sfbMaskHighFactorSprEn,
+                bitrate,
+                LONG_WINDOW);
+
+  /*
+    init ratio
+  */
+  psyConf->ratio = c_ratio;      
+
+  psyConf->maxAllowedIncreaseFactor = 2;              
+  psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor;    /* 0.01 *(1 << 15)*/  
+
+  psyConf->clipEnergy = c_maxClipEnergyLong;                   
+  psyConf->lowpassLine = extract_l((bandwidth<<1) * FRAME_LEN_LONG / samplerate);
+
+  for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
+    if (sub(psyConf->sfbOffset[sfb], psyConf->lowpassLine) >= 0)
+      break;
+  }
+  psyConf->sfbActive = sfb;                 
+
+  /*
+    calculate minSnr
+  */
+  initMinSnr(bitrate,
+             samplerate,
+             psyConf->sfbOffset[psyConf->sfbCnt],
+             psyConf->sfbOffset,
+             sfbBarcVal,
+             psyConf->sfbActive,
+             psyConf->sfbMinSnr);
+
+
+  return(0);
+}
+
+/*****************************************************************************
+*
+* function name: InitPsyConfigurationShort
+* description:  init short block psychoacoustic configuration
+*
+*****************************************************************************/
+Word16 InitPsyConfigurationShort(Word32 bitrate,
+                                 Word32 samplerate,
+                                 Word16 bandwidth,
+                                 PSY_CONFIGURATION_SHORT *psyConf) 

+{
+  Word32 samplerateindex;
+  Word16 sfbBarcVal[MAX_SFB_SHORT];
+  Word16 sfb;
+  /*
+    init sfb table
+  */
+  samplerateindex = GetSRIndex(samplerate);  

+  psyConf->sfbCnt = sfBandTotalShort[samplerateindex];

+  psyConf->sfbOffset = sfBandTabShort + sfBandTabShortOffset[samplerateindex];
+  psyConf->sampRateIdx = samplerateindex;
+  /*
+    calculate barc values for each pb
+  */
+  initBarcValues(psyConf->sfbCnt,
+                 psyConf->sfbOffset,
+                 psyConf->sfbOffset[psyConf->sfbCnt],
+                 samplerate,
+                 sfbBarcVal);
+
+  /*
+    init thresholds in quiet
+  */
+  initThrQuiet(psyConf->sfbCnt,
+               psyConf->sfbOffset,
+               sfbBarcVal,
+               psyConf->sfbThresholdQuiet);
+
+  /*
+    calculate spreading function
+  */
+  initSpreading(psyConf->sfbCnt,
+                sfbBarcVal,
+                psyConf->sfbMaskLowFactor,
+                psyConf->sfbMaskHighFactor,
+                psyConf->sfbMaskLowFactorSprEn,
+                psyConf->sfbMaskHighFactorSprEn,
+                bitrate,
+                SHORT_WINDOW);
+
+  /*
+    init ratio
+  */
+  psyConf->ratio = c_ratio;                                                      
+
+  psyConf->maxAllowedIncreaseFactor = 2;                                         
+  psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor;                            	 
+
+  psyConf->clipEnergy = c_maxClipEnergyShort;                                    
+
+  psyConf->lowpassLine = extract_l(((bandwidth << 1) * FRAME_LEN_SHORT) / samplerate);
+ 
+  for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
+     
+    if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine)
+      break;
+  }
+  psyConf->sfbActive = sfb;                                                      
+
+  /*
+    calculate minSnr
+  */
+  initMinSnr(bitrate,
+             samplerate,
+             psyConf->sfbOffset[psyConf->sfbCnt],
+             psyConf->sfbOffset,
+             sfbBarcVal,
+             psyConf->sfbActive,
+             psyConf->sfbMinSnr);
+
+  return(0);
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/psy_main.c b/media/libstagefright/codecs/aacenc/src/psy_main.c
new file mode 100644
index 0000000..8746a72
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/psy_main.c
@@ -0,0 +1,810 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		psy_main.c

+

+	Content:	Psychoacoustic major functions

+

+*******************************************************************************/
+
+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"
+#include "psy_const.h"
+#include "block_switch.h"
+#include "transform.h"
+#include "spreading.h"
+#include "pre_echo_control.h"
+#include "band_nrg.h"
+#include "psy_configuration.h"
+#include "psy_data.h"
+#include "ms_stereo.h"
+#include "interface.h"
+#include "psy_main.h"
+#include "grp_data.h"
+#include "tns_func.h"
+#include "memalign.h"
+
+/*                                    long       start       short       stop */
+static Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW};
+
+/*
+  forward definitions
+*/
+static Word16 advancePsychLong(PSY_DATA* psyData,
+                               TNS_DATA* tnsData,
+                               PSY_CONFIGURATION_LONG *hPsyConfLong,
+                               PSY_OUT_CHANNEL* psyOutChannel,
+                               Word32 *pScratchTns,
+                               const TNS_DATA *tnsData2,
+                               const Word16 ch);
+
+static Word16 advancePsychLongMS (PSY_DATA  psyData[MAX_CHANNELS],
+                                  const PSY_CONFIGURATION_LONG *hPsyConfLong);
+
+static Word16 advancePsychShort(PSY_DATA* psyData,
+                                TNS_DATA* tnsData,
+                                const PSY_CONFIGURATION_SHORT *hPsyConfShort,
+                                PSY_OUT_CHANNEL* psyOutChannel,
+                                Word32 *pScratchTns,
+                                const TNS_DATA *tnsData2,
+                                const Word16 ch);
+
+static Word16 advancePsychShortMS (PSY_DATA  psyData[MAX_CHANNELS],
+                                   const PSY_CONFIGURATION_SHORT *hPsyConfShort);
+
+
+/*****************************************************************************
+*
+* function name: PsyNew
+* description:  allocates memory for psychoacoustic
+* returns:      an error code
+* input:        pointer to a psych handle
+*
+*****************************************************************************/
+Word16 PsyNew(PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP)
+{
+  Word16 i;

+  Word32 *mdctSpectrum;

+  Word32 *scratchTNS;

+  Word16 *mdctDelayBuffer;

+  

+  mdctSpectrum = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);

+  if(NULL == mdctSpectrum)

+	  return 1;

+

+  scratchTNS = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);

+  if(NULL == scratchTNS)

+  {

+	  return 1;

+  }

+

+  mdctDelayBuffer = (Word16 *)mem_malloc(pMemOP, nChan * BLOCK_SWITCHING_OFFSET * sizeof(Word16), 32, VO_INDEX_ENC_AAC);

+  if(NULL == mdctDelayBuffer)

+  {

+	  return 1;
+  }

+

+  for (i=0; i<nChan; i++){
+    hPsy->psyData[i].mdctDelayBuffer = mdctDelayBuffer + i*BLOCK_SWITCHING_OFFSET;      
+    hPsy->psyData[i].mdctSpectrum = mdctSpectrum + i*FRAME_LEN_LONG;
+  }
+
+  hPsy->pScratchTns = scratchTNS;
+
+  return 0;
+}
+
+
+/*****************************************************************************
+*
+* function name: PsyDelete
+* description:  allocates memory for psychoacoustic
+* returns:      an error code
+*
+*****************************************************************************/
+Word16 PsyDelete(PSY_KERNEL  *hPsy, VO_MEM_OPERATOR *pMemOP)
+{
+  Word32 nch;

+

+  if(hPsy)

+  {

+	if(hPsy->psyData[0].mdctDelayBuffer)

+		mem_free(pMemOP, hPsy->psyData[0].mdctDelayBuffer, VO_INDEX_ENC_AAC);

+      

+    if(hPsy->psyData[0].mdctSpectrum)

+		mem_free(pMemOP, hPsy->psyData[0].mdctSpectrum, VO_INDEX_ENC_AAC);

+

+    for (nch=0; nch<MAX_CHANNELS; nch++){

+	  hPsy->psyData[nch].mdctDelayBuffer = NULL;      

+	  hPsy->psyData[nch].mdctSpectrum = NULL;

+	}

+

+	if(hPsy->pScratchTns)

+	{

+		mem_free(pMemOP, hPsy->pScratchTns, VO_INDEX_ENC_AAC);

+		hPsy->pScratchTns = NULL;

+	}

+  }

+
+  return 0;
+}
+
+
+/*****************************************************************************
+*
+* function name: PsyOutNew
+* description:  allocates memory for psyOut struc
+* returns:      an error code
+* input:        pointer to a psych handle
+*
+*****************************************************************************/
+Word16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
+{
+  pMemOP->Set(VO_INDEX_ENC_AAC, hPsyOut, 0, sizeof(PSY_OUT));
+  /*
+    alloc some more stuff, tbd
+  */
+  return 0;
+}
+
+/*****************************************************************************
+*
+* function name: PsyOutDelete
+* description:  allocates memory for psychoacoustic
+* returns:      an error code
+*
+*****************************************************************************/
+Word16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
+{
+  hPsyOut=NULL;
+  return 0;
+}
+
+
+/*****************************************************************************
+*
+* function name: psyMainInit
+* description:  initializes psychoacoustic
+* returns:      an error code
+*
+*****************************************************************************/
+
+Word16 psyMainInit(PSY_KERNEL *hPsy,
+                   Word32 sampleRate,
+                   Word32 bitRate,
+                   Word16 channels,
+                   Word16 tnsMask,
+                   Word16 bandwidth)
+{
+  Word16 ch, err;
+  Word32 channelBitRate = bitRate/channels;
+
+  err = InitPsyConfigurationLong(channelBitRate,
+                                 sampleRate,
+                                 bandwidth,
+                                 &(hPsy->psyConfLong));

+

+  if (!err) {
+      hPsy->sampleRateIdx = hPsy->psyConfLong.sampRateIdx;

+	  err = InitTnsConfigurationLong(bitRate, sampleRate, channels,
+                                   &hPsy->psyConfLong.tnsConf, &hPsy->psyConfLong, tnsMask&2);
+  }
+
+  if (!err)
+    err = InitPsyConfigurationShort(channelBitRate,
+                                    sampleRate,
+                                    bandwidth,
+                                    &hPsy->psyConfShort);
+  if (!err) {
+    err = InitTnsConfigurationShort(bitRate, sampleRate, channels,
+                                    &hPsy->psyConfShort.tnsConf, &hPsy->psyConfShort, tnsMask&1);
+  }
+
+  if (!err)
+    for(ch=0;ch < channels;ch++){
+  
+      InitBlockSwitching(&hPsy->psyData[ch].blockSwitchingControl,
+                         bitRate, channels);
+
+      InitPreEchoControl(hPsy->psyData[ch].sfbThresholdnm1,
+                         hPsy->psyConfLong.sfbCnt,
+                         hPsy->psyConfLong.sfbThresholdQuiet);
+      hPsy->psyData[ch].mdctScalenm1 = 0;                                
+    }
+
+	return(err);
+}
+
+/*****************************************************************************
+*
+* function name: psyMain
+* description:  psychoacoustic main function
+* returns:      an error code
+*
+*    This function assumes that enough input data is in the modulo buffer.
+*
+*****************************************************************************/
+
+Word16 psyMain(Word16                   nChannels,
+               ELEMENT_INFO            *elemInfo,
+               Word16                  *timeSignal, 
+               PSY_DATA                 psyData[MAX_CHANNELS],
+               TNS_DATA                 tnsData[MAX_CHANNELS],
+               PSY_CONFIGURATION_LONG  *hPsyConfLong,
+               PSY_CONFIGURATION_SHORT *hPsyConfShort,
+               PSY_OUT_CHANNEL          psyOutChannel[MAX_CHANNELS],
+               PSY_OUT_ELEMENT         *psyOutElement,
+               Word32                  *pScratchTns,
+			   Word32				   sampleRate)
+{
+  Word16 maxSfbPerGroup[MAX_CHANNELS];
+  Word16 mdctScalingArray[MAX_CHANNELS];
+
+  Word16 ch;   /* counts through channels          */
+  Word16 sfb;  /* counts through scalefactor bands */
+  Word16 line; /* counts through lines             */
+  Word16 channels;
+  Word16 maxScale;
+
+  channels = elemInfo->nChannelsInEl;                            
+  maxScale = 0;                                                  
+
+  /* block switching */

+  for(ch = 0; ch < channels; ch++) {
+    BlockSwitching(&psyData[ch].blockSwitchingControl,
+                   timeSignal+elemInfo->ChannelIndex[ch],
+				   sampleRate,
+                   nChannels);
+  }
+
+  /* synch left and right block type */
+  SyncBlockSwitching(&psyData[0].blockSwitchingControl,
+                     &psyData[1].blockSwitchingControl,
+                     channels);
+
+  /* transform
+     and get maxScale (max mdctScaling) for all channels */
+  for(ch=0; ch<channels; ch++) {
+    Transform_Real(psyData[ch].mdctDelayBuffer,
+                   timeSignal+elemInfo->ChannelIndex[ch],
+                   nChannels,
+                   psyData[ch].mdctSpectrum,
+                   &(mdctScalingArray[ch]),
+                   psyData[ch].blockSwitchingControl.windowSequence);
+    maxScale = max(maxScale, mdctScalingArray[ch]);
+  }
+
+  /* common scaling for all channels */
+  for (ch=0; ch<channels; ch++) {
+    Word16 scaleDiff = maxScale - mdctScalingArray[ch];
+     
+    if (scaleDiff > 0) {
+      Word32 *Spectrum = psyData[ch].mdctSpectrum;
+	  for(line=0; line<FRAME_LEN_LONG; line++) {
+        *Spectrum = (*Spectrum) >> scaleDiff;
+		Spectrum++;
+      }
+    }
+    psyData[ch].mdctScale = maxScale;                                    
+  }
+
+  for (ch=0; ch<channels; ch++) {
+     
+    if(psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW) {
+      /* update long block parameter */
+	  advancePsychLong(&psyData[ch],
+                       &tnsData[ch],
+                       hPsyConfLong,
+                       &psyOutChannel[ch],
+                       pScratchTns,
+                       &tnsData[1 - ch],
+                       ch);
+
+      /* determine maxSfb */
+      for (sfb=hPsyConfLong->sfbCnt-1; sfb>=0; sfb--) {
+        for (line=hPsyConfLong->sfbOffset[sfb+1] - 1; line>=hPsyConfLong->sfbOffset[sfb]; line--) {
+           
+          if (psyData[ch].mdctSpectrum[line] != 0) break;
+        }
+        if (line >= hPsyConfLong->sfbOffset[sfb]) break;
+      }
+      maxSfbPerGroup[ch] = sfb + 1;
+
+      /* Calc bandwise energies for mid and side channel
+         Do it only if 2 channels exist */
+       
+      if (ch == 1)
+        advancePsychLongMS(psyData, hPsyConfLong);
+    }
+    else {
+      advancePsychShort(&psyData[ch],
+                        &tnsData[ch],
+                        hPsyConfShort,
+                        &psyOutChannel[ch],
+                        pScratchTns,
+                        &tnsData[1 - ch],
+                        ch);
+
+      /* Calc bandwise energies for mid and side channel
+         Do it only if 2 channels exist */
+       
+      if (ch == 1)
+        advancePsychShortMS (psyData, hPsyConfShort);
+    }
+  }
+
+  /* group short data */
+  for(ch=0; ch<channels; ch++) {
+     
+    if (psyData[ch].blockSwitchingControl.windowSequence == SHORT_WINDOW) {
+      groupShortData(psyData[ch].mdctSpectrum,
+                     pScratchTns,
+                     &psyData[ch].sfbThreshold,
+                     &psyData[ch].sfbEnergy,
+                     &psyData[ch].sfbEnergyMS,
+                     &psyData[ch].sfbSpreadedEnergy,
+                     hPsyConfShort->sfbCnt,
+                     hPsyConfShort->sfbOffset,
+                     hPsyConfShort->sfbMinSnr,
+                     psyOutElement->groupedSfbOffset[ch],
+                     &maxSfbPerGroup[ch],
+                     psyOutElement->groupedSfbMinSnr[ch],
+                     psyData[ch].blockSwitchingControl.noOfGroups,
+                     psyData[ch].blockSwitchingControl.groupLen);
+    }
+  }
+
+
+#if (MAX_CHANNELS>1)
+  /*
+    stereo Processing
+  */
+  if (channels == 2) {
+    psyOutElement->toolsInfo.msDigest = MS_NONE;                 
+    maxSfbPerGroup[0] = maxSfbPerGroup[1] = max(maxSfbPerGroup[0], maxSfbPerGroup[1]);
+
+     
+    if (psyData[0].blockSwitchingControl.windowSequence != SHORT_WINDOW)
+      MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
+                         psyData[1].sfbEnergy.sfbLong,
+                         psyData[0].sfbEnergyMS.sfbLong,
+                         psyData[1].sfbEnergyMS.sfbLong,
+                         psyData[0].mdctSpectrum,
+                         psyData[1].mdctSpectrum,
+                         psyData[0].sfbThreshold.sfbLong,
+                         psyData[1].sfbThreshold.sfbLong,
+                         psyData[0].sfbSpreadedEnergy.sfbLong,
+                         psyData[1].sfbSpreadedEnergy.sfbLong,
+                         (Word16*)&psyOutElement->toolsInfo.msDigest,
+                         (Word16*)psyOutElement->toolsInfo.msMask,
+                         hPsyConfLong->sfbCnt,
+                         hPsyConfLong->sfbCnt,
+                         maxSfbPerGroup[0],
+                         (const Word16*)hPsyConfLong->sfbOffset);
+      else
+        MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
+                           psyData[1].sfbEnergy.sfbLong,
+                           psyData[0].sfbEnergyMS.sfbLong,
+                           psyData[1].sfbEnergyMS.sfbLong,
+                           psyData[0].mdctSpectrum,
+                           psyData[1].mdctSpectrum,
+                           psyData[0].sfbThreshold.sfbLong,
+                           psyData[1].sfbThreshold.sfbLong,
+                           psyData[0].sfbSpreadedEnergy.sfbLong,
+                           psyData[1].sfbSpreadedEnergy.sfbLong,
+                           (Word16*)&psyOutElement->toolsInfo.msDigest,
+                           (Word16*)psyOutElement->toolsInfo.msMask,
+                           psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
+                           hPsyConfShort->sfbCnt,
+                           maxSfbPerGroup[0],
+                           (const Word16*)psyOutElement->groupedSfbOffset[0]);
+  }
+
+#endif /* (MAX_CHANNELS>1) */
+
+  /*
+    build output
+  */
+  for(ch=0;ch<channels;ch++) {
+     
+    if (psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW)
+      BuildInterface(psyData[ch].mdctSpectrum,
+                     psyData[ch].mdctScale,
+                     &psyData[ch].sfbThreshold,
+                     &psyData[ch].sfbEnergy,
+                     &psyData[ch].sfbSpreadedEnergy,
+                     psyData[ch].sfbEnergySum,
+                     psyData[ch].sfbEnergySumMS,
+                     psyData[ch].blockSwitchingControl.windowSequence,
+                     blockType2windowShape[psyData[ch].blockSwitchingControl.windowSequence],
+                     hPsyConfLong->sfbCnt,
+                     hPsyConfLong->sfbOffset,
+                     maxSfbPerGroup[ch],
+                     hPsyConfLong->sfbMinSnr,
+                     psyData[ch].blockSwitchingControl.noOfGroups,
+                     psyData[ch].blockSwitchingControl.groupLen,
+                     &psyOutChannel[ch]);
+    else
+      BuildInterface(psyData[ch].mdctSpectrum,
+                     psyData[ch].mdctScale,
+                     &psyData[ch].sfbThreshold,
+                     &psyData[ch].sfbEnergy,
+                     &psyData[ch].sfbSpreadedEnergy,
+                     psyData[ch].sfbEnergySum,
+                     psyData[ch].sfbEnergySumMS,
+                     SHORT_WINDOW,
+                     SINE_WINDOW,
+                     psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
+                     psyOutElement->groupedSfbOffset[ch],
+                     maxSfbPerGroup[ch],
+                     psyOutElement->groupedSfbMinSnr[ch],
+                     psyData[ch].blockSwitchingControl.noOfGroups,
+                     psyData[ch].blockSwitchingControl.groupLen,
+                     &psyOutChannel[ch]);
+  }
+
+  return(0); /* no error */
+}
+
+/*****************************************************************************
+*
+* function name: advancePsychLong
+* description:  psychoacoustic for long blocks
+*
+*****************************************************************************/
+
+static Word16 advancePsychLong(PSY_DATA* psyData,
+                               TNS_DATA* tnsData,
+                               PSY_CONFIGURATION_LONG *hPsyConfLong,
+                               PSY_OUT_CHANNEL* psyOutChannel,
+                               Word32 *pScratchTns,
+                               const TNS_DATA* tnsData2,
+                               const Word16 ch)
+{
+  Word32 i;
+  Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
+  Word32 clipEnergy = hPsyConfLong->clipEnergy >> normEnergyShift;

+  Word32 *data0, *data1, tdata;
+
+  /* low pass */
+  data0 = psyData->mdctSpectrum + hPsyConfLong->lowpassLine;

+  for(i=hPsyConfLong->lowpassLine; i<FRAME_LEN_LONG; i++) {
+    *data0++ = 0;                                
+  }
+
+  /* Calc sfb-bandwise mdct-energies for left and right channel */
+  CalcBandEnergy( psyData->mdctSpectrum,
+                  hPsyConfLong->sfbOffset,
+                  hPsyConfLong->sfbActive,
+                  psyData->sfbEnergy.sfbLong,
+                  &psyData->sfbEnergySum.sfbLong);
+
+  /*
+    TNS detect
+  */
+  TnsDetect(tnsData,
+            hPsyConfLong->tnsConf,
+            pScratchTns,
+            (const Word16*)hPsyConfLong->sfbOffset,
+            psyData->mdctSpectrum,
+            0,
+            psyData->blockSwitchingControl.windowSequence,
+            psyData->sfbEnergy.sfbLong);
+
+  /*  TnsSync */   
+  if (ch == 1) {
+    TnsSync(tnsData,
+            tnsData2,
+            hPsyConfLong->tnsConf,
+            0,
+            psyData->blockSwitchingControl.windowSequence);
+  }
+
+  /*  Tns Encoder */ 
+  TnsEncode(&psyOutChannel->tnsInfo,
+            tnsData,
+            hPsyConfLong->sfbCnt,
+            hPsyConfLong->tnsConf,
+            hPsyConfLong->lowpassLine,
+            psyData->mdctSpectrum,
+            0,
+            psyData->blockSwitchingControl.windowSequence);
+
+  /* first part of threshold calculation */
+  data0 = psyData->sfbEnergy.sfbLong;

+  data1 = psyData->sfbThreshold.sfbLong;

+  for (i=hPsyConfLong->sfbCnt; i; i--) {
+    tdata = L_mpy_ls(*data0++, hPsyConfLong->ratio);
+    *data1++ = min(tdata, clipEnergy);

+  }
+
+  /* Calc sfb-bandwise mdct-energies for left and right channel again */   
+  if (tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive!=0) {
+    Word16 tnsStartBand = hPsyConfLong->tnsConf.tnsStartBand;                            
+    CalcBandEnergy( psyData->mdctSpectrum,
+                    hPsyConfLong->sfbOffset+tnsStartBand,
+                    hPsyConfLong->sfbActive - tnsStartBand,
+                    psyData->sfbEnergy.sfbLong+tnsStartBand,
+                    &psyData->sfbEnergySum.sfbLong);
+    

+	data0 = psyData->sfbEnergy.sfbLong;

+	tdata = psyData->sfbEnergySum.sfbLong;

+	for (i=0; i<tnsStartBand; i++)
+      tdata += *data0++;

+

+	psyData->sfbEnergySum.sfbLong = tdata;
+  }
+
+
+  /* spreading energy */
+  SpreadingMax(hPsyConfLong->sfbCnt,
+               hPsyConfLong->sfbMaskLowFactor,
+               hPsyConfLong->sfbMaskHighFactor,
+               psyData->sfbThreshold.sfbLong);
+
+  /* threshold in quiet */
+  data0 = psyData->sfbThreshold.sfbLong;

+  data1 = hPsyConfLong->sfbThresholdQuiet;

+  for (i=hPsyConfLong->sfbCnt; i; i--)
+  {

+	  *data0 = max(*data0, (*data1 >> normEnergyShift));

+	  data0++; data1++;

+  }
+
+  /* preecho control */   
+  if (psyData->blockSwitchingControl.windowSequence == STOP_WINDOW) {
+    data0 = psyData->sfbThresholdnm1;

+	for (i=hPsyConfLong->sfbCnt; i; i--) {

+      *data0++ = MAX_32;                              

+    }

+    psyData->mdctScalenm1 = 0;                                           
+  }
+
+  PreEchoControl( psyData->sfbThresholdnm1,
+                  hPsyConfLong->sfbCnt,
+                  hPsyConfLong->maxAllowedIncreaseFactor,
+                  hPsyConfLong->minRemainingThresholdFactor,
+                  psyData->sfbThreshold.sfbLong,
+                  psyData->mdctScale,
+                  psyData->mdctScalenm1);
+  psyData->mdctScalenm1 = psyData->mdctScale;                            
+
+   
+  if (psyData->blockSwitchingControl.windowSequence== START_WINDOW) {
+    data0 = psyData->sfbThresholdnm1;

+	for (i=hPsyConfLong->sfbCnt; i; i--) {
+      *data0++ = MAX_32;                              
+    }
+    psyData->mdctScalenm1 = 0;                                           
+  }
+
+  /* apply tns mult table on cb thresholds */
+  ApplyTnsMultTableToRatios(hPsyConfLong->tnsConf.tnsRatioPatchLowestCb,
+                            hPsyConfLong->tnsConf.tnsStartBand,
+                            tnsData->dataRaw.tnsLong.subBlockInfo,
+                            psyData->sfbThreshold.sfbLong);
+
+
+  /* spreaded energy */
+  data0 = psyData->sfbSpreadedEnergy.sfbLong;

+  data1 = psyData->sfbEnergy.sfbLong;

+  for (i=hPsyConfLong->sfbCnt; i; i--) {
+    //psyData->sfbSpreadedEnergy.sfbLong[i] = psyData->sfbEnergy.sfbLong[i];       

+	  *data0++ = *data1++;
+  }
+
+  /* spreading energy */
+  SpreadingMax(hPsyConfLong->sfbCnt,
+               hPsyConfLong->sfbMaskLowFactorSprEn, 
+               hPsyConfLong->sfbMaskHighFactorSprEn,
+               psyData->sfbSpreadedEnergy.sfbLong);
+
+  return 0;
+}
+
+/*****************************************************************************
+*
+* function name: advancePsychLongMS
+* description:   update mdct-energies for left add or minus right channel 
+*				for long block
+*
+*****************************************************************************/
+static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
+                                  const PSY_CONFIGURATION_LONG *hPsyConfLong)
+{
+  CalcBandEnergyMS(psyData[0].mdctSpectrum,
+                   psyData[1].mdctSpectrum,
+                   hPsyConfLong->sfbOffset,
+                   hPsyConfLong->sfbActive,
+                   psyData[0].sfbEnergyMS.sfbLong,
+                   &psyData[0].sfbEnergySumMS.sfbLong,
+                   psyData[1].sfbEnergyMS.sfbLong,
+                   &psyData[1].sfbEnergySumMS.sfbLong);
+
+  return 0;
+}
+
+
+/*****************************************************************************
+*
+* function name: advancePsychShort
+* description:  psychoacoustic for short blocks
+*
+*****************************************************************************/
+
+static Word16 advancePsychShort(PSY_DATA* psyData,
+                                TNS_DATA* tnsData,
+                                const PSY_CONFIGURATION_SHORT *hPsyConfShort,
+                                PSY_OUT_CHANNEL* psyOutChannel,
+                                Word32 *pScratchTns,
+                                const TNS_DATA *tnsData2,
+                                const Word16 ch)
+{
+  Word32 w;
+  Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
+  Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift;
+  Word32 wOffset = 0;     

+  Word32 *data0, *data1;
+
+  for(w = 0; w < TRANS_FAC; w++) {
+    Word32 i, tdata;
+
+    /* low pass */
+    data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine;

+	for(i=hPsyConfShort->lowpassLine; i<FRAME_LEN_SHORT; i++){
+      *data0++ = 0;                                      
+    }
+
+    /* Calc sfb-bandwise mdct-energies for left and right channel */
+    CalcBandEnergy( psyData->mdctSpectrum+wOffset,
+                    hPsyConfShort->sfbOffset,
+                    hPsyConfShort->sfbActive,
+                    psyData->sfbEnergy.sfbShort[w],
+                    &psyData->sfbEnergySum.sfbShort[w]);
+    /*
+       TNS
+    */
+    TnsDetect(tnsData,
+              hPsyConfShort->tnsConf,
+              pScratchTns,
+              (const Word16*)hPsyConfShort->sfbOffset,
+              psyData->mdctSpectrum+wOffset,
+              w,
+              psyData->blockSwitchingControl.windowSequence,
+              psyData->sfbEnergy.sfbShort[w]);
+
+    /*  TnsSync */
+    if (ch == 1) {
+      TnsSync(tnsData,
+              tnsData2,
+              hPsyConfShort->tnsConf,
+              w,
+              psyData->blockSwitchingControl.windowSequence);
+    }
+
+    TnsEncode(&psyOutChannel->tnsInfo,
+              tnsData,
+              hPsyConfShort->sfbCnt,
+              hPsyConfShort->tnsConf,
+              hPsyConfShort->lowpassLine,
+              psyData->mdctSpectrum+wOffset,
+              w,
+              psyData->blockSwitchingControl.windowSequence);
+
+    /* first part of threshold calculation */
+    data0 = psyData->sfbThreshold.sfbShort[w];

+	data1 = psyData->sfbEnergy.sfbShort[w];

+	for (i=hPsyConfShort->sfbCnt; i; i--) {
+      tdata = L_mpy_ls(*data1++, hPsyConfShort->ratio);
+      *data0++ = min(tdata, clipEnergy);

+    }
+
+    /* Calc sfb-bandwise mdct-energies for left and right channel again */     
+    if (tnsData->dataRaw.tnsShort.subBlockInfo[w].tnsActive != 0) {
+      Word16 tnsStartBand = hPsyConfShort->tnsConf.tnsStartBand;                            
+      CalcBandEnergy( psyData->mdctSpectrum+wOffset,
+                      hPsyConfShort->sfbOffset+tnsStartBand,
+                      (hPsyConfShort->sfbActive - tnsStartBand),
+                      psyData->sfbEnergy.sfbShort[w]+tnsStartBand,
+                      &psyData->sfbEnergySum.sfbShort[w]);

+
+      tdata = psyData->sfbEnergySum.sfbShort[w];

+	  data0 = psyData->sfbEnergy.sfbShort[w];

+	  for (i=tnsStartBand; i; i--)
+        tdata += *data0++;

+

+	  psyData->sfbEnergySum.sfbShort[w] = tdata;
+    }
+
+    /* spreading */
+    SpreadingMax(hPsyConfShort->sfbCnt,
+                 hPsyConfShort->sfbMaskLowFactor,
+                 hPsyConfShort->sfbMaskHighFactor,
+                 psyData->sfbThreshold.sfbShort[w]);
+
+
+    /* threshold in quiet */
+    data0 = psyData->sfbThreshold.sfbShort[w];

+	data1 = hPsyConfShort->sfbThresholdQuiet;

+	for (i=hPsyConfShort->sfbCnt; i; i--)
+    {

+		*data0 = max(*data0, (*data1 >> normEnergyShift));

+

+		data0++; data1++;

+	}

+
+
+    /* preecho */     
+    PreEchoControl( psyData->sfbThresholdnm1,
+                    hPsyConfShort->sfbCnt,
+                    hPsyConfShort->maxAllowedIncreaseFactor,
+                    hPsyConfShort->minRemainingThresholdFactor,
+                    psyData->sfbThreshold.sfbShort[w],
+                    psyData->mdctScale,
+                    w==0 ? psyData->mdctScalenm1 : psyData->mdctScale);
+
+    /* apply tns mult table on cb thresholds */
+    ApplyTnsMultTableToRatios( hPsyConfShort->tnsConf.tnsRatioPatchLowestCb,
+                               hPsyConfShort->tnsConf.tnsStartBand,
+                               tnsData->dataRaw.tnsShort.subBlockInfo[w],
+                               psyData->sfbThreshold.sfbShort[w]);
+
+    /* spreaded energy */
+    data0 = psyData->sfbSpreadedEnergy.sfbShort[w];

+	data1 = psyData->sfbEnergy.sfbShort[w];

+	for (i=hPsyConfShort->sfbCnt; i; i--) {
+	  *data0++ = *data1++;
+    }
+    SpreadingMax(hPsyConfShort->sfbCnt,
+                 hPsyConfShort->sfbMaskLowFactorSprEn, 
+                 hPsyConfShort->sfbMaskHighFactorSprEn,
+                 psyData->sfbSpreadedEnergy.sfbShort[w]);
+
+    wOffset += FRAME_LEN_SHORT;
+  } /* for TRANS_FAC */
+
+  psyData->mdctScalenm1 = psyData->mdctScale;              
+
+  return 0;
+}
+
+/*****************************************************************************
+*
+* function name: advancePsychShortMS
+* description:   update mdct-energies for left add or minus right channel 
+*				for short block
+*
+*****************************************************************************/
+static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
+                                   const PSY_CONFIGURATION_SHORT *hPsyConfShort)
+{
+  Word32 w, wOffset;
+  wOffset = 0;                                   
+  for(w=0; w<TRANS_FAC; w++) {
+    CalcBandEnergyMS(psyData[0].mdctSpectrum+wOffset,
+                     psyData[1].mdctSpectrum+wOffset,
+                     hPsyConfShort->sfbOffset,
+                     hPsyConfShort->sfbActive,
+                     psyData[0].sfbEnergyMS.sfbShort[w],
+                     &psyData[0].sfbEnergySumMS.sfbShort[w],
+                     psyData[1].sfbEnergyMS.sfbShort[w],
+                     &psyData[1].sfbEnergySumMS.sfbShort[w]);
+    wOffset += FRAME_LEN_SHORT;
+  }
+
+  return 0;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/qc_main.c b/media/libstagefright/codecs/aacenc/src/qc_main.c
new file mode 100644
index 0000000..a568020
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/qc_main.c
@@ -0,0 +1,580 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		qc_main.c

+

+	Content:	Quantizing & coding functions

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "oper_32b.h"

+#include "qc_main.h"
+#include "quantize.h"
+#include "interface.h"
+#include "adj_thr.h"
+#include "sf_estim.h"
+#include "stat_bits.h"
+#include "bit_cnt.h"
+#include "dyn_bits.h"
+#include "channel_map.h"
+#include "memalign.h"
+
+
+typedef enum{
+  FRAME_LEN_BYTES_MODULO =  1,
+  FRAME_LEN_BYTES_INT    =  2
+}FRAME_LEN_RESULT_MODE;
+
+static const Word16 maxFillElemBits = 7 + 270*8;
+
+/* forward declarations */
+
+static Word16 calcMaxValueInSfb(Word16 sfbCnt,
+                                Word16 maxSfbPerGroup,
+                                Word16 sfbPerGroup,
+                                Word16 sfbOffset[MAX_GROUPED_SFB],
+                                Word16 quantSpectrum[FRAME_LEN_LONG],
+                                UWord16 maxValue[MAX_GROUPED_SFB]);
+
+
+/*****************************************************************************
+*
+* function name: calcFrameLen
+* description: estimate the frame length according the bitrates
+*
+*****************************************************************************/
+static Word16 calcFrameLen(Word32 bitRate,
+                           Word32 sampleRate,
+                           FRAME_LEN_RESULT_MODE mode)
+{
+
+  Word32 result;
+  Word32 quot;
+
+  result = (FRAME_LEN_LONG >> 3) * bitRate;
+  quot = result / sampleRate;
+
+   
+  if (mode == FRAME_LEN_BYTES_MODULO) {
+    result -= quot * sampleRate;
+  }
+  else { /* FRAME_LEN_BYTES_INT */
+    result = quot;                                      
+  }
+
+  return result;
+}
+
+/*****************************************************************************
+*
+*  function name:framePadding
+*  description: Calculates if padding is needed for actual frame
+*  returns: paddingOn or not 
+*
+*****************************************************************************/
+static Word16 framePadding(Word32 bitRate,
+                           Word32 sampleRate,
+                           Word32 *paddingRest)
+{
+  Word16 paddingOn;
+  Word16 difference;
+
+  paddingOn = 0;                                                 
+
+  difference = calcFrameLen( bitRate,
+                             sampleRate,
+                             FRAME_LEN_BYTES_MODULO );
+  *paddingRest = *paddingRest - difference;
+
+   
+  if (*paddingRest <= 0 ) {
+    paddingOn = 1;                                               
+    *paddingRest = *paddingRest + sampleRate;
+  }
+
+  return paddingOn;
+}
+
+
+/*********************************************************************************
+*
+* function name: QCOutNew
+* description: init qcout parameter
+* returns:     0 if success
+*
+**********************************************************************************/
+
+Word16 QCOutNew(QC_OUT *hQC, Word16 nChannels, VO_MEM_OPERATOR *pMemOP)
+{
+  Word32 i;

+  Word16 *quantSpec;

+  Word16 *scf;

+  UWord16 *maxValueInSfb;	
+	

+  quantSpec = (Word16 *)mem_malloc(pMemOP, nChannels * FRAME_LEN_LONG * sizeof(Word16), 32, VO_INDEX_ENC_AAC);

+  if(NULL == quantSpec)

+	  return 1;
+  scf = (Word16 *)mem_malloc(pMemOP, nChannels * MAX_GROUPED_SFB * sizeof(Word16), 32, VO_INDEX_ENC_AAC);     

+  if(NULL == scf)

+  {

+	  return 1;

+  }
+  maxValueInSfb = (UWord16 *)mem_malloc(pMemOP, nChannels * MAX_GROUPED_SFB * sizeof(UWord16), 32, VO_INDEX_ENC_AAC);

+  if(NULL == maxValueInSfb)

+  {

+	  return 1;

+  }

+

+  for (i=0; i<nChannels; i++) {
+    hQC->qcChannel[i].quantSpec = quantSpec + i*FRAME_LEN_LONG;
+    
+    hQC->qcChannel[i].maxValueInSfb = maxValueInSfb + i*MAX_GROUPED_SFB;
+    
+    hQC->qcChannel[i].scf = scf + i*MAX_GROUPED_SFB;
+  }
+ 
+  return 0;
+}
+
+
+/*********************************************************************************
+*
+* function name: QCOutDelete
+* description: unint qcout parameter
+* returns:      0 if success
+*
+**********************************************************************************/
+void QCOutDelete(QC_OUT* hQC, VO_MEM_OPERATOR *pMemOP)
+{
+   Word32 i;

+   if(hQC)

+   {

+      if(hQC->qcChannel[0].quantSpec);

+		 mem_free(pMemOP, hQC->qcChannel[0].quantSpec, VO_INDEX_ENC_AAC);

+    

+      if(hQC->qcChannel[0].maxValueInSfb)

+		  mem_free(pMemOP, hQC->qcChannel[0].maxValueInSfb, VO_INDEX_ENC_AAC);

+    

+	  if(hQC->qcChannel[0].scf)

+		  mem_free(pMemOP, hQC->qcChannel[0].scf, VO_INDEX_ENC_AAC);

+

+	  for (i=0; i<MAX_CHANNELS; i++) {

+		  hQC->qcChannel[i].quantSpec = NULL;

+		  

+		  hQC->qcChannel[i].maxValueInSfb = NULL;

+		  

+		  hQC->qcChannel[i].scf = NULL;

+	  }

+   } 
+}
+
+/*********************************************************************************
+*
+* function name: QCNew
+* description: set QC to zero
+* returns:     0 if success
+*
+**********************************************************************************/
+Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP)
+{
+  pMemOP->Set(VO_INDEX_ENC_AAC, hQC,0,sizeof(QC_STATE));
+
+  return (0);
+}
+
+/*********************************************************************************
+*
+* function name: QCDelete
+* description: unint qcout parameter
+*
+**********************************************************************************/
+void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP)
+{
+ 
+  /* 
+     nothing to do
+  */
+  hQC=NULL;
+}
+
+/*********************************************************************************
+*
+* function name: QCInit
+* description: init QD parameter
+* returns:     0 if success
+*
+**********************************************************************************/
+Word16 QCInit(QC_STATE *hQC,
+              struct QC_INIT *init)
+{
+  hQC->nChannels       = init->elInfo->nChannelsInEl;              
+  hQC->maxBitsTot      = init->maxBits;                            
+  hQC->bitResTot       = sub(init->bitRes, init->averageBits);
+  hQC->averageBitsTot  = init->averageBits;                        
+  hQC->maxBitFac       = init->maxBitFac;                          
+
+  hQC->padding.paddingRest = init->padding.paddingRest;            
+
+  hQC->globStatBits    = 3;                          /* for ID_END */ 
+
+  /* channel elements init */
+  InitElementBits(&hQC->elementBits,
+                  *init->elInfo,
+                  init->bitrate,
+                  init->averageBits,
+                  hQC->globStatBits);
+
+  /* threshold parameter init */
+  AdjThrInit(&hQC->adjThr,
+             init->meanPe,
+             hQC->elementBits.chBitrate);
+
+  return 0;
+}
+
+
+/*********************************************************************************
+* 
+* function name: QCMain
+* description:  quantization and coding the spectrum
+* returns:      0 if success
+*
+**********************************************************************************/
+Word16 QCMain(QC_STATE* hQC,              
+              ELEMENT_BITS* elBits,
+              ATS_ELEMENT* adjThrStateElement,
+              PSY_OUT_CHANNEL  psyOutChannel[MAX_CHANNELS],  /* may be modified in-place */
+              PSY_OUT_ELEMENT* psyOutElement,
+              QC_OUT_CHANNEL  qcOutChannel[MAX_CHANNELS],    /* out                      */
+              QC_OUT_ELEMENT* qcOutElement,
+              Word16 nChannels,
+			  Word16 ancillaryDataBytes)      
+{
+  Word16 maxChDynBits[MAX_CHANNELS];
+  Word16 chBitDistribution[MAX_CHANNELS];  
+  Word32 ch;
+   
+  if (elBits->bitResLevel < 0) {
+    return -1;
+  }
+   
+  if (elBits->bitResLevel > elBits->maxBitResBits) {
+    return -1;
+  }
+
+  qcOutElement->staticBitsUsed = countStaticBitdemand(psyOutChannel,
+                                                      psyOutElement,
+                                                      nChannels, 

+													  qcOutElement->adtsUsed);
+
+   
+  if (ancillaryDataBytes) {
+    qcOutElement->ancBitsUsed = 7 + (ancillaryDataBytes << 3);
+     
+    if (ancillaryDataBytes >= 15)
+      qcOutElement->ancBitsUsed = qcOutElement->ancBitsUsed + 8;
+  }
+  else {
+    qcOutElement->ancBitsUsed = 0; 
+  }
+
+  CalcFormFactor(hQC->logSfbFormFactor, hQC->sfbNRelevantLines, hQC->logSfbEnergy, psyOutChannel, nChannels);
+
+  /*adjust thresholds for the desired bitrate */
+  AdjustThresholds(&hQC->adjThr,
+                   adjThrStateElement,
+                   psyOutChannel,
+                   psyOutElement,
+                   chBitDistribution,
+                   hQC->logSfbEnergy,
+                   hQC->sfbNRelevantLines,                   
+                   qcOutElement,
+				   elBits,
+				   nChannels,
+				   hQC->maxBitFac);
+
+  /*estimate scale factors */
+  EstimateScaleFactors(psyOutChannel,
+                       qcOutChannel,
+                       hQC->logSfbEnergy,
+                       hQC->logSfbFormFactor,
+                       hQC->sfbNRelevantLines,
+                       nChannels);
+
+  /* condition to prevent empty bitreservoir */
+  for (ch = 0; ch < nChannels; ch++) {
+    Word32 maxDynBits;
+    maxDynBits = elBits->averageBits + elBits->bitResLevel - 7; /* -7 bec. of align bits */
+    maxDynBits = maxDynBits - qcOutElement->staticBitsUsed + qcOutElement->ancBitsUsed;
+    maxChDynBits[ch] = extract_l(chBitDistribution[ch] * maxDynBits / 1000);
+  }
+
+  qcOutElement->dynBitsUsed = 0;                                         
+  for (ch = 0; ch < nChannels; ch++) {
+    Word32 chDynBits;
+    Flag   constraintsFulfilled;
+    Word32 iter;
+    iter = 0;                                                          
+    do {
+      constraintsFulfilled = 1;                                        
+
+      QuantizeSpectrum(psyOutChannel[ch].sfbCnt,
+                       psyOutChannel[ch].maxSfbPerGroup,
+                       psyOutChannel[ch].sfbPerGroup,
+                       psyOutChannel[ch].sfbOffsets,
+                       psyOutChannel[ch].mdctSpectrum,
+                       qcOutChannel[ch].globalGain,
+                       qcOutChannel[ch].scf,
+                       qcOutChannel[ch].quantSpec);
+       
+      if (calcMaxValueInSfb(psyOutChannel[ch].sfbCnt,
+                            psyOutChannel[ch].maxSfbPerGroup,
+                            psyOutChannel[ch].sfbPerGroup,
+                            psyOutChannel[ch].sfbOffsets,
+                            qcOutChannel[ch].quantSpec,
+                            qcOutChannel[ch].maxValueInSfb) > MAX_QUANT) {
+        constraintsFulfilled = 0;                                        
+      }
+
+      chDynBits = dynBitCount(qcOutChannel[ch].quantSpec,
+                              qcOutChannel[ch].maxValueInSfb,
+                              qcOutChannel[ch].scf,
+                              psyOutChannel[ch].windowSequence,
+                              psyOutChannel[ch].sfbCnt,
+                              psyOutChannel[ch].maxSfbPerGroup,
+                              psyOutChannel[ch].sfbPerGroup,
+                              psyOutChannel[ch].sfbOffsets,
+                              &qcOutChannel[ch].sectionData);
+       
+      if (chDynBits >= maxChDynBits[ch]) {
+        constraintsFulfilled = 0;                                        
+      }
+       
+      if (!constraintsFulfilled) {
+        qcOutChannel[ch].globalGain = qcOutChannel[ch].globalGain + 1;
+      }
+
+      iter = iter + 1;
+       
+    } while(!constraintsFulfilled);
+
+    qcOutElement->dynBitsUsed = qcOutElement->dynBitsUsed + chDynBits;
+
+    qcOutChannel[ch].mdctScale    = psyOutChannel[ch].mdctScale;         
+    qcOutChannel[ch].groupingMask = psyOutChannel[ch].groupingMask;      
+    qcOutChannel[ch].windowShape  = psyOutChannel[ch].windowShape;       
+  }
+
+  /* save dynBitsUsed for correction of bits2pe relation */
+  AdjThrUpdate(adjThrStateElement, qcOutElement->dynBitsUsed);
+
+  {
+    Word16 bitResSpace = elBits->maxBitResBits - elBits->bitResLevel;
+    Word16 deltaBitRes = elBits->averageBits -
+                        (qcOutElement->staticBitsUsed +
+                         qcOutElement->dynBitsUsed + qcOutElement->ancBitsUsed);
+
+    qcOutElement->fillBits = max(0, (deltaBitRes - bitResSpace));
+  }
+
+  return 0; /* OK */
+}
+
+
+/*********************************************************************************
+*
+* function name: calcMaxValueInSfb
+* description:  search the max Spectrum in one sfb
+*
+**********************************************************************************/
+static Word16 calcMaxValueInSfb(Word16 sfbCnt,
+                                Word16 maxSfbPerGroup,
+                                Word16 sfbPerGroup,
+                                Word16 sfbOffset[MAX_GROUPED_SFB],
+                                Word16 quantSpectrum[FRAME_LEN_LONG],
+                                UWord16 maxValue[MAX_GROUPED_SFB])
+{
+  Word16 sfbOffs, sfb;
+  Word16 maxValueAll;
+
+  maxValueAll = 0;                                       
+
+  for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) {
+    for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
+      Word16 line;
+      Word16 maxThisSfb;
+      maxThisSfb = 0;                                    
+
+      for (line = sfbOffset[sfbOffs+sfb]; line < sfbOffset[sfbOffs+sfb+1]; line++) {
+        Word16 absVal;
+        absVal = abs_s(quantSpectrum[line]);
+        maxThisSfb = max(maxThisSfb, absVal);
+      }
+
+      maxValue[sfbOffs+sfb] = maxThisSfb;                
+      maxValueAll = max(maxValueAll, maxThisSfb);
+    }
+  }
+  return maxValueAll;
+}
+
+
+/*********************************************************************************
+*
+* function name: updateBitres
+* description: update bitreservoir
+*
+**********************************************************************************/
+void updateBitres(QC_STATE* qcKernel,
+                  QC_OUT*   qcOut)
+                  
+{
+  ELEMENT_BITS *elBits;
+ 
+  qcKernel->bitResTot = 0;                               
+
+  elBits = &qcKernel->elementBits;
+
+   
+  if (elBits->averageBits > 0) {
+    /* constant bitrate */
+    Word16 bitsUsed;
+    bitsUsed = (qcOut->qcElement.staticBitsUsed + qcOut->qcElement.dynBitsUsed) +
+                   (qcOut->qcElement.ancBitsUsed + qcOut->qcElement.fillBits);
+    elBits->bitResLevel = elBits->bitResLevel + (elBits->averageBits - bitsUsed);
+    qcKernel->bitResTot = qcKernel->bitResTot + elBits->bitResLevel;
+  }
+  else {
+    /* variable bitrate */
+    elBits->bitResLevel = elBits->maxBits;           
+    qcKernel->bitResTot = qcKernel->maxBitsTot;      
+  }
+}
+
+/*********************************************************************************
+*
+* function name: FinalizeBitConsumption
+* description: count bits used
+*
+**********************************************************************************/
+Word16 FinalizeBitConsumption(QC_STATE *qcKernel,
+                              QC_OUT* qcOut)
+{
+  Word32 nFullFillElem;

+  Word32 totFillBits;

+  Word16 diffBits;  
+  Word16 bitsUsed;
+
+  totFillBits = 0;                                       
+
+  qcOut->totStaticBitsUsed = qcKernel->globStatBits;     
+  qcOut->totStaticBitsUsed += qcOut->qcElement.staticBitsUsed;
+  qcOut->totDynBitsUsed    = qcOut->qcElement.dynBitsUsed;
+  qcOut->totAncBitsUsed    = qcOut->qcElement.ancBitsUsed;
+  qcOut->totFillBits       = qcOut->qcElement.fillBits;
+   
+  if (qcOut->qcElement.fillBits) {
+    totFillBits += qcOut->qcElement.fillBits;
+  }
+
+  nFullFillElem = (max((qcOut->totFillBits - 1), 0) / maxFillElemBits) * maxFillElemBits;

+  
+  qcOut->totFillBits = qcOut->totFillBits - nFullFillElem;
+
+  /* check fill elements */
+   
+  if (qcOut->totFillBits > 0) {
+    /* minimum Fillelement contains 7 (TAG + byte cnt) bits */
+    qcOut->totFillBits = max(7, qcOut->totFillBits);
+    /* fill element size equals n*8 + 7 */
+    qcOut->totFillBits = qcOut->totFillBits + ((8 - ((qcOut->totFillBits - 7) & 0x0007)) & 0x0007);     
+  }
+
+  qcOut->totFillBits = qcOut->totFillBits + nFullFillElem;
+
+  /* now distribute extra fillbits and alignbits over channel elements */
+  qcOut->alignBits = 7 - ((qcOut->totDynBitsUsed + qcOut->totStaticBitsUsed +
+                           qcOut->totAncBitsUsed + qcOut->totFillBits - 1) & 0x0007);             
+
+     
+  if ( (qcOut->alignBits + qcOut->totFillBits - totFillBits == 8) &&
+       (qcOut->totFillBits > 8))
+    qcOut->totFillBits = qcOut->totFillBits - 8;
+
+   
+  diffBits = qcOut->alignBits + qcOut->totFillBits - totFillBits;
+   
+  if(diffBits>=0) {
+    qcOut->qcElement.fillBits += diffBits;
+  }
+
+  bitsUsed = qcOut->totDynBitsUsed + qcOut->totStaticBitsUsed + qcOut->totAncBitsUsed;
+  bitsUsed = bitsUsed + qcOut->totFillBits + qcOut->alignBits;
+   
+  if (bitsUsed > qcKernel->maxBitsTot) {
+    return -1;
+  }
+  return bitsUsed;
+}
+
+
+/*********************************************************************************
+*
+* function name: AdjustBitrate
+* description:  adjusts framelength via padding on a frame to frame basis,
+*               to achieve a bitrate that demands a non byte aligned
+*               framelength
+* return:       errorcode
+*
+**********************************************************************************/
+Word16 AdjustBitrate(QC_STATE        *hQC,
+                     Word32           bitRate,    /* total bitrate */
+                     Word32           sampleRate) /* output sampling rate */
+{
+  Word16 paddingOn;
+  Word16 frameLen;
+  Word16 codeBits;
+  Word16 codeBitsLast;
+
+  /* Do we need a extra padding byte? */
+  paddingOn = framePadding(bitRate,
+                           sampleRate,
+                           &hQC->padding.paddingRest);
+
+  /* frame length */
+  frameLen = paddingOn + calcFrameLen(bitRate,
+                                      sampleRate,
+                                      FRAME_LEN_BYTES_INT);
+
+  frameLen = frameLen << 3;
+  codeBitsLast = hQC->averageBitsTot - hQC->globStatBits;
+  codeBits     = frameLen - hQC->globStatBits;
+
+  /* calculate bits for every channel element */   
+  if (codeBits != codeBitsLast) {
+    Word16 totalBits = 0;                                       
+
+    hQC->elementBits.averageBits = (hQC->elementBits.relativeBits * codeBits) >> 16; /* relativeBits was scaled down by 2 */
+    totalBits += hQC->elementBits.averageBits;
+
+    hQC->elementBits.averageBits = hQC->elementBits.averageBits + (codeBits - totalBits);
+  }
+
+  hQC->averageBitsTot = frameLen;                        
+
+  return 0;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/quantize.c b/media/libstagefright/codecs/aacenc/src/quantize.c
new file mode 100644
index 0000000..205f167
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/quantize.c
@@ -0,0 +1,445 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		quantize.c

+

+	Content:	quantization functions

+

+*******************************************************************************/
+
+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"
+#include "quantize.h"
+#include "aac_rom.h"
+
+#define MANT_DIGITS 9
+#define MANT_SIZE   (1<<MANT_DIGITS)
+
+static const Word32 XROUND = 0x33e425af; /* final rounding constant (-0.0946f+ 0.5f) */
+
+
+/*****************************************************************************
+*
+* function name:pow34 
+* description: calculate $x^{\frac{3}{4}}, for 0.5 < x < 1.0$.  
+*
+*****************************************************************************/
+__inline Word32 pow34(Word32 x)
+{
+  /* index table using MANT_DIGITS bits, but mask out the sign bit and the MSB
+     which is always one */   
+  return mTab_3_4[(x >> (INT_BITS-2-MANT_DIGITS)) & (MANT_SIZE-1)];
+}
+
+
+/*****************************************************************************
+*
+* function name:quantizeSingleLine 
+* description: quantizes spectrum  
+*              quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)    
+*
+*****************************************************************************/
+static Word16 quantizeSingleLine(const Word16 gain, const Word32 absSpectrum)
+{
+  Word32 e, minusFinalExp, finalShift;
+  Word32 x;
+  Word16 qua = 0;                        
+
+   
+  if (absSpectrum) {
+    e = norm_l(absSpectrum);
+    x = pow34(absSpectrum << e);
+
+    /* calculate the final fractional exponent times 16 (was 3*(4*e + gain) + (INT_BITS-1)*16) */
+    minusFinalExp = (e << 2) + gain;
+    minusFinalExp = (minusFinalExp << 1) + minusFinalExp;
+    minusFinalExp = minusFinalExp + ((INT_BITS-1) << 4);
+
+    /* separate the exponent into a shift, and a multiply */
+    finalShift = minusFinalExp >> 4;
+     
+    if (finalShift < INT_BITS) {
+      x = L_mpy_wx(x, pow2tominusNover16[minusFinalExp & 15]);
+
+      x += XROUND >> (INT_BITS - finalShift);
+
+      /* shift and quantize */

+	  finalShift--;

+

+	  if(finalShift >= 0)

+		  x >>= finalShift;

+	  else

+		  x <<= (-finalShift);

+		

+	  qua = saturate(x);
+    }
+  }
+
+  return qua;
+}
+
+/*****************************************************************************
+*
+* function name:quantizeLines 
+* description: quantizes spectrum lines  
+*              quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)    
+*  input: global gain, number of lines to process, spectral data         
+*  output: quantized spectrum
+*
+*****************************************************************************/
+static void quantizeLines(const Word16 gain,
+                          const Word16 noOfLines,
+                          const Word32 *mdctSpectrum,
+                          Word16 *quaSpectrum)
+{
+  Word32 line;
+  Word32 m = gain&3;
+  Word32 g = (gain >> 2) + 4;

+  Word32 mdctSpeL;

+  Word16 *pquat;
+    /* gain&3 */

+

+  pquat = quantBorders[m];

+

+  g += 16;

+  

+  if(g >= 0)

+  {

+	for (line=0; line<noOfLines; line++) {
+	  Word32 qua;
+	  qua = 0;                                                     
+    

+	  mdctSpeL = mdctSpectrum[line];

+	
+	  if (mdctSpeL) {
+		Word32 sa;
+		Word32 saShft;
+
+        sa = L_abs(mdctSpeL);
+        //saShft = L_shr(sa, 16 + g);

+	    saShft = sa >> g;
+
+        if (saShft > pquat[0]) {
+         
+          if (saShft < pquat[1]) {
+             
+            qua = mdctSpeL>0 ? 1 : -1;
+		  }
+          else {
+           
+            if (saShft < pquat[2]) {
+               
+              qua = mdctSpeL>0 ? 2 : -2;
+			}
+            else {
+             
+              if (saShft < pquat[3]) {
+                 
+                qua = mdctSpeL>0 ? 3 : -3;
+			  }
+              else {
+                qua = quantizeSingleLine(gain, sa);
+                /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
+               
+                if (mdctSpeL < 0)
+                  qua = -qua;
+			  }
+			}
+		  }
+		}
+	  }
+      quaSpectrum[line] = qua ;                                    
+	}

+  }

+  else

+  {

+	for (line=0; line<noOfLines; line++) {

+	  Word32 qua;

+	  qua = 0;                                                     

+    

+	  mdctSpeL = mdctSpectrum[line];

+	

+	  if (mdctSpeL) {

+		Word32 sa;

+		Word32 saShft;

+

+        sa = L_abs(mdctSpeL);

+        saShft = sa << g;

+

+        if (saShft > pquat[0]) {

+         

+          if (saShft < pquat[1]) {

+             

+            qua = mdctSpeL>0 ? 1 : -1;

+		  }

+          else {

+           

+            if (saShft < pquat[2]) {

+               

+              qua = mdctSpeL>0 ? 2 : -2;

+			}

+            else {

+             

+              if (saShft < pquat[3]) {

+                 

+                qua = mdctSpeL>0 ? 3 : -3;

+			  }

+              else {

+                qua = quantizeSingleLine(gain, sa);

+                /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */

+               

+                if (mdctSpeL < 0)

+                  qua = -qua;

+			  }

+			}

+		  }

+		}

+	  }

+      quaSpectrum[line] = qua ;                                    

+	}	  

+  }
+
+}
+
+
+/*****************************************************************************
+*
+* function name:iquantizeLines 
+* description: iquantizes spectrum lines without sign
+*              mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain) 
+* input: global gain, number of lines to process,quantized spectrum        
+* output: spectral data
+*
+*****************************************************************************/
+static void iquantizeLines(const Word16 gain,
+                           const Word16 noOfLines,
+                           const Word16 *quantSpectrum,
+                           Word32 *mdctSpectrum)
+{
+  Word32   iquantizermod;
+  Word32   iquantizershift;
+  Word32   line;
+
+  iquantizermod = gain & 3;                              
+  iquantizershift = gain >> 2;
+
+  for (line=0; line<noOfLines; line++) {
+     
+    if( quantSpectrum[line] != 0 ) {
+      Word32 accu;
+      Word32 ex;
+	  Word32 tabIndex;
+      Word32 specExp;
+      Word32 s,t;
+
+      accu = quantSpectrum[line];
+
+      ex = norm_l(accu);
+      accu = accu << ex;
+      specExp = INT_BITS-1 - ex;
+
+      tabIndex = (accu >> (INT_BITS-2-MANT_DIGITS)) & (~MANT_SIZE);        
+
+      /* calculate "mantissa" ^4/3 */
+      s = mTab_4_3[tabIndex];                                                    
+
+      /* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */
+      t = specExpMantTableComb_enc[iquantizermod][specExp];                      
+
+      /* multiply "mantissa" ^4/3 with exponent multiplier */
+      accu = MULHIGH(s, t);
+
+      /* get approperiate exponent shifter */
+      specExp = specExpTableComb_enc[iquantizermod][specExp];                    
+
+      specExp += iquantizershift + 1;

+	  if(specExp >= 0)

+		  mdctSpectrum[line] = accu << specExp;

+	  else

+		  mdctSpectrum[line] = accu >> (-specExp);
+    }
+    else {
+      mdctSpectrum[line] = 0;                                                    
+    }
+  }
+}
+
+/*****************************************************************************
+*
+* function name: QuantizeSpectrum
+* description: quantizes the entire spectrum
+* returns:
+* input: number of scalefactor bands to be quantized, ...
+* output: quantized spectrum
+*
+*****************************************************************************/
+void QuantizeSpectrum(Word16 sfbCnt,
+                      Word16 maxSfbPerGroup,
+                      Word16 sfbPerGroup,
+                      Word16 *sfbOffset,
+                      Word32 *mdctSpectrum,
+                      Word16 globalGain,
+                      Word16 *scalefactors,
+                      Word16 *quantizedSpectrum)
+{
+  Word32 sfbOffs, sfb;
+
+  for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) {
+    Word32 sfbNext ;
+    for (sfb = 0; sfb < maxSfbPerGroup; sfb = sfbNext) {
+      Word16 scalefactor = scalefactors[sfbOffs+sfb];                          
+      /* coalesce sfbs with the same scalefactor */
+      for (sfbNext = sfb+1;
+           sfbNext < maxSfbPerGroup && scalefactor == scalefactors[sfbOffs+sfbNext];
+           sfbNext++) ;
+
+      quantizeLines(globalGain - scalefactor,
+                    sfbOffset[sfbOffs+sfbNext] - sfbOffset[sfbOffs+sfb],
+                    mdctSpectrum + sfbOffset[sfbOffs+sfb],
+                    quantizedSpectrum + sfbOffset[sfbOffs+sfb]);
+    }
+  }
+}
+
+
+/*****************************************************************************
+*
+* function name:calcSfbDist 
+* description: quantizes and requantizes lines to calculate distortion
+* input:  number of lines to be quantized, ...
+* output: distortion
+*
+*****************************************************************************/
+Word32 calcSfbDist(const Word32 *spec,
+                   Word16  sfbWidth,
+                   Word16  gain)
+{
+  Word32 line;
+  Word32 dist;
+  Word32 m = gain&3;
+  Word32 g = (gain >> 2) + 4;

+  Word32 g2 = (g << 1) + 1;

+  Word16 *pquat, *repquat;

+    /* gain&3 */
+

+  pquat = quantBorders[m];

+  repquat = quantRecon[m];
+	

+  dist = 0;  

+  g += 16;

+  if(g2 < 0 && g >= 0)

+  {	  
+	  g2 = -g2;

+	  for(line=0; line<sfbWidth; line++) {		  
+		  if (spec[line]) {			  
+			  Word32 diff;
+			  Word32 distSingle;
+			  Word32 sa;
+			  Word32 saShft;
+			  sa = L_abs(spec[line]);
+			  //saShft = round16(L_shr(sa, g));
+			  //saShft = L_shr(sa, 16+g);

+			  saShft = sa >> g;

+
+			  if (saShft < pquat[0]) {

+				  distSingle = (saShft * saShft) >> g2;

+			  }

+			  else {

+				  

+				  if (saShft < pquat[1]) {

+					  diff = saShft - repquat[0];

+					  distSingle = (diff * diff) >> g2;

+				  }

+				  else {

+					  

+					  if (saShft < pquat[2]) {

+						  diff = saShft - repquat[1];

+						  distSingle = (diff * diff) >> g2;

+					  }

+					  else {

+						  

+						  if (saShft < pquat[3]) {

+							  diff = saShft - repquat[2];

+							  distSingle = (diff * diff) >> g2;

+						  }

+						  else {

+							  Word16 qua = quantizeSingleLine(gain, sa);

+							  Word32 iqval, diff32;

+							  /* now that we have quantized x, re-quantize it. */

+							  iquantizeLines(gain, 1, &qua, &iqval);

+							  diff32 = sa - iqval;

+							  distSingle = fixmul(diff32, diff32);

+						  }

+					  }

+				  }

+			  }

+			  

+			  dist = L_add(dist, distSingle);

+		  }
+	  }

+  }

+  else

+  {

+	  for(line=0; line<sfbWidth; line++) {		  

+		  if (spec[line]) {			  

+			  Word32 diff;

+			  Word32 distSingle;

+			  Word32 sa;

+			  Word32 saShft;

+			  sa = L_abs(spec[line]);

+			  //saShft = round16(L_shr(sa, g));

+			  saShft = L_shr(sa, g);

+

+			  if (saShft < pquat[0]) {

+				  distSingle = L_shl((saShft * saShft), g2);

+			  }

+			  else {

+				  

+				  if (saShft < pquat[1]) {

+					  diff = saShft - repquat[0];

+					  distSingle = L_shl((diff * diff), g2);

+				  }

+				  else {

+					  

+					  if (saShft < pquat[2]) {

+						  diff = saShft - repquat[1];

+						  distSingle = L_shl((diff * diff), g2);

+					  }

+					  else {

+						  

+						  if (saShft < pquat[3]) {

+							  diff = saShft - repquat[2];

+							  distSingle = L_shl((diff * diff), g2);

+						  }

+						  else {

+							  Word16 qua = quantizeSingleLine(gain, sa);

+							  Word32 iqval, diff32;

+							  /* now that we have quantized x, re-quantize it. */

+							  iquantizeLines(gain, 1, &qua, &iqval);

+							  diff32 = sa - iqval;

+							  distSingle = fixmul(diff32, diff32);

+						  }

+					  }

+				  }

+			  }

+			  dist = L_add(dist, distSingle);

+		  }

+	  }	  

+  }
+
+  return dist;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/sf_estim.c b/media/libstagefright/codecs/aacenc/src/sf_estim.c
new file mode 100644
index 0000000..d34b365
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/sf_estim.c
@@ -0,0 +1,882 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		sf_estim.c

+

+	Content:	Scale factor estimation functions

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "oper_32b.h"
+#include "sf_estim.h"
+#include "quantize.h"
+#include "bit_cnt.h"
+#include "aac_rom.h"
+
+static const Word16 MAX_SCF_DELTA = 60;
+
+/*!
+constants reference in comments 
+
+ C0 = 6.75f;
+ C1 = -69.33295f;   -16/3*log(MAX_QUANT+0.5-logCon)/log(2) 
+ C2 = 4.0f;
+ C3 = 2.66666666f;
+ 
+  PE_C1 = 3.0f;        log(8.0)/log(2) 
+  PE_C2 = 1.3219281f;  log(2.5)/log(2) 
+  PE_C3 = 0.5593573f;  1-C2/C1 
+  
+*/
+
+#define FF_SQRT_BITS                    7
+#define FF_SQRT_TABLE_SIZE              (1<<FF_SQRT_BITS - 1<<(FF_SQRT_BITS-2))
+#define COEF08_31		0x66666666		/* 0.8*(1 << 31) */

+#define PE_C1_8			24				/* PE_C1*8 */

+#define PE_C2_16		21				/* PE_C2*8/PE_C3 */

+#define PE_SCALE		0x059a			/* 0.7 * (1 << (15 - 1 - 3))*/

+

+#define SCALE_ESTIMATE_COEF	0x5555		/* (8.8585/(4*log2(10))) * (1 << 15)*/

+
+/*********************************************************************************
+*
+* function name: formfac_sqrt
+* description:  calculates sqrt(x)/256 
+*
+**********************************************************************************/
+__inline Word32 formfac_sqrt(Word32 x)
+{
+	Word32 y;
+	Word32 preshift, postshift;
+	
+	
+	if (x==0) return 0;
+	preshift  = norm_l(x) - (INT_BITS-1-FF_SQRT_BITS);
+	postshift = preshift >> 1;
+	preshift  = postshift << 1;
+	postshift = postshift + 8;	  /* sqrt/256 */
+	if(preshift >= 0)

+		y = x << preshift;        /* now 1/4 <= y < 1 */

+	else

+		y = x >> (-preshift);

+	y = formfac_sqrttable[y-32];

+	

+	if(postshift >= 0)

+		y = y >> postshift;

+	else

+		y = y << (-postshift);

+	

+	return y;
+}
+
+
+/*********************************************************************************
+*
+* function name: CalcFormFactorChannel
+* description:  calculate the form factor one channel
+*				ffac(n) = sqrt(abs(X(k)) + sqrt(abs(X(k+1)) + ....
+*
+**********************************************************************************/
+static void
+CalcFormFactorChannel(Word16 *logSfbFormFactor,
+                      Word16 *sfbNRelevantLines,
+                      Word16 *logSfbEnergy,
+                      PSY_OUT_CHANNEL *psyOutChan)
+{
+	Word32 sfbw, sfbw1;

+	Word32 i, j;
+	Word32 sfbOffs, sfb, shift;
+	

+	sfbw = sfbw1 = 0;

+	for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup){
+		for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+			i = sfbOffs+sfb;      
+			
+			if (psyOutChan->sfbEnergy[i] > psyOutChan->sfbThreshold[i]) {
+				Word32 accu, avgFormFactor,iSfbWidth;

+				Word32 *mdctSpec;
+				sfbw = psyOutChan->sfbOffsets[i+1] - psyOutChan->sfbOffsets[i];

+				iSfbWidth = invSBF[(sfbw >> 2) - 1];

+				mdctSpec = psyOutChan->mdctSpectrum + psyOutChan->sfbOffsets[i];
+				accu = 0;                                                                       
+				/* calc sum of sqrt(spec) */
+				for (j=sfbw; j; j--) {

+					accu += formfac_sqrt(L_abs(*mdctSpec)); mdctSpec++;

+				}
+				logSfbFormFactor[i] = iLog4(accu);
+				logSfbEnergy[i] = iLog4(psyOutChan->sfbEnergy[i]);
+				avgFormFactor = fixmul(rsqrt(psyOutChan->sfbEnergy[i],INT_BITS), iSfbWidth);
+				avgFormFactor = rsqrt((Word32)avgFormFactor,INT_BITS) >> 10;
+				/* result is multiplied by 4 */
+				if(avgFormFactor)
+					sfbNRelevantLines[i] = accu / avgFormFactor;
+				else
+					sfbNRelevantLines[i] = 0x7fff;
+			}
+			else {
+				/* set number of lines to zero */
+				sfbNRelevantLines[i] = 0;                                                       
+			}
+		}
+	}
+}
+
+/*********************************************************************************
+*
+* function name: improveScf
+* description:  find better scalefactor with analysis by synthesis
+*
+**********************************************************************************/
+static Word16 improveScf(Word32 *spec, 
+                         Word16  sfbWidth, 
+                         Word32  thresh, 
+                         Word16  scf,
+                         Word16  minScf,
+                         Word32 *dist, 
+                         Word16 *minScfCalculated)
+{
+	Word32 cnt;
+	Word32 sfbDist;
+	Word32 scfBest;
+	Word32 thresh125 = L_add(thresh, (thresh >> 2));
+	
+	scfBest = scf;                                                       
+	
+	/* calc real distortion */
+	sfbDist = calcSfbDist(spec, sfbWidth, scf);
+	*minScfCalculated = scf;     

+	if(!sfbDist)

+	  return scfBest;
+	
+	if (sfbDist > thresh125) {
+		Word32 scfEstimated;
+		Word32 sfbDistBest;
+		scfEstimated = scf;                                               
+		sfbDistBest = sfbDist;                                            
+		
+		cnt = 0;                                                          
+		while (sfbDist > thresh125 && (cnt < 3)) {
+			
+			scf = scf + 1;
+			sfbDist = calcSfbDist(spec, sfbWidth, scf);
+			
+			if (sfbDist < sfbDistBest) {
+				scfBest = scf;                                              
+				sfbDistBest = sfbDist;                                      
+			}
+			cnt = cnt + 1;
+		}
+		cnt = 0;                                                          
+		scf = scfEstimated;                                               
+		sfbDist = sfbDistBest;                                            
+		while ((sfbDist > thresh125) && (cnt < 1) && (scf > minScf)) {
+			
+			scf = scf - 1;
+			sfbDist = calcSfbDist(spec, sfbWidth, scf);
+			
+			if (sfbDist < sfbDistBest) {
+				scfBest = scf;                                              
+				sfbDistBest = sfbDist;                                      
+			}
+			*minScfCalculated = scf;                                       
+			cnt = cnt + 1;
+		}

+		*dist = sfbDistBest;                                              
+	}
+	else {
+		Word32 sfbDistBest; 
+		Word32 sfbDistAllowed;
+		Word32 thresh08 = fixmul(COEF08_31, thresh);
+		sfbDistBest = sfbDist;                                            
+		
+		if (sfbDist < thresh08)
+			sfbDistAllowed = sfbDist;
+		else
+			sfbDistAllowed = thresh08;
+		for (cnt=0; cnt<3; cnt++) {
+			scf = scf + 1;
+			sfbDist = calcSfbDist(spec, sfbWidth, scf);
+			
+			if (fixmul(COEF08_31,sfbDist) < sfbDistAllowed) {
+				*minScfCalculated = scfBest + 1;
+				scfBest = scf;                                              
+				sfbDistBest = sfbDist;                                      
+			}
+		}
+		*dist = sfbDistBest;                                              
+	}
+	
+	/* return best scalefactor */
+	return scfBest;
+}
+
+/*********************************************************************************
+*
+* function name: countSingleScfBits
+* description:  count single scf bits in huffum
+*
+**********************************************************************************/
+static Word16 countSingleScfBits(Word16 scf, Word16 scfLeft, Word16 scfRight)
+{
+	Word16 scfBits;
+	
+	scfBits = bitCountScalefactorDelta(scfLeft - scf) +
+		bitCountScalefactorDelta(scf - scfRight);
+	
+	return scfBits;
+}
+
+/*********************************************************************************
+*
+* function name: calcSingleSpecPe
+* description:  ldRatio = log2(en(n)) - 0,375*scfGain(n)
+*				nbits = 0.7*nLines*ldRation for ldRation >= c1
+*				nbits = 0.7*nLines*(c2 + c3*ldRatio) for ldRation < c1 
+*
+**********************************************************************************/
+static Word16 calcSingleSpecPe(Word16 scf, Word16 sfbConstPePart, Word16 nLines)
+{
+	Word32 specPe;
+	Word32 ldRatio;
+	Word32 scf3;
+	
+	ldRatio = sfbConstPePart << 3; /*  (sfbConstPePart -0.375*scf)*8 */
+	scf3 = scf + scf + scf;
+	ldRatio = ldRatio - scf3;
+    
+	if (ldRatio < PE_C1_8) {
+		/* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/ 
+		ldRatio = (ldRatio + PE_C2_16) >> 1;
+	}
+	specPe = nLines * ldRatio;
+	specPe = (specPe * PE_SCALE) >> 14;
+	
+	return saturate(specPe);
+}
+
+
+/*********************************************************************************
+*
+* function name: countScfBitsDiff
+* description:  count different scf bits used
+*
+**********************************************************************************/
+static Word16 countScfBitsDiff(Word16 *scfOld, Word16 *scfNew, 
+                               Word16 sfbCnt, Word16 startSfb, Word16 stopSfb)
+{
+	Word32 scfBitsDiff;
+	Word32 sfb, sfbLast;
+	Word32 sfbPrev, sfbNext;
+	
+	scfBitsDiff = 0;                                                      
+	sfb = 0;                                                              
+	
+	/* search for first relevant sfb */
+	sfbLast = startSfb;                                                   
+	while (sfbLast < stopSfb && scfOld[sfbLast] == VOAAC_SHRT_MIN) {
+		
+		sfbLast = sfbLast + 1;
+	}
+	/* search for previous relevant sfb and count diff */
+	sfbPrev = startSfb - 1;
+	while ((sfbPrev>=0) && scfOld[sfbPrev] == VOAAC_SHRT_MIN) {
+		
+		sfbPrev = sfbPrev - 1;
+	}
+	
+	if (sfbPrev>=0) {
+		scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbPrev] - scfNew[sfbLast]) -
+			bitCountScalefactorDelta(scfOld[sfbPrev] - scfOld[sfbLast]);
+	}
+	/* now loop through all sfbs and count diffs of relevant sfbs */
+	for (sfb=sfbLast+1; sfb<stopSfb; sfb++) {
+		
+		if (scfOld[sfb] != VOAAC_SHRT_MIN) {
+			scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfb]) -
+				bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfb]);
+			sfbLast = sfb;                                                    
+		}
+	}
+	/* search for next relevant sfb and count diff */
+	sfbNext = stopSfb;                                                    
+	while (sfbNext < sfbCnt && scfOld[sfbNext] == VOAAC_SHRT_MIN) {
+		
+		sfbNext = sfbNext + 1;
+	}
+	
+	if (sfbNext < sfbCnt)
+		scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfbNext]) -
+		bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfbNext]);
+	
+	return saturate(scfBitsDiff);
+}
+
+static Word16 calcSpecPeDiff(Word16 *scfOld,
+                             Word16 *scfNew,
+                             Word16 *sfbConstPePart,
+                             Word16 *logSfbEnergy,
+                             Word16 *logSfbFormFactor,
+                             Word16 *sfbNRelevantLines,
+                             Word16 startSfb, 
+                             Word16 stopSfb)
+{
+	Word32 specPeDiff;
+	Word32 sfb;
+	
+	specPeDiff = 0;                                                       
+	
+	/* loop through all sfbs and count pe difference */
+	for (sfb=startSfb; sfb<stopSfb; sfb++) {
+		
+		
+		if (scfOld[sfb] != VOAAC_SHRT_MIN) {
+			Word32 ldRatioOld, ldRatioNew;
+			Word32 scf3;
+			
+			
+			if (sfbConstPePart[sfb] == MIN_16) {
+				sfbConstPePart[sfb] = ((logSfbEnergy[sfb] -
+					logSfbFormFactor[sfb]) + 11-8*4+3) >> 2;
+			}
+			
+			
+			ldRatioOld = sfbConstPePart[sfb] << 3;
+			scf3 = scfOld[sfb] + scfOld[sfb] + scfOld[sfb];
+			ldRatioOld = ldRatioOld - scf3;
+			ldRatioNew = sfbConstPePart[sfb] << 3;
+			scf3 = scfNew[sfb] + scfNew[sfb] + scfNew[sfb];
+			ldRatioNew = ldRatioNew - scf3;
+			
+			if (ldRatioOld < PE_C1_8) {
+				/* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/
+				ldRatioOld = (ldRatioOld + PE_C2_16) >> 1;
+			}
+			
+			if (ldRatioNew < PE_C1_8) {
+				/* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/
+				ldRatioNew = (ldRatioNew + PE_C2_16) >> 1;
+			}
+			
+			specPeDiff +=  sfbNRelevantLines[sfb] * (ldRatioNew - ldRatioOld);
+		}
+	}
+	
+	specPeDiff = (specPeDiff * PE_SCALE) >> 14;
+	
+	return saturate(specPeDiff);
+}
+
+
+/*********************************************************************************
+*
+* function name: assimilateSingleScf
+* description:  searched for single scalefactor bands, where the number of bits gained
+*				by using a smaller scfgain(n) is greater than the estimated increased
+*				bit demand
+*
+**********************************************************************************/
+static void assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan,
+                                Word16 *scf, 
+                                Word16 *minScf,
+                                Word32 *sfbDist, 
+                                Word16 *sfbConstPePart,
+                                Word16 *logSfbEnergy,
+                                Word16 *logSfbFormFactor,
+                                Word16 *sfbNRelevantLines,
+                                Word16 *minScfCalculated,
+                                Flag    restartOnSuccess)
+{
+	Word32 sfbLast, sfbAct, sfbNext, scfAct, scfMin;
+	Word16 *scfLast, *scfNext;
+	Word32 sfbPeOld, sfbPeNew;
+	Word32 sfbDistNew;
+	Word32 j;
+	Flag   success;
+	Word16 deltaPe, deltaPeNew, deltaPeTmp;
+	Word16 *prevScfLast = psyOutChan->prevScfLast;
+	Word16 *prevScfNext = psyOutChan->prevScfNext;
+	Word16 *deltaPeLast = psyOutChan->deltaPeLast;
+	Flag   updateMinScfCalculated;
+	
+	success = 0;                                                                  
+	deltaPe = 0;                                                                  
+	
+	for(j=0;j<psyOutChan->sfbCnt;j++){
+		prevScfLast[j] = MAX_16;                                                    
+		prevScfNext[j] = MAX_16;                                                    
+		deltaPeLast[j] = MAX_16;                                                    
+	}

+	
+	sfbLast = -1;                                                                 
+	sfbAct = -1;                                                                  
+	sfbNext = -1;                                                                 
+	scfLast = 0;
+	scfNext = 0;
+	scfMin = MAX_16;                                                              
+	do {
+		/* search for new relevant sfb */
+		sfbNext = sfbNext + 1;
+		while (sfbNext < psyOutChan->sfbCnt && scf[sfbNext] == MIN_16) {
+			
+			sfbNext = sfbNext + 1;
+		}
+		
+		if ((sfbLast>=0) && (sfbAct>=0) && sfbNext < psyOutChan->sfbCnt) {
+			/* relevant scfs to the left and to the right */
+			scfAct  = scf[sfbAct];                                                    
+			scfLast = scf + sfbLast;
+			scfNext = scf + sfbNext;
+			scfMin  = min(*scfLast, *scfNext);
+		}
+		else {
+			
+			if (sfbLast == -1 && (sfbAct>=0) && sfbNext < psyOutChan->sfbCnt) {
+				/* first relevant scf */
+				scfAct  = scf[sfbAct];                                                  
+				scfLast = &scfAct;
+				scfNext = scf + sfbNext;
+				scfMin  = *scfNext;                                                     
+			}
+			else {
+				
+				if ((sfbLast>=0) && (sfbAct>=0) && sfbNext == psyOutChan->sfbCnt) {
+					/* last relevant scf */
+					scfAct  = scf[sfbAct];                                                
+					scfLast = scf + sfbLast;
+					scfNext = &scfAct;
+					scfMin  = *scfLast;                                                   
+				}
+			}
+		}
+		
+		if (sfbAct>=0)
+			scfMin = max(scfMin, minScf[sfbAct]);
+		
+		if ((sfbAct >= 0) && 
+			(sfbLast>=0 || sfbNext < psyOutChan->sfbCnt) && 
+			scfAct > scfMin && 
+			(*scfLast != prevScfLast[sfbAct] || 
+			*scfNext != prevScfNext[sfbAct] || 
+			deltaPe < deltaPeLast[sfbAct])) {
+			success = 0;                                                              
+			
+			/* estimate required bits for actual scf */			
+			if (sfbConstPePart[sfbAct] == MIN_16) {
+				sfbConstPePart[sfbAct] = logSfbEnergy[sfbAct] -
+					logSfbFormFactor[sfbAct] + 11-8*4; /* 4*log2(6.75) - 32 */
+				
+				if (sfbConstPePart[sfbAct] < 0)
+					sfbConstPePart[sfbAct] = sfbConstPePart[sfbAct] + 3;
+				sfbConstPePart[sfbAct] = sfbConstPePart[sfbAct] >> 2;
+			}
+			
+			sfbPeOld = calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], sfbNRelevantLines[sfbAct]) +
+				countSingleScfBits(scfAct, *scfLast, *scfNext);
+			deltaPeNew = deltaPe;                                                     
+			updateMinScfCalculated = 1;                                               
+			do {
+				scfAct = scfAct - 1;
+				/* check only if the same check was not done before */
+				
+				if (scfAct < minScfCalculated[sfbAct]) {
+					sfbPeNew = calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], sfbNRelevantLines[sfbAct]) +
+						countSingleScfBits(scfAct, *scfLast, *scfNext);
+					/* use new scf if no increase in pe and 
+					quantization error is smaller */
+					deltaPeTmp = deltaPe + sfbPeNew - sfbPeOld;
+					
+					if (deltaPeTmp < 10) {
+						sfbDistNew = calcSfbDist(psyOutChan->mdctSpectrum+
+							psyOutChan->sfbOffsets[sfbAct],
+							(psyOutChan->sfbOffsets[sfbAct+1] - psyOutChan->sfbOffsets[sfbAct]),
+							scfAct);
+						if (sfbDistNew < sfbDist[sfbAct]) {
+							/* success, replace scf by new one */
+							scf[sfbAct] = scfAct;                                     
+							sfbDist[sfbAct] = sfbDistNew;                             
+							deltaPeNew = deltaPeTmp;                                  
+							success = 1;                                              
+						}
+						/* mark as already checked */
+						
+						if (updateMinScfCalculated) {
+							minScfCalculated[sfbAct] = scfAct;                        
+						}
+					}
+					else {
+						updateMinScfCalculated = 0;                                 
+					}
+				}
+				
+			} while (scfAct > scfMin);
+			deltaPe = deltaPeNew;                                             
+			/* save parameters to avoid multiple computations of the same sfb */
+			prevScfLast[sfbAct] = *scfLast;                                   
+			prevScfNext[sfbAct] = *scfNext;                                   
+			deltaPeLast[sfbAct] = deltaPe;                                    
+		}
+		
+		if (success && restartOnSuccess) {
+			/* start again at first sfb */
+			sfbLast = -1;                                                     
+			sfbAct  = -1;                                                     
+			sfbNext = -1;                                                     
+			scfLast = 0;
+			scfNext = 0;
+			scfMin  = MAX_16;                                                 
+			success = 0;                                                      
+		}
+		else {
+			/* shift sfbs for next band */
+			sfbLast = sfbAct;                                                 
+			sfbAct  = sfbNext;                                                
+		}
+		
+  } while (sfbNext < psyOutChan->sfbCnt);
+}
+
+
+/*********************************************************************************
+*
+* function name: assimilateMultipleScf
+* description:  scalefactor difference reduction
+*
+**********************************************************************************/
+static void assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan,
+                                  Word16 *scf, 
+                                  Word16 *minScf,
+                                  Word32 *sfbDist, 
+                                  Word16 *sfbConstPePart,
+                                  Word16 *logSfbEnergy,
+                                  Word16 *logSfbFormFactor,
+                                  Word16 *sfbNRelevantLines)
+{
+	Word32 sfb, startSfb, stopSfb, scfMin, scfMax, scfAct;
+	Flag   possibleRegionFound;
+	Word32 deltaScfBits;
+	Word32 deltaSpecPe;
+	Word32 deltaPe, deltaPeNew;
+	Word32 sfbCnt;
+	Word32 *sfbDistNew = psyOutChan->sfbDistNew;
+	Word16 *scfTmp = psyOutChan->prevScfLast;
+
+	deltaPe = 0;                                                          
+	sfbCnt = psyOutChan->sfbCnt;                                          
+	
+	/* calc min and max scalfactors */
+	scfMin = MAX_16;                                                      
+	scfMax = MIN_16;                                                      
+	for (sfb=0; sfb<sfbCnt; sfb++) {
+		
+		if (scf[sfb] != MIN_16) {
+			scfMin = min(scfMin, scf[sfb]);
+			scfMax = max(scfMax, scf[sfb]);
+		}
+	}
+	
+	if (scfMax !=  MIN_16) {
+		
+		scfAct = scfMax;                                             
+		
+		do {
+			scfAct = scfAct - 1;
+			for (sfb=0; sfb<sfbCnt; sfb++) {
+				scfTmp[sfb] = scf[sfb];                                         
+			}
+			stopSfb = 0;                                                      
+			do {
+				sfb = stopSfb;                                                  
+				
+				while (sfb < sfbCnt && (scf[sfb] == MIN_16 || scf[sfb] <= scfAct)) {
+					sfb = sfb + 1;
+				}
+				startSfb = sfb;                                                 
+				sfb = sfb + 1;
+				
+				while (sfb < sfbCnt && (scf[sfb] == MIN_16 || scf[sfb] > scfAct)) {
+					sfb = sfb + 1;
+				}
+				stopSfb = sfb;                                                  
+				
+				possibleRegionFound = 0;                                        
+				
+				if (startSfb < sfbCnt) {
+					possibleRegionFound = 1;                                      
+					for (sfb=startSfb; sfb<stopSfb; sfb++) {
+						
+						if (scf[sfb]!=MIN_16) {
+							
+							if (scfAct < minScf[sfb]) {
+								possibleRegionFound = 0;                                
+								break;
+							}
+						}
+					}
+				}
+				
+				
+				if (possibleRegionFound) { /* region found */
+					
+					/* replace scfs in region by scfAct */
+					for (sfb=startSfb; sfb<stopSfb; sfb++) {
+						
+						if (scfTmp[sfb]!=MIN_16)
+							scfTmp[sfb] = scfAct;                                     
+					}
+					
+					/* estimate change in bit demand for new scfs */
+					deltaScfBits = countScfBitsDiff(scf,scfTmp,sfbCnt,startSfb,stopSfb);
+					deltaSpecPe = calcSpecPeDiff(scf, scfTmp, sfbConstPePart,
+						logSfbEnergy, logSfbFormFactor, sfbNRelevantLines, 
+						startSfb, stopSfb);
+					deltaPeNew = deltaPe + deltaScfBits + deltaSpecPe;
+					
+					
+					if (deltaPeNew < 10) {
+						Word32 distOldSum, distNewSum;
+						
+						/* quantize and calc sum of new distortion */
+						distOldSum = 0;                                                     
+						distNewSum = 0;                                                     
+						for (sfb=startSfb; sfb<stopSfb; sfb++) {
+							
+							if (scfTmp[sfb] != MIN_16) {
+								distOldSum = L_add(distOldSum, sfbDist[sfb]);
+								
+								sfbDistNew[sfb] = calcSfbDist(psyOutChan->mdctSpectrum +
+									psyOutChan->sfbOffsets[sfb], 
+									(psyOutChan->sfbOffsets[sfb+1] - psyOutChan->sfbOffsets[sfb]),
+									scfAct);
+								
+								
+								if (sfbDistNew[sfb] > psyOutChan->sfbThreshold[sfb]) {
+									distNewSum = distOldSum << 1;
+									break;
+								}
+								distNewSum = L_add(distNewSum, sfbDistNew[sfb]);
+							}
+						}
+						
+						if (distNewSum < distOldSum) {
+							deltaPe = deltaPeNew;                                             
+							for (sfb=startSfb; sfb<stopSfb; sfb++) {
+								
+								if (scf[sfb]!=MIN_16) {
+									scf[sfb] = scfAct;                                            
+									sfbDist[sfb] = sfbDistNew[sfb];                               
+								}
+							}
+						}
+					}
+				}        
+			} while (stopSfb <= sfbCnt);      
+		} while (scfAct > scfMin);
+	}
+}
+
+/*********************************************************************************
+*
+* function name: EstimateScaleFactorsChannel
+* description:  estimate scale factors for one channel
+*
+**********************************************************************************/
+static void
+EstimateScaleFactorsChannel(PSY_OUT_CHANNEL *psyOutChan,
+                            Word16          *scf,
+                            Word16          *globalGain,
+                            Word16          *logSfbEnergy,
+                            Word16          *logSfbFormFactor,
+                            Word16          *sfbNRelevantLines)
+{
+	Word32 i, j;
+	Word32 thresh, energy;
+	Word32 energyPart, thresholdPart;
+	Word32 scfInt, minScf, maxScf, maxAllowedScf, lastSf;
+	Word32 maxSpec;
+	Word32 *sfbDist = psyOutChan->sfbDist;
+	Word16 *minSfMaxQuant = psyOutChan->minSfMaxQuant;
+	Word16 *minScfCalculated = psyOutChan->minScfCalculated;
+	
+	
+	for (i=0; i<psyOutChan->sfbCnt; i++) {
+		Word32 sbfwith, sbfStart;

+		Word32 *mdctSpec;
+		thresh = psyOutChan->sfbThreshold[i];                                       
+		energy = psyOutChan->sfbEnergy[i];                                          
+		

+		sbfStart = psyOutChan->sfbOffsets[i];

+		sbfwith = psyOutChan->sfbOffsets[i+1] - sbfStart;

+		mdctSpec = psyOutChan->mdctSpectrum+sbfStart;

+		
+		maxSpec = 0;                                                                
+		/* maximum of spectrum */
+		for (j=sbfwith; j; j-- ) {

+			Word32 absSpec = L_abs(*mdctSpec); mdctSpec++;

+			maxSpec |= absSpec;                                                       

+		}
+		
+		/* scfs without energy or with thresh>energy are marked with MIN_16 */
+		scf[i] = MIN_16;                                                            
+		minSfMaxQuant[i] = MIN_16;    
+		
+		if ((maxSpec > 0) && (energy > thresh)) {
+			
+			energyPart = logSfbFormFactor[i];                                         
+			thresholdPart = iLog4(thresh);  
+			/* -20 = 4*log2(6.75) - 32 */

+			scfInt = ((thresholdPart - energyPart - 20) * SCALE_ESTIMATE_COEF) >> 15;
+			
+			minSfMaxQuant[i] = iLog4(maxSpec) - 68; /* 68  -16/3*log(MAX_QUANT+0.5-logCon)/log(2) + 1 */
+			
+			
+			if (minSfMaxQuant[i] > scfInt) {
+				scfInt = minSfMaxQuant[i];                                              
+			}
+			
+			/* find better scalefactor with analysis by synthesis */
+			scfInt = improveScf(psyOutChan->mdctSpectrum+sbfStart,

+				sbfwith,

+				thresh, scfInt, minSfMaxQuant[i], 

+				&sfbDist[i], &minScfCalculated[i]);
+			
+			scf[i] = scfInt;                                                          
+		}
+	}
+	
+	
+	/* scalefactor differece reduction  */
+	{
+		Word16 sfbConstPePart[MAX_GROUPED_SFB];
+		for(i=0;i<psyOutChan->sfbCnt;i++) {
+			sfbConstPePart[i] = MIN_16;                                               
+		}
+		
+		assimilateSingleScf(psyOutChan, scf, 
+			minSfMaxQuant, sfbDist, sfbConstPePart, logSfbEnergy,
+			logSfbFormFactor, sfbNRelevantLines, minScfCalculated, 1);
+		
+		assimilateMultipleScf(psyOutChan, scf, 
+			minSfMaxQuant, sfbDist, sfbConstPePart, logSfbEnergy,
+			logSfbFormFactor, sfbNRelevantLines);
+	}
+
+	/* get max scalefac for global gain */
+	maxScf = MIN_16;                                                              
+	minScf = MAX_16;                                                              
+	for (i=0; i<psyOutChan->sfbCnt; i++) {
+		
+		if (maxScf < scf[i]) {
+			maxScf = scf[i];                                                          
+		}
+		
+		if ((scf[i] != MIN_16) && (minScf > scf[i])) {
+			minScf = scf[i];                                                          
+		}
+	}
+	/* limit scf delta */
+	maxAllowedScf = minScf + MAX_SCF_DELTA;
+	for(i=0; i<psyOutChan->sfbCnt; i++) {
+		
+		if ((scf[i] != MIN_16) && (maxAllowedScf < scf[i])) {
+			scf[i] = maxAllowedScf;                                                   
+		}
+	}
+	/* new maxScf if any scf has been limited */
+	
+	if (maxAllowedScf < maxScf) {
+		maxScf = maxAllowedScf;                                                     
+	}
+	
+	/* calc loop scalefactors */
+	
+	if (maxScf > MIN_16) {
+		*globalGain = maxScf;                                                       
+		lastSf = 0;                                                                 
+		
+		for(i=0; i<psyOutChan->sfbCnt; i++) {
+			
+			if (scf[i] == MIN_16) {
+				scf[i] = lastSf;                                                        
+				/* set band explicitely to zero */
+				for (j=psyOutChan->sfbOffsets[i]; j<psyOutChan->sfbOffsets[i+1]; j++) {
+					psyOutChan->mdctSpectrum[j] = 0;                                      
+				}
+			}
+			else {
+				scf[i] = maxScf - scf[i];
+				lastSf = scf[i];                                                        
+			}
+		}
+	}
+	else{
+		*globalGain = 0;                                                            
+		/* set spectrum explicitely to zero */
+		for(i=0; i<psyOutChan->sfbCnt; i++) {
+			scf[i] = 0;                                                               
+			for (j=psyOutChan->sfbOffsets[i]; j<psyOutChan->sfbOffsets[i+1]; j++) {
+				psyOutChan->mdctSpectrum[j] = 0;                                        
+			}
+		}
+	}
+}
+
+/*********************************************************************************
+*
+* function name: CalcFormFactor
+* description:  estimate Form factors for all channel
+*
+**********************************************************************************/
+void
+CalcFormFactor(Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
+               Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+               Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+               PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+               const Word16 nChannels)
+{
+	Word16 j;
+	
+	for (j=0; j<nChannels; j++) {
+		CalcFormFactorChannel(logSfbFormFactor[j], sfbNRelevantLines[j], logSfbEnergy[j], &psyOutChannel[j]);
+	}
+}
+
+/*********************************************************************************
+*
+* function name: EstimateScaleFactors
+* description:  estimate scale factors for all channel
+*
+**********************************************************************************/
+void
+EstimateScaleFactors(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+                     QC_OUT_CHANNEL  qcOutChannel[MAX_CHANNELS],
+                     Word16          logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+                     Word16          logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
+                     Word16          sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+                     const Word16    nChannels)
+{
+	Word16 j;
+	
+	for (j=0; j<nChannels; j++) {
+		EstimateScaleFactorsChannel(&psyOutChannel[j],
+			qcOutChannel[j].scf,
+			&(qcOutChannel[j].globalGain),
+			logSfbEnergy[j],
+			logSfbFormFactor[j],
+			sfbNRelevantLines[j]);
+	}
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/spreading.c b/media/libstagefright/codecs/aacenc/src/spreading.c
new file mode 100644
index 0000000..e6fc7da
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/spreading.c
@@ -0,0 +1,52 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		spreading.c

+

+	Content:	Spreading of energy function

+

+*******************************************************************************/

+

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "spreading.h"

+

+/*********************************************************************************
+*
+* function name: SpreadingMax
+* description:  spreading the energy
+*				 higher frequencies thr(n) = max(thr(n), sh(n)*thr(n-1))
+*				 lower frequencies  thr(n) = max(thr(n), sl(n)*thr(n+1))
+*
+**********************************************************************************/

+void SpreadingMax(const Word16 pbCnt,

+                  const Word16 *maskLowFactor,

+                  const Word16 *maskHighFactor,

+                  Word32       *pbSpreadedEnergy)

+{

+  Word32 i;

+

+  /* slope to higher frequencies */

+  for (i=1; i<pbCnt; i++) {

+    pbSpreadedEnergy[i] = max(pbSpreadedEnergy[i],

+                                L_mpy_ls(pbSpreadedEnergy[i-1], maskHighFactor[i]));

+  }

+  /* slope to lower frequencies */

+  for (i=pbCnt - 2; i>=0; i--) {

+    pbSpreadedEnergy[i] = max(pbSpreadedEnergy[i],

+                                L_mpy_ls(pbSpreadedEnergy[i+1], maskLowFactor[i]));

+  }

+}

diff --git a/media/libstagefright/codecs/aacenc/src/stat_bits.c b/media/libstagefright/codecs/aacenc/src/stat_bits.c
new file mode 100644
index 0000000..556104e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/stat_bits.c
@@ -0,0 +1,237 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		stat_bits.c

+

+	Content:	Static bit counter functions

+

+*******************************************************************************/
+
+#include "stat_bits.h"
+#include "bitenc.h"
+#include "tns.h"
+
+
+typedef enum {
+  SI_ID_BITS                =(3),
+  SI_FILL_COUNT_BITS        =(4),
+  SI_FILL_ESC_COUNT_BITS    =(8),
+  SI_FILL_EXTENTION_BITS    =(4),
+  SI_FILL_NIBBLE_BITS       =(4),
+  SI_SCE_BITS               =(4),
+  SI_CPE_BITS               =(5),
+  SI_CPE_MS_MASK_BITS       =(2) ,
+  SI_ICS_INFO_BITS_LONG     =(1+2+1+6+1),
+  SI_ICS_INFO_BITS_SHORT    =(1+2+1+4+7),
+  SI_ICS_BITS               =(8+1+1+1)
+} SI_BITS;
+
+
+/*********************************************************************************
+*
+* function name: countMsMaskBits
+* description:   count ms stereo bits demand
+*
+**********************************************************************************/
+static Word16 countMsMaskBits(Word16   sfbCnt,
+                              Word16   sfbPerGroup,
+                              Word16   maxSfbPerGroup,
+                              struct TOOLSINFO *toolsInfo)
+{
+  Word16 msBits, sfbOff, sfb;
+  msBits = 0;                                            
+
+   
+  switch(toolsInfo->msDigest) {
+    case MS_NONE:
+    case MS_ALL:
+      break;
+
+    case MS_SOME:
+      for(sfbOff=0; sfbOff<sfbCnt; sfbOff+=sfbPerGroup)
+        for(sfb=0; sfb<maxSfbPerGroup; sfb++)
+          msBits += 1;
+      break;
+  }
+  return(msBits);
+}
+
+/*********************************************************************************
+*
+* function name: tnsCount
+* description:   count tns bit demand  core function
+*
+**********************************************************************************/
+static Word16 tnsCount(TNS_INFO *tnsInfo, Word16 blockType)
+{
+
+  Word32 i, k;
+  Flag tnsPresent;
+  Word32 numOfWindows;
+  Word32 count;
+  Word32 coefBits;

+  Word16 *ptcoef;
+
+  count = 0;       

+  
+  if (blockType == 2)
+    numOfWindows = 8;
+  else
+    numOfWindows = 1;
+  tnsPresent = 0;                                        
+
+  for (i=0; i<numOfWindows; i++) {
+     
+    if (tnsInfo->tnsActive[i]!=0) {
+      tnsPresent = 1;                                    
+    }
+  }
+   
+  if (tnsPresent) {
+    /* there is data to be written*/
+    /*count += 1; */
+    for (i=0; i<numOfWindows; i++) {
+       
+      if (blockType == 2)
+        count += 1;
+      else
+        count += 2;
+       
+      if (tnsInfo->tnsActive[i]) {
+        count += 1;
+         
+        if (blockType == 2) {
+          count += 4;
+          count += 3;
+        }
+        else {
+          count += 6;
+          count += 5;
+        }
+         
+        if (tnsInfo->order[i]) {
+          count += 1; /*direction*/
+          count += 1; /*coef_compression */	
+           
+          if (tnsInfo->coefRes[i] == 4) {
+            ptcoef = tnsInfo->coef + i*TNS_MAX_ORDER_SHORT;

+			coefBits = 3;                                        
+            for(k=0; k<tnsInfo->order[i]; k++) {
+                 
+              if ((ptcoef[k] > 3) || (ptcoef[k] < -4)) {
+                coefBits = 4;                                    
+                break;
+              }
+            }
+          }
+          else {
+            coefBits = 2;                                        
+            ptcoef = tnsInfo->coef + i*TNS_MAX_ORDER_SHORT;

+			for(k=0; k<tnsInfo->order[i]; k++) {
+                 
+              if ((ptcoef[k] > 1) || (ptcoef[k] < -2)) {
+                coefBits = 3;                                    
+                break;
+              }
+            }
+          }
+          for (k=0; k<tnsInfo->order[i]; k++ ) {
+            count += coefBits;
+          }
+        }
+      }
+    }
+  }

+  
+  return count;
+}
+
+/**********************************************************************************
+*
+* function name: countTnsBits
+* description:   count tns bit demand  
+*
+**********************************************************************************/
+static Word16 countTnsBits(TNS_INFO *tnsInfo,Word16 blockType)
+{
+  return(tnsCount(tnsInfo, blockType));
+}
+
+/*********************************************************************************
+*
+* function name: countStaticBitdemand
+* description:   count static bit demand include tns  
+*
+**********************************************************************************/
+Word16 countStaticBitdemand(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+                            PSY_OUT_ELEMENT *psyOutElement,
+                            Word16 channels, 

+							Word16 adtsUsed)
+{
+  Word32 statBits;
+  Word32 ch;
+  
+  statBits = 0;                                                  

+

+  /* if adts used, add 56 bits */
+  if(adtsUsed) statBits += 56;
+
+   
+  switch (channels) {
+    case 1:
+      statBits += SI_ID_BITS+SI_SCE_BITS+SI_ICS_BITS;
+      statBits += countTnsBits(&(psyOutChannel[0].tnsInfo),
+                               psyOutChannel[0].windowSequence);
+       
+      switch(psyOutChannel[0].windowSequence){
+        case LONG_WINDOW:
+        case START_WINDOW:
+        case STOP_WINDOW:
+          statBits += SI_ICS_INFO_BITS_LONG;
+          break;
+        case SHORT_WINDOW:
+          statBits += SI_ICS_INFO_BITS_SHORT;
+          break;
+      }
+      break;
+    case 2:
+      statBits += SI_ID_BITS+SI_CPE_BITS+2*SI_ICS_BITS;
+
+      statBits += SI_CPE_MS_MASK_BITS;
+      statBits += countMsMaskBits(psyOutChannel[0].sfbCnt,
+								  psyOutChannel[0].sfbPerGroup,
+								  psyOutChannel[0].maxSfbPerGroup,
+								  &psyOutElement->toolsInfo);
+       
+      switch (psyOutChannel[0].windowSequence) {
+        case LONG_WINDOW:
+        case START_WINDOW:
+        case STOP_WINDOW:
+          statBits += SI_ICS_INFO_BITS_LONG;
+          break;
+        case SHORT_WINDOW:
+          statBits += SI_ICS_INFO_BITS_SHORT;
+          break;
+      }
+      for(ch=0; ch<2; ch++)
+        statBits += countTnsBits(&(psyOutChannel[ch].tnsInfo),
+                                 psyOutChannel[ch].windowSequence);
+      break;
+  }
+
+  return statBits;
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/tns.c b/media/libstagefright/codecs/aacenc/src/tns.c
new file mode 100644
index 0000000..96d890e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/tns.c
@@ -0,0 +1,932 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		tns.c

+

+	Content:	Definition TNS tools functions

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "oper_32b.h"

+#include "assert.h"
+#include "aac_rom.h"
+#include "psy_const.h"
+#include "tns.h"
+#include "tns_param.h"
+#include "psy_configuration.h"
+#include "tns_func.h"
+
+#define TNS_MODIFY_BEGIN         2600  /* Hz */
+#define RATIO_PATCH_LOWER_BORDER 380   /* Hz */
+#define TNS_GAIN_THRESH			 141   /* 1.41*100 */

+#define NORM_COEF				 0x028f5c28

+
+static const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */

+/* Limit bands to > 2.0 kHz */

+static unsigned short tnsMinBandNumberLong[12] =

+{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };

+static unsigned short tnsMinBandNumberShort[12] =

+{ 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 };

+

+/**************************************/

+/* Main/Low Profile TNS Parameters    */

+/**************************************/

+static unsigned short tnsMaxBandsLongMainLow[12] =

+{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };

+

+static unsigned short tnsMaxBandsShortMainLow[12] =

+{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
+
+
+static void CalcWeightedSpectrum(const Word32 spectrum[],
+                                 Word16 weightedSpectrum[],
+                                 Word32* sfbEnergy,
+                                 const Word16* sfbOffset, Word16 lpcStartLine,
+                                 Word16 lpcStopLine, Word16 lpcStartBand,Word16 lpcStopBand,
+                                 Word32 *pWork32);
+
+
+
+void AutoCorrelation(const Word16 input[], Word32 corr[],
+                            Word16 samples, Word16 corrCoeff);
+static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff);
+
+static Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines,
+                                              Word16 tnsOrder, Word32 parcor[]);
+
+
+static void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order,
+                         Word16 bitsPerCoeff);
+
+static void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order,
+                         Word16 bitsPerCoeff);
+
+
+
+static void AnalysisFilterLattice(const Word32 signal[], Word16 numOfLines,
+                                  const Word32 parCoeff[], Word16 order,
+                                  Word32 output[]);
+
+
+/**
+*
+* function name: FreqToBandWithRounding
+* description:  Retrieve index of nearest band border
+* returnt:		index
+*
+*/
+static Word16 FreqToBandWithRounding(Word32 freq,                   /*!< frequency in Hertz */
+                                     Word32 fs,                     /*!< Sampling frequency in Hertz */
+                                     Word16 numOfBands,             /*!< total number of bands */
+                                     const Word16 *bandStartOffset) /*!< table of band borders */
+{
+  Word32 lineNumber, band;
+  Word32 temp, shift;
+
+  /*  assert(freq >= 0);  */
+  shift = norm_l(fs);
+  lineNumber = (extract_l(fixmul((bandStartOffset[numOfBands] << 2),Div_32(freq << shift,fs << shift))) + 1) >> 1;
+ 
+  /* freq > fs/2 */
+  temp = lineNumber - bandStartOffset[numOfBands] ;                                            
+  if (temp >= 0)
+    return numOfBands;
+
+  /* find band the line number lies in */
+  for (band=0; band<numOfBands; band++) {
+    temp = bandStartOffset[band + 1] - lineNumber;                                           
+    if (temp > 0) break;
+  }
+
+  temp = (lineNumber - bandStartOffset[band]);
+  temp = (temp - (bandStartOffset[band + 1] - lineNumber));                                   
+  if ( temp > 0 )
+  {
+    band = band + 1;
+  }
+
+  return extract_l(band);
+}
+
+
+/**
+*
+* function name: InitTnsConfigurationLong
+* description:  Fill TNS_CONFIG structure with sensible content for long blocks
+* returns:		0 if success
+*
+*/
+Word16 InitTnsConfigurationLong(Word32 bitRate,          /*!< bitrate */
+                                Word32 sampleRate,          /*!< Sampling frequency */
+                                Word16 channels,            /*!< number of channels */
+                                TNS_CONFIG *tC,             /*!< TNS Config struct (modified) */
+                                PSY_CONFIGURATION_LONG *pC, /*!< psy config struct */
+                                Word16 active)              /*!< tns active flag */
+{
+
+  Word32 bitratePerChannel;
+  tC->maxOrder     = TNS_MAX_ORDER;                                           
+  tC->tnsStartFreq = 1275;
+  tC->coefRes      = 4;                                                                                 
+  
+  /* to avoid integer division */
+  if ( sub(channels,2) == 0 ) { 
+    bitratePerChannel = bitRate >> 1;    
+  }
+  else {
+    bitratePerChannel = bitRate;                                                                    
+  }
+
+  tC->tnsMaxSfb = tnsMaxBandsLongMainLow[pC->sampRateIdx];
+
+  tC->tnsActive = active;                                                                           
+
+  /* now calc band and line borders */
+  tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
+  tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];                                                 
+
+  tC->tnsStartBand = FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
+                                            pC->sfbCnt, (const Word16*)pC->sfbOffset);
+
+  tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
+                                                sampleRate,
+                                                pC->sfbCnt,
+                                                (const Word16*)pC->sfbOffset);
+
+  tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
+                                                     sampleRate,
+                                                     pC->sfbCnt,
+                                                     (const Word16*)pC->sfbOffset);
+
+
+  tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];                                                                                                             
+
+  tC->lpcStopBand = tnsMaxBandsLongMainLow[pC->sampRateIdx];
+  tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
+
+  tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];   

+  

+  tC->lpcStartBand = tnsMinBandNumberLong[pC->sampRateIdx];
+
+  tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];                                               
+
+  tC->threshold = TNS_GAIN_THRESH;                                                             
+
+
+  return(0);
+}
+
+/**
+*
+* function name: InitTnsConfigurationShort
+* description:  Fill TNS_CONFIG structure with sensible content for short blocks
+* returns:		0 if success
+*
+*/
+Word16 InitTnsConfigurationShort(Word32 bitRate,              /*!< bitrate */
+                                 Word32 sampleRate,           /*!< Sampling frequency */
+                                 Word16 channels,             /*!< number of channels */
+                                 TNS_CONFIG *tC,              /*!< TNS Config struct (modified) */
+                                 PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */
+                                 Word16 active)               /*!< tns active flag */
+{
+  Word32 bitratePerChannel;
+  tC->maxOrder     = TNS_MAX_ORDER_SHORT;
+  tC->tnsStartFreq = 2750;
+  tC->coefRes      = 3;                                                                                 
+  
+  /* to avoid integer division */
+  if ( sub(channels,2) == 0 ) {
+    bitratePerChannel = L_shr(bitRate,1);    
+  }
+  else {
+    bitratePerChannel = bitRate;                                                                    
+  }
+
+  tC->tnsMaxSfb = tnsMaxBandsShortMainLow[pC->sampRateIdx];
+
+  tC->tnsActive = active;                                                                           
+
+  /* now calc band and line borders */
+  tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
+  tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];                                                 
+
+  tC->tnsStartBand=FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
+                                          pC->sfbCnt, (const Word16*)pC->sfbOffset);
+
+  tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
+                                                sampleRate,
+                                                pC->sfbCnt,
+                                                (const Word16*)pC->sfbOffset);
+
+  tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
+                                                     sampleRate,
+                                                     pC->sfbCnt,
+                                                     (const Word16*)pC->sfbOffset);
+
+
+  tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];                                               
+
+  tC->lpcStopBand = tnsMaxBandsShortMainLow[pC->sampRateIdx];

+
+  tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
+
+  tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];                                                 
+
+  tC->lpcStartBand = tnsMinBandNumberShort[pC->sampRateIdx];

+
+  tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];                                               
+
+  tC->threshold = TNS_GAIN_THRESH;                                                             
+
+  return(0);
+}
+
+/**
+*
+* function name: TnsDetect
+* description:  Calculate TNS filter and decide on TNS usage 
+* returns:		0 if success
+*
+*/
+Word32 TnsDetect(TNS_DATA* tnsData,        /*!< tns data structure (modified) */
+                 TNS_CONFIG tC,            /*!< tns config structure */
+                 Word32* pScratchTns,      /*!< pointer to scratch space */
+                 const Word16 sfbOffset[], /*!< scalefactor size and table */
+                 Word32* spectrum,         /*!< spectral data */
+                 Word16 subBlockNumber,    /*!< subblock num */
+                 Word16 blockType,         /*!< blocktype (long or short) */
+                 Word32 * sfbEnergy)       /*!< sfb-wise energy */
+{
+
+  Word32  predictionGain;
+  Word32  temp;
+  Word32* pWork32 = &pScratchTns[subBlockNumber >> 8];
+  Word16* pWeightedSpectrum = (Word16 *)&pScratchTns[subBlockNumber >> 8];
+
+                                                                                                    
+  if (tC.tnsActive) {
+    CalcWeightedSpectrum(spectrum,
+                         pWeightedSpectrum,
+                         sfbEnergy,
+                         sfbOffset,
+                         tC.lpcStartLine,
+                         tC.lpcStopLine,
+                         tC.lpcStartBand,
+                         tC.lpcStopBand,
+                         pWork32);
+
+    temp = blockType - SHORT_WINDOW;                                                          
+    if ( temp != 0 ) {
+        predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
+                                        tC.acfWindow,
+                                        tC.lpcStopLine - tC.lpcStartLine,
+                                        tC.maxOrder,
+                                        tnsData->dataRaw.tnsLong.subBlockInfo.parcor);
+
+
+        temp = predictionGain - tC.threshold;                                                  
+        if ( temp > 0 ) {
+          tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 1;                                      
+        }
+        else {
+          tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;                                      
+        }
+
+        tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = predictionGain;                      
+    }
+    else{
+
+        predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
+                                        tC.acfWindow,
+                                        tC.lpcStopLine - tC.lpcStartLine,
+                                        tC.maxOrder,
+                                        tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].parcor);
+
+        temp = predictionGain - tC.threshold;                                                 
+        if ( temp > 0 ) {
+          tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 1;                     
+        }
+        else {
+          tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;                     
+        }
+
+        tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = predictionGain;     
+    }
+
+  }
+  else{
+
+    temp = blockType - SHORT_WINDOW;                                                          
+    if ( temp != 0 ) {
+        tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;                                        
+        tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = 0;                                   
+    }
+    else {
+        tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;                       
+        tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = 0;                  
+    }
+  }
+
+  return(0);
+}
+
+
+/*****************************************************************************
+*
+* function name: TnsSync
+* description: update tns parameter
+*
+*****************************************************************************/
+void TnsSync(TNS_DATA *tnsDataDest,
+             const TNS_DATA *tnsDataSrc,
+             const TNS_CONFIG tC,
+             const Word16 subBlockNumber,
+             const Word16 blockType)
+{
+   TNS_SUBBLOCK_INFO *sbInfoDest;
+   const TNS_SUBBLOCK_INFO *sbInfoSrc;
+   Word32 i, temp;
+
+   temp =  blockType - SHORT_WINDOW;                                                           
+   if ( temp != 0 ) {
+      sbInfoDest = &tnsDataDest->dataRaw.tnsLong.subBlockInfo;                                      
+      sbInfoSrc  = &tnsDataSrc->dataRaw.tnsLong.subBlockInfo;                                       
+   }
+   else {
+      sbInfoDest = &tnsDataDest->dataRaw.tnsShort.subBlockInfo[subBlockNumber];                     
+      sbInfoSrc  = &tnsDataSrc->dataRaw.tnsShort.subBlockInfo[subBlockNumber];                      
+   }
+
+   if (100*abs_s(sbInfoDest->predictionGain - sbInfoSrc->predictionGain) <
+       (3 * sbInfoDest->predictionGain)) {
+      sbInfoDest->tnsActive = sbInfoSrc->tnsActive;                                                 
+      for ( i=0; i< tC.maxOrder; i++) {
+        sbInfoDest->parcor[i] = sbInfoSrc->parcor[i];                                               
+      }
+   }
+}
+
+/*****************************************************************************
+*
+* function name: TnsEncode
+* description: do TNS filtering
+* returns:     0 if success
+*
+*****************************************************************************/
+Word16 TnsEncode(TNS_INFO* tnsInfo,     /*!< tns info structure (modified) */
+                 TNS_DATA* tnsData,     /*!< tns data structure (modified) */
+                 Word16 numOfSfb,       /*!< number of scale factor bands */
+                 TNS_CONFIG tC,         /*!< tns config structure */
+                 Word16 lowPassLine,    /*!< lowpass line */
+                 Word32* spectrum,      /*!< spectral data (modified) */
+                 Word16 subBlockNumber, /*!< subblock num */
+                 Word16 blockType)      /*!< blocktype (long or short) */
+{
+  Word32 i;
+  Word32 temp_s;
+  Word32 temp;

+  TNS_SUBBLOCK_INFO *psubBlockInfo;
+
+  temp_s = blockType - SHORT_WINDOW;                                                             
+  if ( temp_s != 0) {                                                                               
+    psubBlockInfo = &tnsData->dataRaw.tnsLong.subBlockInfo;

+	if (psubBlockInfo->tnsActive == 0) {
+      tnsInfo->tnsActive[subBlockNumber] = 0;                                                       
+      return(0);
+    }
+    else {
+
+      Parcor2Index(psubBlockInfo->parcor,
+                   tnsInfo->coef,
+                   tC.maxOrder,
+                   tC.coefRes);
+
+      Index2Parcor(tnsInfo->coef,
+                   psubBlockInfo->parcor,
+                   tC.maxOrder,
+                   tC.coefRes);
+
+      for (i=tC.maxOrder - 1; i>=0; i--)  {
+        temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;         
+        if ( temp > 0 )
+          break;
+        temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;         
+        if ( temp < 0 )
+          break;
+      }
+      tnsInfo->order[subBlockNumber] = i + 1;                                                    
+
+
+      tnsInfo->tnsActive[subBlockNumber] = 1;                                                       
+      for (i=subBlockNumber+1; i<TRANS_FAC; i++) {
+        tnsInfo->tnsActive[i] = 0;                                                                  
+      }
+      tnsInfo->coefRes[subBlockNumber] = tC.coefRes;                                                
+      tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;                                 
+
+
+      AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]),
+                            (min(tC.tnsStopLine,lowPassLine) - tC.tnsStartLine),
+                            psubBlockInfo->parcor,
+                            tnsInfo->order[subBlockNumber],
+                            &(spectrum[tC.tnsStartLine]));
+
+    }
+  }     /* if (blockType!=SHORT_WINDOW) */
+  else /*short block*/ {                                                                            
+    psubBlockInfo = &tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber];

+	if (psubBlockInfo->tnsActive == 0) {
+      tnsInfo->tnsActive[subBlockNumber] = 0;                                                       
+      return(0);
+    }
+    else {
+
+      Parcor2Index(psubBlockInfo->parcor,
+                   &tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
+                   tC.maxOrder,
+                   tC.coefRes);
+
+      Index2Parcor(&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
+                   psubBlockInfo->parcor,
+                   tC.maxOrder,
+                   tC.coefRes);
+      for (i=(tC.maxOrder - 1); i>=0; i--)  {
+        temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;    
+         if ( temp > 0 )
+          break;
+
+        temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;    
+        if ( temp < 0 )
+          break;
+      }
+      tnsInfo->order[subBlockNumber] = i + 1;                                                    
+
+      tnsInfo->tnsActive[subBlockNumber] = 1;                                                       
+      tnsInfo->coefRes[subBlockNumber] = tC.coefRes;                                                
+      tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;                             
+
+
+      AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), (tC.tnsStopLine - tC.tnsStartLine),
+                 psubBlockInfo->parcor,
+                 tnsInfo->order[subBlockNumber],
+                 &(spectrum[tC.tnsStartLine]));
+
+    }
+  }
+
+  return(0);
+}
+
+
+/*****************************************************************************
+*
+* function name: m_pow2_cordic
+* description: Iterative power function
+*
+*	Calculates pow(2.0,x-1.0*(scale+1)) with INT_BITS bit precision
+*	using modified cordic algorithm
+* returns:     the result of pow2
+*
+*****************************************************************************/
+static Word32 m_pow2_cordic(Word32 x, Word16 scale)
+{
+  Word32 k;
+
+  Word32 accu_y = 0x40000000;                                                                     
+  accu_y = L_shr(accu_y,scale);
+
+  for(k=1; k<INT_BITS; k++) {
+    const Word32 z = m_log2_table[k];                                                             
+
+    while(L_sub(x,z) >= 0) {
+       
+      x = L_sub(x, z);
+      accu_y = L_add(accu_y, (accu_y >> k));
+    }
+  }
+  return(accu_y);
+}
+
+
+/*****************************************************************************
+*
+* function name: CalcWeightedSpectrum
+* description: Calculate weighted spectrum for LPC calculation
+*
+*****************************************************************************/
+static void CalcWeightedSpectrum(const Word32  spectrum[],         /*!< input spectrum */
+                                 Word16        weightedSpectrum[],
+                                 Word32       *sfbEnergy,          /*!< sfb energies */
+                                 const Word16 *sfbOffset,
+                                 Word16        lpcStartLine,
+                                 Word16        lpcStopLine,
+                                 Word16        lpcStartBand,
+                                 Word16        lpcStopBand,
+                                 Word32       *pWork32)
+{
+    #define INT_BITS_SCAL 1<<(INT_BITS/2)
+
+    Word32 i, sfb, shift;
+    Word32 maxShift;
+    Word32 tmp_s, tmp2_s;
+    Word32 tmp, tmp2;
+    Word32 maxWS;
+    Word32 tnsSfbMean[MAX_SFB];    /* length [lpcStopBand-lpcStartBand] should be sufficient here */
+
+    maxWS = 0;                                                                                   
+  
+    /* calc 1.0*2^-INT_BITS/2/sqrt(en) */
+    for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) {
+
+      tmp2 = sfbEnergy[sfb] - 2;                                                            
+      if( tmp2 > 0) {
+        tmp = rsqrt(sfbEnergy[sfb], INT_BITS);
+		if(tmp > INT_BITS_SCAL) 

+		{

+			shift =  norm_l(tmp);

+			tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift ); 
+		}
+		else
+		{
+			tmp = 0x7fffffff; 
+		}
+      }
+      else {
+        tmp = 0x7fffffff;                                                                           
+      } 
+      tnsSfbMean[sfb] = tmp;                                                                        
+    }
+
+    /* spread normalized values from sfbs to lines */
+    sfb = lpcStartBand;                                                                             
+    tmp = tnsSfbMean[sfb];                                                                          
+    for ( i=lpcStartLine; i<lpcStopLine; i++){
+      tmp_s = sfbOffset[sfb + 1] - i;                                                      
+      if ( tmp_s == 0 ) {
+        sfb = sfb + 1;
+        tmp2_s = sfb + 1 - lpcStopBand;                                                       
+        if (tmp2_s <= 0) {
+          tmp = tnsSfbMean[sfb];                                                                    
+        }
+      }
+      pWork32[i] = tmp;                                                                    
+    }
+    /*filter down*/
+    for (i=(lpcStopLine - 2); i>=lpcStartLine; i--){
+        pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1;
+    }
+    /* filter up */
+    for (i=(lpcStartLine + 1); i<lpcStopLine; i++){
+       pWork32[i] = (pWork32[i] + pWork32[i - 1]) >> 1;
+    }
+
+    /* weight and normalize */
+    for (i=lpcStartLine; i<lpcStopLine; i++){
+      pWork32[i] = MULHIGH(pWork32[i], spectrum[i]);                               
+      maxWS |= L_abs(pWork32[i]);                                                          
+    }
+    maxShift = norm_l(maxWS);
+

+	maxShift = 16 - maxShift;

+    if(maxShift >= 0)

+	{

+		for (i=lpcStartLine; i<lpcStopLine; i++){

+			weightedSpectrum[i] = pWork32[i] >> maxShift;

+		}

+    }

+	else

+	{

+		maxShift = -maxShift;

+		for (i=lpcStartLine; i<lpcStopLine; i++){

+			weightedSpectrum[i] = saturate(pWork32[i] << maxShift);

+		}

+	}
+}
+
+
+
+
+/*****************************************************************************
+*
+* function name: CalcTnsFilter
+* description:  LPC calculation for one TNS filter
+* returns:      prediction gain
+* input:        signal spectrum, acf window, no. of spectral lines,
+*                max. TNS order, ptr. to reflection ocefficients
+* output:       reflection coefficients
+*(half) window size must be larger than tnsOrder !!*
+******************************************************************************/
+
+static Word16 CalcTnsFilter(const Word16 *signal,
+                            const Word32 window[],
+                            Word16 numOfLines,
+                            Word16 tnsOrder,
+                            Word32 parcor[])
+{
+  Word32 parcorWorkBuffer[2*TNS_MAX_ORDER+1];
+  Word32 predictionGain;
+  Word32 i;
+  Word32 tnsOrderPlus1 = tnsOrder + 1;
+
+  assert(tnsOrder <= TNS_MAX_ORDER);      /* remove asserts later? (btg) */
+
+  for(i=0;i<tnsOrder;i++) {
+    parcor[i] = 0;                               
+  }
+
+  AutoCorrelation(signal, parcorWorkBuffer, numOfLines, tnsOrderPlus1);
+
+  /* early return if signal is very low: signal prediction off, with zero parcor coeffs */
+  if (parcorWorkBuffer[0] == 0)
+    return 0;
+
+  predictionGain = AutoToParcor(parcorWorkBuffer, parcor, tnsOrder);
+
+  return(predictionGain);
+}
+
+/*****************************************************************************
+*
+* function name: AutoCorrelation
+* description:  calc. autocorrelation (acf)
+* returns:      -
+* input:        input values, no. of input values, no. of acf values
+* output:       acf values
+*
+*****************************************************************************/
+#ifndef ARMV5E

+void AutoCorrelation(const Word16		 input[],
+                            Word32       corr[],
+                            Word16       samples,
+                            Word16       corrCoeff) {
+  Word32 i, j, isamples;
+  Word32 accu;
+  Word32 scf;
+
+  scf = 10 - 1;                                                                                      
+

+  isamples = samples;
+  /* calc first corrCoef:  R[0] = sum { t[i] * t[i] } ; i = 0..N-1 */
+  accu = 0;                                                                                      
+  for(j=0; j<isamples; j++) {
+    accu = L_add(accu, ((input[j] * input[j]) >> scf));

+  }
+  corr[0] = accu;                                                                                
+
+  /* early termination if all corr coeffs are likely going to be zero */
+  if(corr[0] == 0) return ;
+
+  /* calc all other corrCoef:  R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */
+  for(i=1; i<corrCoeff; i++) {
+    isamples = isamples - 1;
+    accu = 0;                                                                                    
+    for(j=0; j<isamples; j++) {
+      accu = L_add(accu, ((input[j] * input[j+i]) >> scf));

+    }
+    corr[i] = accu;                                                                              
+  }
+}    
+#endif
+
+/*****************************************************************************
+*
+* function name: AutoToParcor
+* description:  conversion autocorrelation to reflection coefficients
+* returns:      prediction gain
+* input:        <order+1> input values, no. of output values (=order),
+*               ptr. to workbuffer (required size: 2*order)
+* output:       <order> reflection coefficients
+*
+*****************************************************************************/
+static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) {
+
+  Word32 i, j, shift;
+  Word32 *pWorkBuffer; /* temp pointer */
+  Word32 predictionGain = 0;
+  Word32 num, denom;
+  Word32 temp, workBuffer0;
+   
+
+  num = workBuffer[0];                                                                           
+  temp = workBuffer[numOfCoeff];                                                                 
+
+  for(i=0; i<numOfCoeff-1; i++) {
+    workBuffer[i + numOfCoeff] = workBuffer[i + 1];                                        
+  }
+  workBuffer[i + numOfCoeff] = temp;                                                                           
+  
+  for(i=0; i<numOfCoeff; i++) {
+    Word32 refc;
+
+     
+    if (workBuffer[0] < L_abs(workBuffer[i + numOfCoeff])) {
+      return 0 ;
+    }
+	shift = norm_l(workBuffer[0]);

+	workBuffer0 = Div_32(1 << shift, workBuffer[0] << shift);
+    /* calculate refc = -workBuffer[numOfCoeff+i] / workBuffer[0]; -1 <= refc < 1 */
+	refc = L_negate(fixmul(workBuffer[numOfCoeff + i], workBuffer0));
+
+    reflCoeff[i] = refc;                                                                           
+
+    pWorkBuffer = &(workBuffer[numOfCoeff]);                                                        
+
+    for(j=i; j<numOfCoeff; j++) {
+      Word32 accu1, accu2;
+      accu1 = L_add(pWorkBuffer[j], fixmul(refc, workBuffer[j - i]));
+      accu2 = L_add(workBuffer[j - i], fixmul(refc, pWorkBuffer[j]));
+      pWorkBuffer[j] = accu1;                                                                       
+      workBuffer[j - i] = accu2;                                                                 
+    }
+  }
+
+  denom = MULHIGH(workBuffer[0], NORM_COEF);
+   
+  if (denom != 0) {
+    Word32 temp;

+	shift = norm_l(denom);

+	temp = Div_32(1 << shift, denom << shift);
+    predictionGain = fixmul(num, temp);
+  }
+
+  return extract_l(predictionGain);
+}
+
+
+
+static Word16 Search3(Word32 parcor)
+{
+  Word32 index = 0;
+  Word32 i;
+  Word32 temp;
+   
+  for (i=0;i<8;i++) {
+    temp = L_sub( parcor, tnsCoeff3Borders[i]);                                                     
+    if (temp > 0)
+      index=i;                                                                                      
+  }
+  return extract_l(index - 4);
+}
+
+static Word16 Search4(Word32 parcor)
+{
+  Word32 index = 0;
+  Word32 i;
+  Word32 temp;
+   
+
+  for (i=0;i<16;i++) {
+    temp = L_sub(parcor, tnsCoeff4Borders[i]);                                                      
+    if (temp > 0)
+      index=i;                                                                                      
+  }
+  return extract_l(index - 8);
+}
+
+
+
+/*****************************************************************************
+*
+* functionname: Parcor2Index
+* description:  quantization index for reflection coefficients
+*
+*****************************************************************************/
+static void Parcor2Index(const Word32 parcor[],   /*!< parcor coefficients */
+                         Word16 index[],          /*!< quantized coeff indices */
+                         Word16 order,            /*!< filter order */
+                         Word16 bitsPerCoeff) {   /*!< quantizer resolution */
+  Word32 i;
+  Word32 temp;
+
+  for(i=0; i<order; i++) {
+    temp = bitsPerCoeff - 3;                                                                    
+    if (temp == 0) {
+      index[i] = Search3(parcor[i]);                                                                
+    } 
+    else {
+      index[i] = Search4(parcor[i]);                                                                
+    }
+  }
+}
+
+/*****************************************************************************
+*
+* functionname: Index2Parcor
+* description:  Inverse quantization for reflection coefficients
+*
+*****************************************************************************/
+static void Index2Parcor(const Word16 index[],  /*!< quantized values */
+                         Word32 parcor[],       /*!< ptr. to reflection coefficients (output) */
+                         Word16 order,          /*!< no. of coefficients */
+                         Word16 bitsPerCoeff)   /*!< quantizer resolution */
+{
+  Word32 i;
+  Word32 temp;
+
+  for (i=0; i<order; i++) {
+    temp = bitsPerCoeff - 4;                                                                     
+    if ( temp == 0 ) {
+        parcor[i] = tnsCoeff4[index[i] + 8];                                                     
+    }
+    else {
+        parcor[i] = tnsCoeff3[index[i] + 4];                                                  
+    }
+  }
+}
+
+/*****************************************************************************
+*
+* functionname: FIRLattice
+* description:  in place lattice filtering of spectral data
+* returns:		pointer to modified data
+*
+*****************************************************************************/
+static Word32 FIRLattice(Word16 order,           /*!< filter order */
+                         Word32 x,               /*!< spectral data */
+                         Word32 *state_par,      /*!< filter states */
+                         const Word32 *coef_par) /*!< filter coefficients */
+{
+   Word32 i;
+   Word32 accu,tmp,tmpSave;
+
+   x = x >> 1;
+   tmpSave = x;                                                                                     
+
+   for (i=0; i<(order - 1); i++) {
+
+     tmp = L_add(fixmul(coef_par[i], x), state_par[i]);
+     x   = L_add(fixmul(coef_par[i], state_par[i]), x);
+
+     state_par[i] = tmpSave;                                                                        
+     tmpSave = tmp;                                                                                 
+  }
+
+  /* last stage: only need half operations */
+  accu = fixmul(state_par[order - 1], coef_par[(order - 1)]);
+  state_par[(order - 1)] = tmpSave;                                                                
+
+  x = L_add(accu, x);
+  x = L_add(x, x);
+
+  return x;
+}
+
+/*****************************************************************************
+*
+* functionname: AnalysisFilterLattice
+* description:  filters spectral lines with TNS filter
+*
+*****************************************************************************/
+static void AnalysisFilterLattice(const  Word32 signal[],  /*!< input spectrum */
+                                  Word16 numOfLines,       /*!< no. of lines */
+                                  const  Word32 parCoeff[],/*!< PARC coefficients */
+                                  Word16 order,            /*!< filter order */
+                                  Word32 output[])         /*!< filtered signal values */
+{
+
+  Word32 state_par[TNS_MAX_ORDER];
+  Word32 j;
+
+  for ( j=0; j<TNS_MAX_ORDER; j++ ) {
+    state_par[j] = 0;                                                                               
+  }
+
+  for(j=0; j<numOfLines; j++) {
+    output[j] = FIRLattice(order,signal[j],state_par,parCoeff);                                     
+  }
+}
+
+/*****************************************************************************
+*
+* functionname: ApplyTnsMultTableToRatios
+* description:  Change thresholds according to tns
+*
+*****************************************************************************/
+void ApplyTnsMultTableToRatios(Word16 startCb,
+                               Word16 stopCb,
+                               TNS_SUBBLOCK_INFO subInfo, /*!< TNS subblock info */
+                               Word32 *thresholds)        /*!< thresholds (modified) */
+{
+  Word32 i;                                                                                         
+  if (subInfo.tnsActive) {
+    for(i=startCb; i<stopCb; i++) {
+      /* thresholds[i] * 0.25 */
+      thresholds[i] = (thresholds[i] >> 2);                                                      
+    }
+  }
+}
diff --git a/media/libstagefright/codecs/aacenc/src/transform.c b/media/libstagefright/codecs/aacenc/src/transform.c
new file mode 100644
index 0000000..af17b5a
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/transform.c
@@ -0,0 +1,672 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		transform.c

+

+	Content:	MDCT Transform functionss

+

+*******************************************************************************/
+
+#include "basic_op.h"

+#include "psy_const.h"
+#include "transform.h"
+#include "aac_rom.h"
+

+

+#define LS_TRANS ((FRAME_LEN_LONG-FRAME_LEN_SHORT)/2) /* 448 */

+#define SQRT1_2 0x5a82799a	/* sqrt(1/2) in Q31 */

+#define swap2(p0,p1) \

+	t = p0; t1 = *(&(p0)+1);	\

+	p0 = p1; *(&(p0)+1) = *(&(p1)+1);	\

+	p1 = t; *(&(p1)+1) = t1	

+
+/*********************************************************************************
+*
+* function name: Shuffle
+* description:  Shuffle points prepared function for fft
+*
+**********************************************************************************/
+static void Shuffle(int *buf, int num, const unsigned char* bitTab)

+{

+    int *part0, *part1;

+	int i, j;

+	int t, t1;

+

+	part0 = buf;

+    part1 = buf + num;

+	

+	while ((i = *bitTab++) != 0) {

+        j = *bitTab++;

+

+        swap2(part0[4*i+0], part0[4*j+0]);	

+        swap2(part0[4*i+2], part1[4*j+0]);	

+        swap2(part1[4*i+0], part0[4*j+2]);	

+        swap2(part1[4*i+2], part1[4*j+2]);	

+    }

+

+    do {

+        swap2(part0[4*i+2], part1[4*i+0]);	

+    } while ((i = *bitTab++) != 0);

+}

+

+#if !defined(ARMV5E) && !defined(ARMV7Neon)

+
+/*****************************************************************************
+*
+* function name: Radix4First
+* description:  Radix 4 point prepared function for fft
+*
+**********************************************************************************/

+static void Radix4First(int *buf, int num)

+{

+    int r0, r1, r2, r3;

+	int r4, r5, r6, r7;

+	

+	for (; num != 0; num--) 

+	{

+		r0 = buf[0] + buf[2];

+		r1 = buf[1] + buf[3];

+		r2 = buf[0] - buf[2];

+		r3 = buf[1] - buf[3];

+		r4 = buf[4] + buf[6];

+		r5 = buf[5] + buf[7];

+		r6 = buf[4] - buf[6];

+		r7 = buf[5] - buf[7];

+

+		buf[0] = r0 + r4;

+		buf[1] = r1 + r5;

+		buf[4] = r0 - r4;

+		buf[5] = r1 - r5;

+		buf[2] = r2 + r7;

+		buf[3] = r3 - r6;

+		buf[6] = r2 - r7;

+		buf[7] = r3 + r6;

+

+		buf += 8;

+	}

+}

+

+/*****************************************************************************
+*
+* function name: Radix8First
+* description:  Radix 8 point prepared function for fft
+*
+**********************************************************************************/

+static void Radix8First(int *buf, int num)

+{

+   int r0, r1, r2, r3;

+   int i0, i1, i2, i3;

+   int r4, r5, r6, r7;

+   int i4, i5, i6, i7;

+   int t0, t1, t2, t3;

+

+	for ( ; num != 0; num--) 

+	{

+		r0 = buf[0] + buf[2];

+		i0 = buf[1] + buf[3];

+		r1 = buf[0] - buf[2];

+		i1 = buf[1] - buf[3];

+		r2 = buf[4] + buf[6];

+		i2 = buf[5] + buf[7];

+		r3 = buf[4] - buf[6];

+		i3 = buf[5] - buf[7];

+

+		r4 = (r0 + r2) >> 1;

+		i4 = (i0 + i2) >> 1;

+		r5 = (r0 - r2) >> 1;

+		i5 = (i0 - i2) >> 1;

+		r6 = (r1 - i3) >> 1;

+		i6 = (i1 + r3) >> 1;

+		r7 = (r1 + i3) >> 1;

+		i7 = (i1 - r3) >> 1;

+

+		r0 = buf[ 8] + buf[10];

+		i0 = buf[ 9] + buf[11];

+		r1 = buf[ 8] - buf[10];

+		i1 = buf[ 9] - buf[11];

+		r2 = buf[12] + buf[14];

+		i2 = buf[13] + buf[15];

+		r3 = buf[12] - buf[14];

+		i3 = buf[13] - buf[15];

+

+		t0 = (r0 + r2) >> 1;

+		t1 = (i0 + i2) >> 1;

+		t2 = (r0 - r2) >> 1;

+		t3 = (i0 - i2) >> 1;

+

+		buf[ 0] = r4 + t0;

+		buf[ 1] = i4 + t1;

+		buf[ 8] = r4 - t0;

+		buf[ 9] = i4 - t1;

+		buf[ 4] = r5 + t3;

+		buf[ 5] = i5 - t2;

+		buf[12] = r5 - t3;

+		buf[13] = i5 + t2;

+

+		r0 = r1 - i3;

+		i0 = i1 + r3;

+		r2 = r1 + i3;

+		i2 = i1 - r3;

+

+		t0 = MULHIGH(SQRT1_2, r0 - i0);

+		t1 = MULHIGH(SQRT1_2, r0 + i0);

+		t2 = MULHIGH(SQRT1_2, r2 - i2);

+		t3 = MULHIGH(SQRT1_2, r2 + i2);

+

+		buf[ 6] = r6 - t0;

+		buf[ 7] = i6 - t1;

+		buf[14] = r6 + t0;

+		buf[15] = i6 + t1;

+		buf[ 2] = r7 + t3;

+		buf[ 3] = i7 - t2;

+		buf[10] = r7 - t3;

+		buf[11] = i7 + t2;

+

+		buf += 16;

+	}

+}

+

+/*****************************************************************************
+*
+* function name: Radix4FFT
+* description:  Radix 4 point fft core function
+*
+**********************************************************************************/

+static void Radix4FFT(int *buf, int num, int bgn, int *twidTab)

+{

+	int r0, r1, r2, r3;

+	int r4, r5, r6, r7;

+	int t0, t1;

+	int sinx, cosx;

+	int i, j, step;

+	int *xptr, *csptr;

+

+	for (num >>= 2; num != 0; num >>= 2) 

+	{

+		step = 2*bgn;

+		xptr = buf;

+

+    	for (i = num; i != 0; i--) 

+		{

+			csptr = twidTab;

+

+			for (j = bgn; j != 0; j--) 

+			{

+				r0 = xptr[0];

+				r1 = xptr[1];

+				xptr += step;

+				

+				t0 = xptr[0];

+				t1 = xptr[1];				

+				cosx = csptr[0];

+				sinx = csptr[1];

+				r2 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1);		/* cos*br + sin*bi */

+				r3 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0);		/* cos*bi - sin*br */

+				xptr += step;

+

+				t0 = r0 >> 2;

+				t1 = r1 >> 2;

+				r0 = t0 - r2;

+				r1 = t1 - r3;

+				r2 = t0 + r2;

+				r3 = t1 + r3;

+				

+				t0 = xptr[0];

+				t1 = xptr[1];

+				cosx = csptr[2];

+				sinx = csptr[3];

+				r4 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1);		/* cos*cr + sin*ci */

+				r5 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0);		/* cos*ci - sin*cr */

+				xptr += step;

+				

+				t0 = xptr[0];

+				t1 = xptr[1];

+				cosx = csptr[4];

+				sinx = csptr[5];

+				r6 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1);		/* cos*cr + sin*ci */

+				r7 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0);		/* cos*ci - sin*cr */

+				csptr += 6;

+

+				t0 = r4;

+				t1 = r5;

+				r4 = t0 + r6;

+				r5 = r7 - t1;

+				r6 = t0 - r6;

+				r7 = r7 + t1;

+

+				xptr[0] = r0 + r5;

+				xptr[1] = r1 + r6;

+				xptr -= step;

+

+				xptr[0] = r2 - r4;

+				xptr[1] = r3 - r7;

+				xptr -= step;

+

+				xptr[0] = r0 - r5;

+				xptr[1] = r1 - r6;

+				xptr -= step;

+

+				xptr[0] = r2 + r4;

+				xptr[1] = r3 + r7;

+				xptr += 2;

+			}

+			xptr += 3*step;

+		}

+		twidTab += 3*step;

+		bgn <<= 2;

+	}

+}

+

+/*********************************************************************************
+*
+* function name: PreMDCT
+* description:  prepare MDCT process for next FFT compute
+*
+**********************************************************************************/

+static void PreMDCT(int *buf0, int num, const int *csptr)

+{

+	int i;

+	int tr1, ti1, tr2, ti2;

+	int cosa, sina, cosb, sinb;

+	int *buf1;

+	

+	buf1 = buf0 + num - 1;

+

+	for(i = num >> 2; i != 0; i--)

+	{

+		cosa = *csptr++;	

+		sina = *csptr++;	

+		cosb = *csptr++;	

+		sinb = *csptr++;		

+

+		tr1 = *(buf0 + 0);

+		ti2 = *(buf0 + 1);

+		tr2 = *(buf1 - 1);

+		ti1 = *(buf1 + 0);

+		

+		*buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1);

+		*buf0++ = MULHIGH(cosa, ti1) - MULHIGH(sina, tr1);		

+		

+		*buf1-- = MULHIGH(cosb, ti2) - MULHIGH(sinb, tr2);		

+		*buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2);

+	}

+}

+

+/*********************************************************************************
+*
+* function name: PostMDCT
+* description:   post MDCT process after next FFT for MDCT
+*
+**********************************************************************************/

+static void PostMDCT(int *buf0, int num, const int *csptr)

+{

+	int i;

+	int tr1, ti1, tr2, ti2;

+	int cosa, sina, cosb, sinb;

+	int *buf1;

+

+	buf1 = buf0 + num - 1;

+	

+	for(i = num >> 2; i != 0; i--)

+	{

+		cosa = *csptr++;	

+		sina = *csptr++;	

+		cosb = *csptr++;	

+		sinb = *csptr++;

+

+		tr1 = *(buf0 + 0);

+		ti1 = *(buf0 + 1);

+		ti2 = *(buf1 + 0);

+		tr2 = *(buf1 - 1);

+

+		*buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1);

+		*buf1-- = MULHIGH(sina, tr1) - MULHIGH(cosa, ti1);		

+		

+		*buf0++ = MULHIGH(sinb, tr2) - MULHIGH(cosb, ti2);

+		*buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2);	

+	}

+}

+#endif

+

+

+/**********************************************************************************
+*
+* function name: Mdct_Long
+* description:  the long block mdct, include long_start block, end_long block
+*
+**********************************************************************************/

+void Mdct_Long(int *buf)

+{

+	PreMDCT(buf, 1024, cossintab + 128);

+

+	Shuffle(buf, 512, bitrevTab + 17);

+	Radix8First(buf, 512 >> 3);						

+	Radix4FFT(buf, 512 >> 3, 8, (int *)twidTab512);

+

+	PostMDCT(buf, 1024, cossintab + 128);	

+}

+

+

+/**********************************************************************************
+*
+* function name: Mdct_Short
+* description:  the short block mdct 
+*
+**********************************************************************************/

+void Mdct_Short(int *buf)

+{

+	PreMDCT(buf, 128, cossintab);

+

+	Shuffle(buf, 64, bitrevTab);

+	Radix4First(buf, 64 >> 2);						

+	Radix4FFT(buf, 64 >> 2, 4, (int *)twidTab64);	

+

+	PostMDCT(buf, 128, cossintab);	

+}

+
+
+/*****************************************************************************
+*
+* function name: shiftMdctDelayBuffer
+* description:    the mdct delay buffer has a size of 1600,
+*  so the calculation of LONG,STOP must be  spilt in two 
+*  passes with 1024 samples and a mid shift,
+*  the SHORT transforms can be completed in the delay buffer,
+*  and afterwards a shift
+*
+**********************************************************************************/
+static void shiftMdctDelayBuffer(Word16 *mdctDelayBuffer, /*! start of mdct delay buffer */
+								 Word16 *timeSignal,      /*! pointer to new time signal samples, interleaved */
+								 Word16 chIncrement       /*! number of channels */
+								 )
+{
+	Word32 i;
+	Word16 *srBuf = mdctDelayBuffer;
+	Word16 *dsBuf = mdctDelayBuffer+FRAME_LEN_LONG;
+
+	for(i = 0; i < BLOCK_SWITCHING_OFFSET-FRAME_LEN_LONG; i+= 8)
+	{
+		*srBuf++ = *dsBuf++;	 *srBuf++ = *dsBuf++;
+		*srBuf++ = *dsBuf++;	 *srBuf++ = *dsBuf++;
+		*srBuf++ = *dsBuf++;	 *srBuf++ = *dsBuf++;
+		*srBuf++ = *dsBuf++;	 *srBuf++ = *dsBuf++;
+	}
+
+	srBuf = mdctDelayBuffer + BLOCK_SWITCHING_OFFSET-FRAME_LEN_LONG;
+	dsBuf = timeSignal;
+
+	for(i=0; i<FRAME_LEN_LONG; i+=8)
+	{   
+		*srBuf++ = *dsBuf; dsBuf += chIncrement;
+		*srBuf++ = *dsBuf; dsBuf += chIncrement;
+		*srBuf++ = *dsBuf; dsBuf += chIncrement;
+		*srBuf++ = *dsBuf; dsBuf += chIncrement;
+		*srBuf++ = *dsBuf; dsBuf += chIncrement;
+		*srBuf++ = *dsBuf; dsBuf += chIncrement;
+		*srBuf++ = *dsBuf; dsBuf += chIncrement;
+		*srBuf++ = *dsBuf; dsBuf += chIncrement;
+	}
+}

+

+

+/*****************************************************************************
+*
+* function name: getScalefactorOfShortVectorStride
+* description:  Calculate max possible scale factor for input vector of shorts
+* returns:      Maximum scale factor
+*
+**********************************************************************************/

+static Word16 getScalefactorOfShortVectorStride(const Word16 *vector, /*!< Pointer to input vector */

+												Word16 len,           /*!< Length of input vector */

+												Word16 stride)        /*!< Stride of input vector */

+{

+	Word16 maxVal = 0;

+	Word16 absVal;

+	Word16 i;

+

+	for(i=0; i<len; i++){

+		absVal = abs_s(vector[i*stride]);

+		maxVal |= absVal;

+	}

+

+	return( maxVal ? norm_s(maxVal) : 15);

+}

+
+
+/*****************************************************************************
+*
+* function name: Transform_Real
+* description:  Calculate transform filter for input vector of shorts
+* returns:      TRUE if success
+*
+**********************************************************************************/
+void Transform_Real(Word16 *mdctDelayBuffer,
+                    Word16 *timeSignal,
+                    Word16 chIncrement,
+                    Word32 *realOut,
+                    Word16 *mdctScale,
+                    Word16 blockType
+                    )
+{
+	Word32 i,w;
+	Word32 timeSignalSample;
+	Word32 ws1,ws2;
+	Word16 *dctIn0, *dctIn1;

+	Word32 *outData0, *outData1;

+	Word32 *winPtr;
+
+	Word32 delayBufferSf,timeSignalSf,minSf;
+	Word32 headRoom=0;
+	
+	switch(blockType){
+		
+		
+	case LONG_WINDOW:
+		/*
+		we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + 448 new timeSignal samples
+		and get the biggest scale factor for next calculate more precise
+		*/
+		delayBufferSf = getScalefactorOfShortVectorStride(mdctDelayBuffer,BLOCK_SWITCHING_OFFSET,1);
+		timeSignalSf  = getScalefactorOfShortVectorStride(timeSignal,2*FRAME_LEN_LONG-BLOCK_SWITCHING_OFFSET,chIncrement);
+		minSf = min(delayBufferSf,timeSignalSf);
+		minSf = min(minSf,14);
+		
+		dctIn0 = mdctDelayBuffer;
+		dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+		outData0 = realOut + FRAME_LEN_LONG/2;
+		
+		/* add windows and pre add for mdct to last buffer*/
+		winPtr = (int *)LongWindowKBD;
+		for(i=0;i<FRAME_LEN_LONG/2;i++){
+			timeSignalSample = (*dctIn0++) << minSf; 
+			ws1 = timeSignalSample * (*winPtr >> 16);
+			timeSignalSample = (*dctIn1--) << minSf;
+			ws2 = timeSignalSample * (*winPtr & 0xffff);
+			winPtr ++;
+			/* shift 2 to avoid overflow next */
+			*outData0++ = (ws1 >> 2) - (ws2 >> 2);
+		}
+		
+		shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
+		
+		/* add windows and pre add for mdct to new buffer*/
+		dctIn0 = mdctDelayBuffer;
+		dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+		outData0 = realOut + FRAME_LEN_LONG/2 - 1; 
+		winPtr = (int *)LongWindowKBD;
+		for(i=0;i<FRAME_LEN_LONG/2;i++){    
+			timeSignalSample = (*dctIn0++) << minSf;
+			ws1 = timeSignalSample * (*winPtr & 0xffff);
+			timeSignalSample = (*dctIn1--) << minSf;
+			ws2 = timeSignalSample * (*winPtr >> 16);
+			winPtr++;
+			/* shift 2 to avoid overflow next */
+			*outData0-- = -((ws1 >> 2) + (ws2 >> 2)); 
+		}
+
+		Mdct_Long(realOut);

+		/* update scale factor */

+		minSf = 14 - minSf;
+		*mdctScale=minSf; 
+		break;
+		
+	case START_WINDOW:
+		/*
+		we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + no timeSignal samples
+		and get the biggest scale factor for next calculate more precise
+		*/
+		minSf = getScalefactorOfShortVectorStride(mdctDelayBuffer,BLOCK_SWITCHING_OFFSET,1);
+		minSf = min(minSf,14);
+
+		dctIn0 = mdctDelayBuffer;
+		dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+		outData0 = realOut + FRAME_LEN_LONG/2; 		
+		winPtr = (int *)LongWindowKBD;
+
+		/* add windows and pre add for mdct to last buffer*/
+		for(i=0;i<FRAME_LEN_LONG/2;i++){
+			timeSignalSample = (*dctIn0++) << minSf;
+			ws1 = timeSignalSample * (*winPtr >> 16);
+			timeSignalSample = (*dctIn1--) << minSf;
+			ws2 = timeSignalSample * (*winPtr & 0xffff);
+			winPtr ++;
+			*outData0++ = (ws1 >> 2) - (ws2 >> 2);  /* shift 2 to avoid overflow next */

+		}
+		
+		shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
+		
+		outData0 = realOut + FRAME_LEN_LONG/2 - 1; 
+		for(i=0;i<LS_TRANS;i++){
+			*outData0-- = -mdctDelayBuffer[i] << (15 - 2 + minSf);  
+		}
+		
+		/* add windows and pre add for mdct to new buffer*/
+		dctIn0 = mdctDelayBuffer + LS_TRANS;
+		dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1 - LS_TRANS;
+		outData0 = realOut + FRAME_LEN_LONG/2 - 1 -LS_TRANS; 
+		winPtr = (int *)ShortWindowSine;
+		for(i=0;i<FRAME_LEN_SHORT/2;i++){
+			timeSignalSample= (*dctIn0++) << minSf;
+			ws1 = timeSignalSample * (*winPtr & 0xffff);
+			timeSignalSample= (*dctIn1--) << minSf;
+			ws2 = timeSignalSample * (*winPtr >> 16);
+			winPtr++;
+			*outData0-- =  -((ws1 >> 2) + (ws2 >> 2));  /* shift 2 to avoid overflow next */

+		}
+
+		Mdct_Long(realOut);
+		/* update scale factor */
+		minSf = 14 - minSf;
+		*mdctScale= minSf;
+		break;
+		
+	case STOP_WINDOW:
+		/*
+		we access BLOCK_SWITCHING_OFFSET-LS_TRANS (1600-448 ) delay buffer samples + 448 new timeSignal samples
+		and get the biggest scale factor for next calculate more precise
+		*/
+		delayBufferSf = getScalefactorOfShortVectorStride(mdctDelayBuffer+LS_TRANS,BLOCK_SWITCHING_OFFSET-LS_TRANS,1);
+		timeSignalSf  = getScalefactorOfShortVectorStride(timeSignal,2*FRAME_LEN_LONG-BLOCK_SWITCHING_OFFSET,chIncrement);
+		minSf = min(delayBufferSf,timeSignalSf);    
+		minSf = min(minSf,13);
+		
+		outData0 = realOut + FRAME_LEN_LONG/2;
+		dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+		for(i=0;i<LS_TRANS;i++){
+			*outData0++ = -(*dctIn1--) << (15 - 2 + minSf);    
+		}
+		
+		/* add windows and pre add for mdct to last buffer*/
+		dctIn0 = mdctDelayBuffer + LS_TRANS;
+		dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1 - LS_TRANS;
+		outData0 = realOut + FRAME_LEN_LONG/2 + LS_TRANS; 
+		winPtr = (int *)ShortWindowSine;
+		for(i=0;i<FRAME_LEN_SHORT/2;i++){
+			timeSignalSample = (*dctIn0++) << minSf;
+			ws1 = timeSignalSample * (*winPtr >> 16);
+			timeSignalSample= (*dctIn1--) << minSf;
+			ws2 = timeSignalSample * (*winPtr & 0xffff);
+			winPtr++;
+			*outData0++ = (ws1 >> 2) - (ws2 >> 2);  /* shift 2 to avoid overflow next */

+		}
+		
+		shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
+		
+		/* add windows and pre add for mdct to new buffer*/
+		dctIn0 = mdctDelayBuffer;
+		dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+		outData0 = realOut + FRAME_LEN_LONG/2 - 1; 
+		winPtr = (int *)LongWindowKBD;
+		for(i=0;i<FRAME_LEN_LONG/2;i++){
+			timeSignalSample= (*dctIn0++) << minSf;
+			ws1 = timeSignalSample *(*winPtr & 0xffff);
+			timeSignalSample= (*dctIn1--) << minSf;
+			ws2 = timeSignalSample * (*winPtr >> 16);
+			*outData0-- =  -((ws1 >> 2) + (ws2 >> 2));  /* shift 2 to avoid overflow next */

+			winPtr++;

+		}
+		
+		Mdct_Long(realOut);
+		minSf = 14 - minSf;
+		*mdctScale= minSf; /* update scale factor */
+		break;
+		
+	case SHORT_WINDOW:
+		/*
+		we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + no new timeSignal samples
+		and get the biggest scale factor for next calculate more precise
+		*/		
+		minSf = getScalefactorOfShortVectorStride(mdctDelayBuffer+TRANSFORM_OFFSET_SHORT,9*FRAME_LEN_SHORT,1);
+		minSf = min(minSf,10);
+		
+		
+		for(w=0;w<TRANS_FAC;w++){
+			dctIn0 = mdctDelayBuffer+w*FRAME_LEN_SHORT+TRANSFORM_OFFSET_SHORT;
+			dctIn1 = mdctDelayBuffer+w*FRAME_LEN_SHORT+TRANSFORM_OFFSET_SHORT + FRAME_LEN_SHORT-1;
+			outData0 = realOut + FRAME_LEN_SHORT/2; 
+			outData1 = realOut + FRAME_LEN_SHORT/2 - 1; 
+
+			winPtr = (int *)ShortWindowSine;
+			for(i=0;i<FRAME_LEN_SHORT/2;i++){
+				timeSignalSample= *dctIn0 << minSf;
+				ws1 = timeSignalSample * (*winPtr >> 16);
+				timeSignalSample= *dctIn1 << minSf;
+				ws2 = timeSignalSample * (*winPtr & 0xffff);
+				*outData0++ = (ws1 >> 2) - (ws2 >> 2);  /* shift 2 to avoid overflow next */

+				
+				timeSignalSample= *(dctIn0 + FRAME_LEN_SHORT) << minSf;
+				ws1 = timeSignalSample * (*winPtr & 0xffff);
+				timeSignalSample= *(dctIn1 + FRAME_LEN_SHORT) << minSf;
+				ws2 = timeSignalSample * (*winPtr >> 16);
+				*outData1-- =  -((ws1 >> 2) + (ws2 >> 2));  /* shift 2 to avoid overflow next */

+

+				winPtr++;

+				dctIn0++;

+				dctIn1--;

+			}
+
+			Mdct_Short(realOut);
+			realOut += FRAME_LEN_SHORT;
+		}
+		

+		minSf = 11 - minSf;
+		*mdctScale = minSf; /* update scale factor */
+		
+		shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
+		break;
+  }
+}
+
diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
index 7728597..fb300da 100644
--- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
@@ -117,7 +117,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         CHECK(seekTimeUs >= 0);
 
         mNumSamplesOutput = 0;
diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
index f349671..c875426 100644
--- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
@@ -29,8 +29,9 @@
 static const int32_t kNumSamplesPerFrame = 160;
 static const int32_t kSampleRate = 8000;
 
-AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source)
+AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
     : mSource(source),
+      mMeta(meta),
       mStarted(false),
       mBufferGroup(NULL),
       mEncState(NULL),
@@ -69,7 +70,10 @@
 }
 
 status_t AMRNBEncoder::start(MetaData *params) {
-    CHECK(!mStarted);
+    if (mStarted) {
+        LOGW("Call start() when encoder already started");
+        return OK;
+    }
 
     mBufferGroup = new MediaBufferGroup;
     mBufferGroup->add_buffer(new MediaBuffer(32));
@@ -78,7 +82,7 @@
                 &mEncState, &mSidState, false /* dtx_enable */),
              0);
 
-    mSource->start();
+    mSource->start(params);
 
     mAnchorTimeUs = 0;
     mNumFramesOutput = 0;
@@ -96,7 +100,10 @@
 }
 
 status_t AMRNBEncoder::stop() {
-    CHECK(mStarted);
+    if (!mStarted) {
+        LOGW("Call stop() when encoder has not started.");
+        return OK;
+    }
 
     if (mInputBuffer) {
         mInputBuffer->release();
@@ -119,28 +126,16 @@
 sp<MetaData> AMRNBEncoder::getFormat() {
     sp<MetaData> srcFormat = mSource->getFormat();
 
-    int32_t numChannels;
-    int32_t sampleRate;
-
-    CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
-    CHECK_EQ(numChannels, 1);
-
-    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-    CHECK_EQ(sampleRate, kSampleRate);
-
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
-    meta->setInt32(kKeyChannelCount, numChannels);
-    meta->setInt32(kKeySampleRate, sampleRate);
+    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
 
     int64_t durationUs;
     if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        meta->setInt64(kKeyDuration, durationUs);
+        mMeta->setInt64(kKeyDuration, durationUs);
     }
 
-    meta->setCString(kKeyDecoderComponent, "AMRNBEncoder");
+    mMeta->setCString(kKeyDecoderComponent, "AMRNBEncoder");
 
-    return meta;
+    return mMeta;
 }
 
 status_t AMRNBEncoder::read(
@@ -150,7 +145,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    CHECK(options == NULL || !options->getSeekTo(&seekTimeUs));
+    ReadOptions::SeekMode mode;
+    CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
 
     while (mNumInputSamples < kNumSamplesPerFrame) {
         if (mInputBuffer == NULL) {
diff --git a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
index c17c100..2a21472 100644
--- a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
+++ b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
@@ -135,7 +135,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode seekMode;
+    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
         CHECK(seekTimeUs >= 0);
 
         mNumSamplesOutput = 0;
diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
new file mode 100644
index 0000000..93304d0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2010 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 "AMRWBEncoder"
+#include <utils/Log.h>
+
+#include "AMRWBEncoder.h"
+#include "voAMRWB.h"
+#include "cmnMemory.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+static const int32_t kNumSamplesPerFrame = 320;
+static const int32_t kBitsPerSample = 16;
+static const int32_t kInputBufferSize = (kBitsPerSample / 8) * kNumSamplesPerFrame;
+static const int32_t kSampleRate = 16000;
+static const int32_t kNumChannels = 1;
+
+AMRWBEncoder::AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
+    : mSource(source),
+      mMeta(meta),
+      mStarted(false),
+      mBufferGroup(NULL),
+      mInputBuffer(NULL),
+      mEncoderHandle(NULL),
+      mApiHandle(NULL),
+      mMemOperator(NULL),
+      mAnchorTimeUs(0),
+      mNumFramesOutput(0),
+      mNumInputSamples(0) {
+}
+
+static VOAMRWBMODE pickModeFromBitRate(int32_t bps) {
+    CHECK(bps >= 0);
+    if (bps <= 6600) {
+        return VOAMRWB_MD66;
+    } else if (bps <= 8850) {
+        return VOAMRWB_MD885;
+    } else if (bps <= 12650) {
+        return VOAMRWB_MD1265;
+    } else if (bps <= 14250) {
+        return VOAMRWB_MD1425;
+    } else if (bps <= 15850) {
+        return VOAMRWB_MD1585;
+    } else if (bps <= 18250) {
+        return VOAMRWB_MD1825;
+    } else if (bps <= 19850) {
+        return VOAMRWB_MD1985;
+    } else if (bps <= 23050) {
+        return VOAMRWB_MD2305;
+    }
+    return VOAMRWB_MD2385;
+}
+
+status_t AMRWBEncoder::initCheck() {
+    CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
+    CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
+
+    mApiHandle = new VO_AUDIO_CODECAPI;
+    CHECK(mApiHandle);
+
+    if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) {
+        LOGE("Failed to get api handle");
+        return UNKNOWN_ERROR;
+    }
+
+    mMemOperator = new VO_MEM_OPERATOR;
+    CHECK(mMemOperator != NULL);
+    mMemOperator->Alloc = cmnMemAlloc;
+    mMemOperator->Copy = cmnMemCopy;
+    mMemOperator->Free = cmnMemFree;
+    mMemOperator->Set = cmnMemSet;
+    mMemOperator->Check = cmnMemCheck;
+
+    VO_CODEC_INIT_USERDATA userData;
+    memset(&userData, 0, sizeof(userData));
+    userData.memflag = VO_IMF_USERMEMOPERATOR;
+    userData.memData = (VO_PTR) mMemOperator;
+    if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) {
+        LOGE("Failed to init AMRWB encoder");
+        return UNKNOWN_ERROR;
+    }
+
+    // Configure AMRWB encoder$
+    VOAMRWBMODE mode = pickModeFromBitRate(mBitRate);
+    if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_MODE,  &mode)) {
+        LOGE("Failed to set AMRWB encoder mode to %d", mode);
+        return UNKNOWN_ERROR;
+    }
+
+    VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267;
+    if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) {
+        LOGE("Failed to set AMRWB encoder frame type to %d", type);
+        return UNKNOWN_ERROR;
+    }
+
+    return OK;
+}
+
+AMRWBEncoder::~AMRWBEncoder() {
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t AMRWBEncoder::start(MetaData *params) {
+    if (mStarted) {
+        LOGW("Call start() when encoder already started");
+        return OK;
+    }
+
+    mBufferGroup = new MediaBufferGroup;
+
+    // The largest buffer size is header + 477 bits
+    mBufferGroup->add_buffer(new MediaBuffer(1024));
+
+    CHECK_EQ(OK, initCheck());
+
+    mNumFramesOutput = 0;
+    mSource->start(params);
+
+    mStarted = true;
+
+    return OK;
+}
+
+status_t AMRWBEncoder::stop() {
+    if (!mStarted) {
+        LOGW("Call stop() when encoder has not started");
+        return OK;
+    }
+
+    if (mInputBuffer) {
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    delete mBufferGroup;
+    mBufferGroup = NULL;
+
+
+    CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
+    mEncoderHandle = NULL;
+
+    delete mApiHandle;
+    mApiHandle = NULL;
+
+    delete mMemOperator;
+    mMemOperator;
+
+    mStarted = false;
+
+    mSource->stop();
+    return OK;
+}
+
+sp<MetaData> AMRWBEncoder::getFormat() {
+    sp<MetaData> srcFormat = mSource->getFormat();
+
+    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        mMeta->setInt64(kKeyDuration, durationUs);
+    }
+
+    mMeta->setCString(kKeyDecoderComponent, "AMRWBEncoder");
+
+    return mMeta;
+}
+
+status_t AMRWBEncoder::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    status_t err;
+
+    *out = NULL;
+
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode mode;
+    CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
+
+    while (mNumInputSamples < kNumSamplesPerFrame) {
+        if (mInputBuffer == NULL) {
+            err = mSource->read(&mInputBuffer, options);
+
+            if (err != OK) {
+                if (mNumInputSamples == 0) {
+                    return ERROR_END_OF_STREAM;
+                }
+                memset(&mInputFrame[mNumInputSamples],
+                       0,
+                       sizeof(int16_t)
+                            * (kNumSamplesPerFrame - mNumInputSamples));
+                mNumInputSamples = 0;
+                break;
+            }
+
+            size_t align = mInputBuffer->range_length() % sizeof(int16_t);
+            CHECK_EQ(align, 0);
+
+            int64_t timeUs;
+            if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+                mAnchorTimeUs = timeUs;
+            }
+        }
+
+        size_t copy =
+            (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
+
+        if (copy > mInputBuffer->range_length()) {
+            copy = mInputBuffer->range_length();
+        }
+
+        memcpy(&mInputFrame[mNumInputSamples],
+               (const uint8_t *)mInputBuffer->data()
+                    + mInputBuffer->range_offset(),
+               copy);
+
+        mInputBuffer->set_range(
+                mInputBuffer->range_offset() + copy,
+                mInputBuffer->range_length() - copy);
+
+        if (mInputBuffer->range_length() == 0) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+        }
+
+        mNumInputSamples += copy / sizeof(int16_t);
+        if (mNumInputSamples >= kNumSamplesPerFrame) {
+            mNumInputSamples %= kNumSamplesPerFrame;
+            break;  // Get a whole input frame 640 bytes
+        }
+    }
+
+    VO_CODECBUFFER inputData;
+    memset(&inputData, 0, sizeof(inputData));
+    inputData.Buffer = (unsigned char*) mInputFrame;
+    inputData.Length = kInputBufferSize;
+    CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
+
+    MediaBuffer *buffer;
+    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
+    uint8_t *outPtr = (uint8_t *)buffer->data();
+
+    VO_CODECBUFFER outputData;
+    memset(&outputData, 0, sizeof(outputData));
+    VO_AUDIO_OUTPUTINFO outputInfo;
+    memset(&outputInfo, 0, sizeof(outputInfo));
+
+    VO_U32 ret = VO_ERR_NONE;
+    outputData.Buffer = outPtr;
+    outputData.Length = buffer->size();
+    ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
+    CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
+
+    buffer->set_range(0, outputData.Length);
+    ++mNumFramesOutput;
+
+    // XXX: fix timestamp calculation
+    int64_t timestampUs = mNumFramesOutput * 20000LL;
+
+    buffer->meta_data()->setInt64(kKeyTime, timestampUs);
+
+    *out = buffer;
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
new file mode 100644
index 0000000..4293287
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -0,0 +1,120 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
+
+LOCAL_PRELINK_MODULE := false
+ 	
+LOCAL_SRC_FILES := \
+	AMRWBEncoder.cpp \
+	src/autocorr.c \
+	src/az_isp.c \
+	src/bits.c \
+	src/c2t64fx.c \
+	src/c4t64fx.c \
+	src/convolve.c \
+	src/cor_h_x.c \
+	src/decim54.c \
+	src/deemph.c \
+	src/dtx.c \
+	src/g_pitch.c \
+	src/gpclip.c \
+	src/homing.c \
+	src/hp400.c \
+	src/hp50.c \
+	src/hp6k.c \
+	src/hp_wsp.c \
+	src/int_lpc.c \
+	src/isp_az.c \
+	src/isp_isf.c \
+	src/lag_wind.c \
+	src/levinson.c \
+	src/log2.c \
+	src/lp_dec2.c \
+	src/math_op.c \
+	src/oper_32b.c \
+	src/p_med_ol.c \
+	src/pit_shrp.c \
+	src/pitch_f4.c \
+	src/pred_lt4.c \
+	src/preemph.c \
+	src/q_gain2.c \
+	src/q_pulse.c \
+	src/qisf_ns.c \
+	src/qpisf_2s.c \
+	src/random.c \
+	src/residu.c \
+	src/scale.c \
+	src/stream.c \
+	src/syn_filt.c \
+	src/updt_tar.c \
+	src/util.c \
+	src/voAMRWBEnc.c \
+	src/voicefac.c \
+	src/wb_vad.c \
+	src/weight_a.c \
+	src/mem_align.c
+
+
+ifeq ($(VOTT), v5)
+LOCAL_SRC_FILES += \
+	src/asm/ARMV5E/convolve_opt.s \
+	src/asm/ARMV5E/cor_h_vec_opt.s \
+	src/asm/ARMV5E/Deemph_32_opt.s \
+	src/asm/ARMV5E/Dot_p_opt.s \
+	src/asm/ARMV5E/Filt_6k_7k_opt.s \
+	src/asm/ARMV5E/Norm_Corr_opt.s \
+	src/asm/ARMV5E/pred_lt4_1_opt.s \
+	src/asm/ARMV5E/residu_asm_opt.s \
+	src/asm/ARMV5E/scale_sig_opt.s \
+	src/asm/ARMV5E/Syn_filt_32_opt.s \
+	src/asm/ARMV5E/syn_filt_opt.s
+
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_SRC_FILES += \
+	src/asm/ARMV7/convolve_neon.s \
+	src/asm/ARMV7/cor_h_vec_neon.s \
+	src/asm/ARMV7/Deemph_32_neon.s \
+	src/asm/ARMV7/Dot_p_neon.s \
+	src/asm/ARMV7/Filt_6k_7k_neon.s \
+	src/asm/ARMV7/Norm_Corr_neon.s \
+	src/asm/ARMV7/pred_lt4_1_neon.s \
+	src/asm/ARMV7/residu_asm_neon.s \
+	src/asm/ARMV7/scale_sig_neon.s \
+	src/asm/ARMV7/Syn_filt_32_neon.s \
+	src/asm/ARMV7/syn_filt_neon.s
+
+endif
+
+LOCAL_MODULE := libstagefright_amrwbenc
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES := 
+
+LOCAL_SHARED_LIBRARIES :=
+
+LOCAL_C_INCLUDES := \
+	frameworks/base/media/libstagefright/include \
+	frameworks/base/media/libstagefright/codecs/common/include \
+	frameworks/base/include \
+	$(LOCAL_PATH)/src \
+	$(LOCAL_PATH)/inc
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+ifeq ($(VOTT), v5)
+LOCAL_CFLAGS += -DARM -DASM_OPT
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_CFLAGS += -DARM -DARMV7 -DASM_OPT
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
new file mode 100644
index 0000000..792d3cc
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
@@ -0,0 +1,364 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+#ifdef LINUX

+#include <dlfcn.h>

+#endif

+

+#include      <stdio.h>

+#include      <stdlib.h>

+#include      <time.h>

+#include      "voAMRWB.h"

+#include      "cmnMemory.h"

+

+#define VOAMRWB_RFC3267_HEADER_INFO "#!AMR-WB\n"

+

+#define  INPUT_SIZE   640

+#define  OUTPUT_SIZE  1024

+unsigned char  InputBuf[INPUT_SIZE];

+unsigned char  OutputBuf[OUTPUT_SIZE];

+

+void usage (void) {

+	printf ("AMR_WB Encoder HELP   Displays this text\n");

+	printf ("\n");

+	printf ("Usage:\n");

+	printf ("AMRWBEnc [options] Input_file output_file \n");

+	printf ("\n");

+	printf ("Options +M* +F* +DTX \n");

+	printf ("Support \n");

+	printf ("Options +M* for seting compression bitrate mode, default is 23.85kbps\n");

+	printf (" +M0 = 6.6kbps \n");

+	printf (" +M1 = 8.85kbps \n");

+	printf (" +M2 = 12.65kbps \n");

+	printf (" +M3 = 14.25kbps \n");

+	printf (" +M4 = 15.58kbps \n");

+	printf (" +M5 = 18.25kbps \n");

+	printf (" +M6 = 19.85kbps \n");

+	printf (" +M7 = 23.05kbps \n");

+	printf (" +M8 = 23.85kbps \n");

+	printf ("\n");

+	printf ("Options +F* for setting output frame Type, default is RFC3267 \n");

+	printf ("+F0 for AMR_WB Defualt bit extern short data frame type \n");

+	printf ("+F1 for AMR_WB_ITU bit extern short data frame type \n");

+	printf ("+F2 for RFC3267\n ");

+	printf ("\n");

+	printf ("Options +DTX enable DTX mode, default is disable.\n");

+	printf ("File names, input raw PCM data, and output is AMR_WB bit-stream file.\n");

+	printf ("\n");

+}

+

+int  GetNextBuf(FILE* inFile,unsigned char* dst,int size)

+{

+	int size2 = (int)fread(dst, sizeof(signed char), size,inFile);

+	return size2;

+}

+

+typedef int (VO_API * VOGETAUDIOENCAPI) (VO_AUDIO_CODECAPI * pEncHandle);

+

+int encode(

+		   int mode, 

+		   short   allow_dtx,

+		   VOAMRWBFRAMETYPE frameType,

+		   const char* srcfile, 

+		   const char* dstfile

+		   )

+{

+	int			ret = 0;

+	int         returnCode;

+	FILE		*fsrc = NULL;

+	FILE		*fdst = NULL;

+	int         framenum = 0;

+	int         eofFile = 0;

+	int         size1 = 0;

+	int         Relens;

+

+	VO_AUDIO_CODECAPI       AudioAPI;

+	VO_MEM_OPERATOR         moper;

+	VO_CODEC_INIT_USERDATA  useData;

+	VO_HANDLE               hCodec;

+	VO_CODECBUFFER          inData;

+	VO_CODECBUFFER          outData;

+	VO_AUDIO_OUTPUTINFO     outFormat;

+

+	unsigned char *inBuf = InputBuf;

+	unsigned char *outBuf = OutputBuf;

+

+

+#ifdef LINUX

+	void  *handle = NULL;

+	void  *pfunc;

+	VOGETAUDIOENCAPI pGetAPI;

+#endif

+

+	clock_t   start, finish;

+	double    duration = 0.0;

+

+	if ((fsrc = fopen (srcfile, "rb")) == NULL)

+	{

+		ret = -1;

+		goto safe_exit;

+	}

+

+	if ((fdst = fopen (dstfile, "wb")) == NULL)

+	{

+		ret = -1;

+		goto safe_exit;

+	}

+

+	moper.Alloc = cmnMemAlloc;

+	moper.Copy = cmnMemCopy;

+	moper.Free = cmnMemFree;

+	moper.Set = cmnMemSet;

+	moper.Check = cmnMemCheck;

+

+	useData.memflag = VO_IMF_USERMEMOPERATOR;

+	useData.memData = (VO_PTR)(&moper);

+

+#ifdef LINUX

+	handle = dlopen("/data/local/tmp/voAMRWBEnc.so", RTLD_NOW);

+	if(handle == 0)

+	{

+		printf("open dll error......");

+		return -1;

+	}

+

+	pfunc = dlsym(handle, "voGetAMRWBEncAPI");	

+	if(pfunc == 0)

+	{

+		printf("open function error......");

+		return -1;

+	}

+

+	pGetAPI = (VOGETAUDIOENCAPI)pfunc;

+

+	returnCode  = pGetAPI(&AudioAPI);

+	if(returnCode)

+	{

+		printf("get APIs error......");

+		return -1;

+	}

+#else

+	ret = voGetAMRWBEncAPI(&AudioAPI);

+	if(ret)

+	{

+		ret = -1;

+		printf("get APIs error......");

+		goto safe_exit;

+	}

+#endif 

+

+	//#######################################   Init Encoding Section   #########################################

+	ret = AudioAPI.Init(&hCodec, VO_AUDIO_CodingAMRWB, &useData);

+

+	if(ret)

+	{

+		ret = -1;

+		printf("APIs init error......");

+		goto safe_exit;

+	}

+

+	Relens = GetNextBuf(fsrc,InputBuf,INPUT_SIZE);

+	if(Relens!=INPUT_SIZE && !feof(fsrc))

+	{

+		ret = -1; //Invalid magic number

+		printf("get next buffer error......");

+		goto safe_exit;

+	}

+

+	//###################################### set encode Mode ##################################################

+	ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_FRAMETYPE, &frameType);

+	ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_MODE, &mode);

+	ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_DTX, &allow_dtx);

+

+	if(frameType == VOAMRWB_RFC3267)

+	{

+		/* write RFC3267 Header info to indicate single channel AMR file storage format */

+		size1 = (int)strlen(VOAMRWB_RFC3267_HEADER_INFO);

+		memcpy(outBuf, VOAMRWB_RFC3267_HEADER_INFO, size1);

+		outBuf += size1;

+	}

+

+	//#######################################   Encoding Section   #########################################

+	printf(" \n ---------------- Running -------------------------\n ");

+

+	do{

+		inData.Buffer = (unsigned char *)inBuf;

+		inData.Length = Relens;

+		outData.Buffer = outBuf;

+

+		start = clock();

+

+		/* decode one amr block */

+		returnCode = AudioAPI.SetInputData(hCodec,&inData);

+

+		do {

+			returnCode = AudioAPI.GetOutputData(hCodec,&outData, &outFormat);

+			if(returnCode == 0)

+			{

+				framenum++;

+				printf(" Frames processed: %hd\r", framenum);

+				if(framenum == 1)

+				{

+					fwrite(OutputBuf, 1, outData.Length + size1, fdst);

+					fflush(fdst);	

+				}

+				else

+				{

+					fwrite(outData.Buffer, 1, outData.Length, fdst);

+					fflush(fdst);

+				}

+			}

+			else if(returnCode == VO_ERR_LICENSE_ERROR)

+			{

+		        printf("Encoder time reach upper limit......");

+		        goto safe_exit;

+			}

+		} while(returnCode != VO_ERR_INPUT_BUFFER_SMALL);

+

+		finish = clock();

+		duration += finish - start;

+

+		if (!eofFile) {

+			Relens = GetNextBuf(fsrc, InputBuf, INPUT_SIZE);

+			inBuf = InputBuf;

+			if (feof(fsrc) && Relens == 0)

+				eofFile = 1;

+		}

+	} while (!eofFile && returnCode);

+	//#######################################   End Encoding Section   #########################################

+

+safe_exit:

+	returnCode = AudioAPI.Uninit(hCodec);

+

+	printf( "\n%2.5f seconds\n", (double)duration/CLOCKS_PER_SEC);

+

+	if (fsrc)

+		fclose(fsrc);

+	if (fdst)

+		fclose(fdst);

+

+#ifdef LINUX

+	dlclose(handle);

+#endif

+

+	return ret;

+}

+

+int main(int argc, char **argv)  // for gcc compiler;

+{

+	int     mode, r;

+	int     arg, filename=0;

+	char    *inFileName = NULL;

+	char    *outFileName = NULL;

+	short   allow_dtx;

+	VOAMRWBFRAMETYPE frameType;

+

+	printf("\n");

+	printf("************************Adaptive Multi-Rate Wide Band Encoder (AMR-WB)*******************************\n");

+	printf("***********************************DEFINITIONS:*******************************************************\n");

+	printf("AMR-WB encoder scheme is based on the principle of Algebraic Code Excited Linear Prediction algorithm\n");

+	printf("The AMR-WB encoder compression MONO liner PCM speech input data at 16kHz sampling rate\n");

+	printf("to one of nine data rate modes-6.60, 8.85, 12.65, 14.25, 15.85, 18.25, 19.25, 23.05 and 23.85kbps.\n");

+	printf("The encoder supports output format AMRWB ITU, AMRWB RFC3267.\n");

+	printf("\n");

+

+	/*Encoder Default setting */

+	mode = VOAMRWB_MD2385;

+	allow_dtx = 0;

+	frameType = VOAMRWB_RFC3267;

+

+	if(argc < 3){

+		usage();

+		return 0;

+	}else{

+		for (arg = 1; arg < argc; arg++) {

+			if (argv [arg] [0] == '+') {

+				if(argv[arg][1] == 'M')

+				{

+					switch(argv[arg][2])

+					{

+					case '0': mode = VOAMRWB_MD66;

+						break;

+					case '1': mode = VOAMRWB_MD885;

+						break;

+					case '2': mode = VOAMRWB_MD1265;

+						break;

+					case '3': mode = VOAMRWB_MD1425;

+						break;

+					case '4': mode = VOAMRWB_MD1585;

+						break;

+					case '5': mode = VOAMRWB_MD1825;

+						break;

+					case '6': mode = VOAMRWB_MD1985;

+						break;

+					case '7': mode = VOAMRWB_MD2305;

+						break;

+					case '8': mode = VOAMRWB_MD2385;

+						break;

+					default:

+						usage();

+						printf ("Invalid parameter '%s'.\n", argv [arg]);

+						break;

+					}

+				}else if(argv[arg][1] == 'F')

+				{

+					switch(argv[arg][2])

+					{

+					case '0': frameType = VOAMRWB_DEFAULT;

+						break;

+					case '1': frameType = VOAMRWB_ITU;

+						break;

+					case '2': frameType = VOAMRWB_RFC3267 ;

+						break; 

+					default:

+						usage();

+						printf ("Invalid parameter '%s'.\n", argv [arg]);

+						break;

+

+

+					}

+				}else if(strcmp (argv[arg], "+DTX") == 0)

+				{

+					allow_dtx = 1;

+				}

+

+			} else {

+				switch (filename) {

+						case 0: 

+							inFileName  = argv[arg];

+							break;

+						case 1: 

+							outFileName = argv[arg]; 

+							break;

+						default:

+							usage ();

+							fprintf (stderr, "Invalid parameter '%s'.\n", argv [arg]);

+							return 0;

+				}

+				filename++;

+			}

+		}

+	}

+

+	r = encode(mode, allow_dtx, frameType, inFileName, outFileName);

+	if(r)

+	{

+		fprintf(stderr, "error: %d\n", r);

+	}

+	return r;

+}

+

diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
new file mode 100644
index 0000000..7edb166
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := 	AMRWB_E_SAMPLE.c
+	
+LOCAL_SRC_FILES += 	\
+	../../../Common/cmnMemory.c 
+
+LOCAL_MODULE := TestvoAMRWBEnc
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES := 
+
+LOCAL_SHARED_LIBRARIES := libvoAMRWBEnc
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/ \
+	$(LOCAL_PATH)/../../../Common \
+	$(LOCAL_PATH)/../../../Include \
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+	
+include $(BUILD_EXECUTABLE)
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile
new file mode 100644
index 0000000..55b876a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile
@@ -0,0 +1,56 @@
+#/*

+# ** Copyright 2003-2010, VisualOn, Inc.

+# **

+# ** 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.

+# */

+

+# target6

+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

+VOTT:= v6

+

+

+# module type

+# please specify the type of your module: lib or exe

+VOMT:= exe

+

+

+# module macros

+# please append the additional macro definitions here for your module if necessary. 

+# e.g. -DVISUALON, macro VISUALON defined for your module 

+VOMM:= #ARMV5E

+

+

+

+# please specify the name of your module

+VOTARGET:= voAMRWBEnc_Test

+

+

+# please modify here to be sure to see the g1.mk

+include ../../../../Tools/eclair.mk 

+

+# dependent libraries.

+VODEPLIBS:=-ldl

+

+

+# module source

+# please modify here to be sure to see the ms.mk which specifies all source info of your module

+include ../ms.mk

+

+

+# please specify where is the voRelease on your PC, relative path is suggested

+VORELDIR:=../

+

+

+# please modify here to be sure to see the doit.mk

+include ../../../../Tools/doit.mk 

+

diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk
new file mode 100644
index 0000000..74e8913
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk
@@ -0,0 +1,24 @@
+#/*

+# ** Copyright 2003-2010, VisualOn, Inc.

+# **

+# ** 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.

+# */

+# please list all objects needed by your target here

+OBJS:=AMRWB_E_SAMPLE.o cmnMemory.o

+			

+# please list all directories that all source files relative with your module(.h .c .cpp) locate 

+VOSRCDIR:=../ \

+          ../../../../Common \

+	  ../../../../Include

+					

+				

diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile
new file mode 100644
index 0000000..58fda29
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile
@@ -0,0 +1,53 @@
+#/*

+# ** Copyright 2003-2010, VisualOn, Inc.

+# **

+# ** 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.

+# */

+

+# target type

+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

+VOTT:= v5

+

+

+# module type

+# please specify the type of your module: lib or exe

+VOMT:= lib

+

+

+# module macros

+# please append the additional macro definitions here for your module if necessary. 

+ifeq ($(VOTT), v5)

+VOMM:=-DARM -DASM_OPT

+endif

+

+# please specify the name of your module

+VOTARGET:= libvoAMRWBEncv5

+

+

+# please modify here to be sure to see the g1.mk

+include ../../../../../Tools/eclair.mk 

+

+# dependent libraries.

+VODEPLIBS:=-ldl -lstdc++ -lcutils

+

+# module source

+# please modify here to be sure to see the ms.mk which specifies all source info of your module

+include ../ms.mk

+

+

+# please specify where is the voRelease on your PC, relative path is suggested

+VORELDIR:=../../../../../../Release

+

+# please modify here to be sure to see the doit.mk

+include ../../../../../Tools/doit.mk 

+

diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile
new file mode 100644
index 0000000..5686411
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile
@@ -0,0 +1,53 @@
+#/*

+# ** Copyright 2003-2010, VisualOn, Inc.

+# **

+# ** 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.

+# */

+

+# target type

+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)

+VOTT:= v7

+

+

+# module type

+# please specify the type of your module: lib or exe

+VOMT:= lib

+

+

+# module macros

+# please append the additional macro definitions here for your module if necessary. 

+ifeq ($(VOTT), v7)

+VOMM:=-DARM -DARMV7 -DASM_OPT

+endif

+

+# please specify the name of your module

+VOTARGET:= libvoAMRWBEncv7

+

+

+# please modify here to be sure to see the g1.mk

+include ../../../../../Tools/eclair.mk 

+

+# dependent libraries.

+VODEPLIBS:=-ldl -lstdc++ -lcutils

+

+# module source

+# please modify here to be sure to see the ms.mk which specifies all source info of your module

+include ../ms.mk

+

+

+# please specify where is the voRelease on your PC, relative path is suggested

+VORELDIR:=../../../../../../Release

+

+# please modify here to be sure to see the doit.mk

+include ../../../../../Tools/doit.mk 

+

diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/makefile
new file mode 100644
index 0000000..3473a1a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/build/eclair/makefile
@@ -0,0 +1,39 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** 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.
+# */
+# Just acting as Father Makefile of Modules
+# please keep the name 'makefile' unchanged
+ 
+# Module Subdirs
+VOMSD:=$(dir $(shell find . -name 'Makefile'))
+
+all:
+	for dir in $(VOMSD); \
+		do \
+			$(MAKE) -C $$dir; \
+		done
+
+.PHONY:clean devel
+clean:
+	for dir in $(VOMSD); \
+		do \
+			$(MAKE) -C $$dir clean; \
+		done
+
+devel:
+	for dir in $(VOMSD); \
+		do \
+			$(MAKE) -C $$dir devel; \
+		done
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk b/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk
new file mode 100644
index 0000000..bd6620c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk
@@ -0,0 +1,43 @@
+#/*

+# ** Copyright 2003-2010, VisualOn, Inc.

+# **

+# ** 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.

+# */

+# please list all directories that all source files relative with your module(.h .c .cpp) locate 

+VOSRCDIR:=../../../inc \

+          ../../../src \

+	  ../../../../../Include 

+

+# please list all objects needed by your target here

+OBJS:= autocorr.o az_isp.o bits.o c2t64fx.o c4t64fx.o convolve.o cor_h_x.o decim54.o \

+       deemph.o dtx.o g_pitch.o gpclip.o homing.o hp400.o hp50.o hp6k.o hp_wsp.o \

+       int_lpc.o isp_az.o isp_isf.o lag_wind.o levinson.o log2.o lp_dec2.o math_op.o mem_align.o \

+       oper_32b.o p_med_ol.o pit_shrp.o pitch_f4.o pred_lt4.o preemph.o q_gain2.o q_pulse.o \

+       qisf_ns.o qpisf_2s.o random.o residu.o scale.o stream.o syn_filt.o updt_tar.o util.o \

+       voAMRWBEnc.o voicefac.o wb_vad.o weight_a.o

+			

+

+ifeq ($(VOTT), v5)

+OBJS += cor_h_vec_opt.o Deemph_32_opt.o Dot_p_opt.o Filt_6k_7k_opt.o residu_asm_opt.o \

+       scale_sig_opt.o Syn_filt_32_opt.o syn_filt_opt.o pred_lt4_1_opt.o convolve_opt.o \

+       Norm_Corr_opt.o

+VOSRCDIR+= ../../../src/asm/ARMV5E

+endif

+

+ifeq ($(VOTT), v7)

+OBJS+= cor_h_vec_neon.o Deemph_32_neon.o Dot_p_neon.o Filt_6k_7k_neon.o residu_asm_neon.o \

+       scale_sig_neon.o Syn_filt_32_neon.o syn_filt_neon.o pred_lt4_1_neon.o convolve_neon.o \

+       Norm_Corr_neon.o

+VOSRCDIR+= ../../../src/asm/ARMV7

+endif

+

diff --git a/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf b/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf
new file mode 100644
index 0000000..5bade44
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf
Binary files differ
diff --git a/media/libstagefright/codecs/amrwbenc/inc/acelp.h b/media/libstagefright/codecs/amrwbenc/inc/acelp.h
new file mode 100644
index 0000000..4cb38a1
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/acelp.h
@@ -0,0 +1,521 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*--------------------------------------------------------------------------*

+ *                         ACELP.H                                          *

+ *--------------------------------------------------------------------------*

+ *       Function			 			             *

+ *--------------------------------------------------------------------------*/

+#ifndef __ACELP_H__

+#define __ACELP_H__

+

+#include "typedef.h"

+#include "cod_main.h"

+

+/*-----------------------------------------------------------------*

+ *                        LPC prototypes                           *

+ *-----------------------------------------------------------------*/

+

+Word16 median5(Word16 x[]);

+

+void Autocorr(

+		Word16 x[],                           /* (i)    : Input signal                      */

+		Word16 m,                             /* (i)    : LPC order                         */

+		Word16 r_h[],                         /* (o)    : Autocorrelations  (msb)           */

+		Word16 r_l[]                          /* (o)    : Autocorrelations  (lsb)           */

+	     );

+

+void Lag_window(

+		Word16 r_h[],                         /* (i/o)   : Autocorrelations  (msb)          */

+		Word16 r_l[]                          /* (i/o)   : Autocorrelations  (lsb)          */

+	       );

+

+void Init_Levinson(

+		Word16 * mem                          /* output  :static memory (18 words) */

+		);

+

+void Levinson(

+		Word16 Rh[],                          /* (i)     : Rh[M+1] Vector of autocorrelations (msb) */

+		Word16 Rl[],                          /* (i)     : Rl[M+1] Vector of autocorrelations (lsb) */

+		Word16 A[],                           /* (o) Q12 : A[M]    LPC coefficients  (m = 16)       */

+		Word16 rc[],                          /* (o) Q15 : rc[M]   Reflection coefficients.         */

+		Word16 * mem                          /* (i/o)   :static memory (18 words)                  */

+	     );

+

+void Az_isp(

+		Word16 a[],                           /* (i) Q12 : predictor coefficients                 */

+		Word16 isp[],                         /* (o) Q15 : Immittance spectral pairs              */

+		Word16 old_isp[]                      /* (i)     : old isp[] (in case not found M roots)  */

+	   );

+

+void Isp_Az(

+		Word16 isp[],                         /* (i) Q15 : Immittance spectral pairs            */

+		Word16 a[],                           /* (o) Q12 : predictor coefficients (order = M)   */

+		Word16 m,

+		Word16 adaptive_scaling               /* (i) 0   : adaptive scaling disabled */

+		/*     1   : adaptive scaling enabled  */

+	   );

+

+void Isp_isf(

+		Word16 isp[],                         /* (i) Q15 : isp[m] (range: -1<=val<1)                */

+		Word16 isf[],                         /* (o) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */

+		Word16 m                              /* (i)     : LPC order                                */

+	    );

+

+void Isf_isp(

+		Word16 isf[],                         /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */

+		Word16 isp[],                         /* (o) Q15 : isp[m] (range: -1<=val<1)                */

+		Word16 m                              /* (i)     : LPC order                                */

+	    );

+

+void Int_isp(

+		Word16 isp_old[],                     /* input : isps from past frame              */

+		Word16 isp_new[],                     /* input : isps from present frame           */

+		Word16 frac[],                        /* input : fraction for 3 first subfr (Q15)  */

+		Word16 Az[]                           /* output: LP coefficients in 4 subframes    */

+	    );

+

+void Weight_a(

+		Word16 a[],                           /* (i) Q12 : a[m+1]  LPC coefficients             */

+		Word16 ap[],                          /* (o) Q12 : Spectral expanded LPC coefficients   */

+		Word16 gamma,                         /* (i) Q15 : Spectral expansion factor.           */

+		Word16 m                              /* (i)     : LPC order.                           */

+	     );

+

+

+/*-----------------------------------------------------------------*

+ *                        isf quantizers                           *

+ *-----------------------------------------------------------------*/

+

+void Qpisf_2s_46b(

+		Word16 * isf1,                        /* (i) Q15 : ISF in the frequency domain (0..0.5) */

+		Word16 * isf_q,                       /* (o) Q15 : quantized ISF               (0..0.5) */

+		Word16 * past_isfq,                   /* (io)Q15 : past ISF quantizer                   */

+		Word16 * indice,                      /* (o)     : quantization indices                 */

+		Word16 nb_surv                        /* (i)     : number of survivor (1, 2, 3 or 4)    */

+		);

+

+void Qpisf_2s_36b(

+		Word16 * isf1,                        /* (i) Q15 : ISF in the frequency domain (0..0.5) */

+		Word16 * isf_q,                       /* (o) Q15 : quantized ISF               (0..0.5) */

+		Word16 * past_isfq,                   /* (io)Q15 : past ISF quantizer                   */

+		Word16 * indice,                      /* (o)     : quantization indices                 */

+		Word16 nb_surv                        /* (i)     : number of survivor (1, 2, 3 or 4)    */

+		);

+

+void Dpisf_2s_46b(

+		Word16 * indice,                      /* input:  quantization indices                       */

+		Word16 * isf_q,                       /* output: quantized ISF in frequency domain (0..0.5) */

+		Word16 * past_isfq,                   /* i/0   : past ISF quantizer                    */

+		Word16 * isfold,                      /* input : past quantized ISF                    */

+		Word16 * isf_buf,                     /* input : isf buffer                                                        */

+		Word16 bfi,                           /* input : Bad frame indicator                   */

+		Word16 enc_dec

+		);

+

+void Dpisf_2s_36b(

+		Word16 * indice,                      /* input:  quantization indices                       */

+		Word16 * isf_q,                       /* output: quantized ISF in frequency domain (0..0.5) */

+		Word16 * past_isfq,                   /* i/0   : past ISF quantizer                    */

+		Word16 * isfold,                      /* input : past quantized ISF                    */

+		Word16 * isf_buf,                     /* input : isf buffer                                                        */

+		Word16 bfi,                           /* input : Bad frame indicator                   */

+		Word16 enc_dec

+		);

+

+void Qisf_ns(

+		Word16 * isf1,                        /* input : ISF in the frequency domain (0..0.5) */

+		Word16 * isf_q,                       /* output: quantized ISF                        */

+		Word16 * indice                       /* output: quantization indices                 */

+	    );

+

+void Disf_ns(

+		Word16 * indice,                      /* input:  quantization indices                  */

+		Word16 * isf_q                        /* input : ISF in the frequency domain (0..0.5)  */

+	    );

+

+Word16 Sub_VQ(                             /* output: return quantization index     */

+		Word16 * x,                           /* input : ISF residual vector           */

+		Word16 * dico,                        /* input : quantization codebook         */

+		Word16 dim,                           /* input : dimention of vector           */

+		Word16 dico_size,                     /* input : size of quantization codebook */

+		Word32 * distance                     /* output: error of quantization         */

+	     );

+

+void Reorder_isf(

+		Word16 * isf,                         /* (i/o) Q15: ISF in the frequency domain (0..0.5) */

+		Word16 min_dist,                      /* (i) Q15  : minimum distance to keep             */

+		Word16 n                              /* (i)      : number of ISF                        */

+		);

+

+/*-----------------------------------------------------------------*

+ *                       filter prototypes                         *

+ *-----------------------------------------------------------------*/

+

+void Init_Decim_12k8(

+		Word16 mem[]                          /* output: memory (2*NB_COEF_DOWN) set to zeros */

+		);

+void Decim_12k8(

+		Word16 sig16k[],                      /* input:  signal to downsampling  */

+		Word16 lg,                            /* input:  length of input         */

+		Word16 sig12k8[],                     /* output: decimated signal        */

+		Word16 mem[]                          /* in/out: memory (2*NB_COEF_DOWN) */

+	       );

+

+void Init_HP50_12k8(Word16 mem[]);

+void HP50_12k8(

+		Word16 signal[],                      /* input/output signal */

+		Word16 lg,                            /* lenght of signal    */

+		Word16 mem[]                          /* filter memory [6]   */

+	      );

+void Init_HP400_12k8(Word16 mem[]);

+void HP400_12k8(

+		Word16 signal[],                      /* input/output signal */

+		Word16 lg,                            /* lenght of signal    */

+		Word16 mem[]                          /* filter memory [6]   */

+	       );

+

+void Init_Filt_6k_7k(Word16 mem[]);

+void Filt_6k_7k(

+		Word16 signal[],                      /* input:  signal                  */

+		Word16 lg,                            /* input:  length of input         */

+		Word16 mem[]                          /* in/out: memory (size=30)        */

+	       );

+void Filt_6k_7k_asm(

+		Word16 signal[],                      /* input:  signal                  */

+		Word16 lg,                            /* input:  length of input         */

+		Word16 mem[]                          /* in/out: memory (size=30)        */

+	       );

+

+void LP_Decim2(

+		Word16 x[],                           /* in/out: signal to process         */

+		Word16 l,                             /* input : size of filtering         */

+		Word16 mem[]                          /* in/out: memory (size=3)           */

+	      );

+

+void Preemph(

+		Word16 x[],                           /* (i/o)   : input signal overwritten by the output */

+		Word16 mu,                            /* (i) Q15 : preemphasis coefficient                */

+		Word16 lg,                            /* (i)     : lenght of filtering                    */

+		Word16 * mem                          /* (i/o)   : memory (x[-1])                         */

+	    );

+void Preemph2(

+		Word16 x[],                           /* (i/o)   : input signal overwritten by the output */

+		Word16 mu,                            /* (i) Q15 : preemphasis coefficient                */

+		Word16 lg,                            /* (i)     : lenght of filtering                    */

+		Word16 * mem                          /* (i/o)   : memory (x[-1])                         */

+	     );

+void Deemph(

+		Word16 x[],                           /* (i/o)   : input signal overwritten by the output */

+		Word16 mu,                            /* (i) Q15 : deemphasis factor                      */

+		Word16 L,                             /* (i)     : vector size                            */

+		Word16 * mem                          /* (i/o)   : memory (y[-1])                         */

+	   );

+void Deemph2(

+		Word16 x[],                           /* (i/o)   : input signal overwritten by the output */

+		Word16 mu,                            /* (i) Q15 : deemphasis factor                      */

+		Word16 L,                             /* (i)     : vector size                            */

+		Word16 * mem                          /* (i/o)   : memory (y[-1])                         */

+	    );

+void Deemph_32(

+		Word16 x_hi[],                        /* (i)     : input signal (bit31..16) */

+		Word16 x_lo[],                        /* (i)     : input signal (bit15..4)  */

+		Word16 y[],                           /* (o)     : output signal (x16)      */

+		Word16 mu,                            /* (i) Q15 : deemphasis factor        */

+		Word16 L,                             /* (i)     : vector size              */

+		Word16 * mem                          /* (i/o)   : memory (y[-1])           */

+	      );

+

+void Deemph_32_asm(

+		Word16 x_hi[],                        /* (i)     : input signal (bit31..16) */

+		Word16 x_lo[],                        /* (i)     : input signal (bit15..4)  */

+		Word16 y[],                           /* (o)     : output signal (x16)      */

+		Word16 * mem                          /* (i/o)   : memory (y[-1])           */

+	      );

+

+void Convolve(

+		Word16 x[],                           /* (i)     : input vector                              */

+		Word16 h[],                           /* (i) Q15    : impulse response                       */

+		Word16 y[],                           /* (o) 12 bits: output vector                          */

+		Word16 L                              /* (i)     : vector size                               */

+	     );

+

+void Convolve_asm(

+		Word16 x[],                           /* (i)     : input vector                              */

+		Word16 h[],                           /* (i) Q15    : impulse response                       */

+		Word16 y[],                           /* (o) 12 bits: output vector                          */

+		Word16 L                              /* (i)     : vector size                               */

+	     );

+

+void Residu(

+		Word16 a[],                           /* (i) Q12 : prediction coefficients                     */

+		Word16 x[],                           /* (i)     : speech (values x[-m..-1] are needed         */

+		Word16 y[],                           /* (o)     : residual signal                             */

+		Word16 lg                             /* (i)     : size of filtering                           */

+		);

+

+void Residu_opt(

+		Word16 a[],                           /* (i) Q12 : prediction coefficients                     */

+		Word16 x[],                           /* (i)     : speech (values x[-m..-1] are needed         */

+		Word16 y[],                           /* (o)     : residual signal                             */

+		Word16 lg                             /* (i)     : size of filtering                           */

+		);

+

+void Syn_filt(

+	Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients           */

+	Word16 x[],                           /* (i)     : input signal                             */

+	Word16 y[],                           /* (o)     : output signal                            */

+	Word16 lg,                            /* (i)     : size of filtering                        */

+	Word16 mem[],                         /* (i/o)   : memory associated with this filtering.   */

+	Word16 update                         /* (i)     : 0=no update, 1=update of memory.         */

+	);

+

+void Syn_filt_asm(

+	Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients           */

+	Word16 x[],                           /* (i)     : input signal                             */

+	Word16 y[],                           /* (o)     : output signal                            */

+	Word16 mem[]                          /* (i/o)   : memory associated with this filtering.   */

+	);

+

+void Syn_filt_32(

+	Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients */

+	Word16 m,                             /* (i)     : order of LP filter             */

+	Word16 exc[],                         /* (i) Qnew: excitation (exc[i] >> Qnew)    */

+	Word16 Qnew,                          /* (i)     : exc scaling = 0(min) to 8(max) */

+	Word16 sig_hi[],                      /* (o) /16 : synthesis high                 */

+	Word16 sig_lo[],                      /* (o) /16 : synthesis low                  */

+	Word16 lg                             /* (i)     : size of filtering              */

+	);

+

+void Syn_filt_32_asm(

+	Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients */

+	Word16 m,                             /* (i)     : order of LP filter             */

+	Word16 exc[],                         /* (i) Qnew: excitation (exc[i] >> Qnew)    */

+	Word16 Qnew,                          /* (i)     : exc scaling = 0(min) to 8(max) */

+	Word16 sig_hi[],                      /* (o) /16 : synthesis high                 */

+	Word16 sig_lo[],                      /* (o) /16 : synthesis low                  */

+	Word16 lg                             /* (i)     : size of filtering              */

+	);

+/*-----------------------------------------------------------------*

+ *                       pitch prototypes                          *

+ *-----------------------------------------------------------------*/

+

+Word16 Pitch_ol(                           /* output: open loop pitch lag                        */

+     Word16 signal[],                      /* input : signal used to compute the open loop pitch */

+/* signal[-pit_max] to signal[-1] should be known */

+     Word16 pit_min,                       /* input : minimum pitch lag                          */

+     Word16 pit_max,                       /* input : maximum pitch lag                          */

+     Word16 L_frame                        /* input : length of frame to compute pitch           */

+);

+

+Word16 Pitch_med_ol(                       /* output: open loop pitch lag                        */

+     Word16 wsp[],                         /* input : signal used to compute the open loop pitch */

+                                           /* wsp[-pit_max] to wsp[-1] should be known   */

+     Coder_State *st,                      /* i/o : global codec structure */

+     Word16 L_frame                        /* input : length of frame to compute pitch           */

+);

+

+Word16 Med_olag(                           /* output : median of  5 previous open-loop lags       */

+     Word16 prev_ol_lag,                   /* input  : previous open-loop lag                     */

+     Word16 old_ol_lag[5]

+);

+

+void Init_Hp_wsp(Word16 mem[]);

+void scale_mem_Hp_wsp(Word16 mem[], Word16 exp);

+void Hp_wsp(

+     Word16 wsp[],                         /* i   : wsp[]  signal       */

+     Word16 hp_wsp[],                      /* o   : hypass wsp[]        */

+     Word16 lg,                            /* i   : lenght of signal    */

+     Word16 mem[]                          /* i/o : filter memory [9]   */

+);

+

+Word16 Pitch_fr4(                          /* (o)     : pitch period.                         */

+     Word16 exc[],                         /* (i)     : excitation buffer                     */

+     Word16 xn[],                          /* (i)     : target vector                         */

+     Word16 h[],                           /* (i) Q15 : impulse response of synth/wgt filters */

+     Word16 t0_min,                        /* (i)     : minimum value in the searched range.  */

+     Word16 t0_max,                        /* (i)     : maximum value in the searched range.  */

+     Word16 * pit_frac,                    /* (o)     : chosen fraction (0, 1, 2 or 3).       */

+     Word16 i_subfr,                       /* (i)     : indicator for first subframe.         */

+     Word16 t0_fr2,                        /* (i)     : minimum value for resolution 1/2      */

+     Word16 t0_fr1,                        /* (i)     : minimum value for resolution 1        */

+     Word16 L_subfr                        /* (i)     : Length of subframe                    */

+);

+void Pred_lt4(

+     Word16 exc[],                         /* in/out: excitation buffer */

+     Word16 T0,                            /* input : integer pitch lag */

+     Word16 frac,                          /* input : fraction of lag   */

+     Word16 L_subfr                        /* input : subframe size     */

+);

+

+void pred_lt4_asm(

+     Word16 exc[],                         /* in/out: excitation buffer */

+     Word16 T0,                            /* input : integer pitch lag */

+     Word16 frac,                          /* input : fraction of lag   */

+     Word16 L_subfr                        /* input : subframe size     */

+);

+

+/*-----------------------------------------------------------------*

+ *                       gain prototypes                           *

+ *-----------------------------------------------------------------*/

+

+Word16 G_pitch(                            /* (o) Q14 : Gain of pitch lag saturated to 1.2   */

+     Word16 xn[],                          /* (i)     : Pitch target.                        */

+     Word16 y1[],                          /* (i)     : filtered adaptive codebook.          */

+     Word16 g_coeff[],                     /* : Correlations need for gain quantization. */

+     Word16 L_subfr                        /* : Length of subframe.                  */

+);

+void Init_Q_gain2(

+     Word16 * mem                          /* output  :static memory (2 words)      */

+);

+Word16 Q_gain2(                            /* Return index of quantization.        */

+     Word16 xn[],                          /* (i) Q_xn:Target vector.               */

+     Word16 y1[],                          /* (i) Q_xn:Adaptive codebook.           */

+     Word16 Q_xn,                          /* (i)     :xn and y1 format             */

+     Word16 y2[],                          /* (i) Q9  :Filtered innovative vector.  */

+     Word16 code[],                        /* (i) Q9  :Innovative vector.           */

+     Word16 g_coeff[],                     /* (i)     :Correlations <xn y1> <y1 y1> */

+/* Compute in G_pitch().        */

+     Word16 L_subfr,                       /* (i)     :Subframe lenght.             */

+     Word16 nbits,                         /* (i)     : number of bits (6 or 7)     */

+     Word16 * gain_pit,                    /* (i/o)Q14:Pitch gain.                  */

+     Word32 * gain_cod,                    /* (o) Q16 :Code gain.                   */

+     Word16 gp_clip,                       /* (i)     : Gp Clipping flag            */

+     Word16 * mem                          /* (i/o)   :static memory (2 words)      */

+);

+

+void Init_D_gain2(

+     Word16 * mem                          /* output  :static memory (4 words)      */

+);

+void D_gain2(

+     Word16 index,                         /* (i)     :index of quantization.       */

+     Word16 nbits,                         /* (i)     : number of bits (6 or 7)     */

+     Word16 code[],                        /* (i) Q9  :Innovative vector.           */

+     Word16 L_subfr,                       /* (i)     :Subframe lenght.             */

+     Word16 * gain_pit,                    /* (o) Q14 :Pitch gain.                  */

+     Word32 * gain_cod,                    /* (o) Q16 :Code gain.                   */

+     Word16 bfi,                           /* (i)     :bad frame indicator          */

+     Word16 prev_bfi,                      /* (i) : Previous BF indicator      */

+     Word16 state,                         /* (i) : State of BFH               */

+     Word16 unusable_frame,                /* (i) : UF indicator            */

+     Word16 vad_hist,                      /* (i)         :number of non-speech frames  */

+     Word16 * mem                          /* (i/o)   :static memory (4 words)      */

+);

+

+/*-----------------------------------------------------------------*

+ *                       acelp prototypes                          *

+ *-----------------------------------------------------------------*/

+

+void cor_h_x(

+     Word16 h[],                           /* (i) Q12 : impulse response of weighted synthesis filter */

+     Word16 x[],                           /* (i) Q0  : target vector                                 */

+     Word16 dn[]                           /* (o) <12bit : correlation between target and h[]         */

+);

+void ACELP_2t64_fx(

+     Word16 dn[],                          /* (i) <12b : correlation between target x[] and H[]      */

+     Word16 cn[],                          /* (i) <12b : residual after long term prediction         */

+     Word16 H[],                           /* (i) Q12: impulse response of weighted synthesis filter */

+     Word16 code[],                        /* (o) Q9 : algebraic (fixed) codebook excitation         */

+     Word16 y[],                           /* (o) Q9 : filtered fixed codebook excitation            */

+     Word16 * index                        /* (o) : index (12): 5+1+5+1 = 11 bits.                     */

+);

+

+void ACELP_4t64_fx(

+     Word16 dn[],                          /* (i) <12b : correlation between target x[] and H[]      */

+     Word16 cn[],                          /* (i) <12b : residual after long term prediction         */

+     Word16 H[],                           /* (i) Q12: impulse response of weighted synthesis filter */

+     Word16 code[],                        /* (o) Q9 : algebraic (fixed) codebook excitation         */

+     Word16 y[],                           /* (o) Q9 : filtered fixed codebook excitation            */

+     Word16 nbbits,                        /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits                */

+     Word16 ser_size,                      /* (i) : bit rate                                         */

+     Word16 _index[]                       /* (o) : index (20): 5+5+5+5 = 20 bits.                   */

+					   /* (o) : index (36): 9+9+9+9 = 36 bits.                   */

+					   /* (o) : index (44): 13+9+13+9 = 44 bits.                 */

+					   /* (o) : index (52): 13+13+13+13 = 52 bits.               */

+					   /* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits.       */

+					   /* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits.     */

+					   /* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits.   */

+);

+

+void Pit_shrp(

+     Word16 * x,                           /* in/out: impulse response (or algebraic code) */

+     Word16 pit_lag,                       /* input : pitch lag                            */

+     Word16 sharp,                         /* input : pitch sharpening factor (Q15)        */

+     Word16 L_subfr                        /* input : subframe size                        */

+);

+

+

+/*-----------------------------------------------------------------*

+ *                        others prototypes                        *

+ *-----------------------------------------------------------------*/

+

+void Copy(

+     Word16 x[],                           /* (i)   : input vector   */

+     Word16 y[],                           /* (o)   : output vector  */

+     Word16 L                              /* (i)   : vector length  */

+);

+void Set_zero(

+     Word16 x[],                           /* (o)    : vector to clear     */

+     Word16 L                              /* (i)    : length of vector    */

+);

+void Updt_tar(

+     Word16 * x,                           /* (i) Q0  : old target (for pitch search)     */

+     Word16 * x2,                          /* (o) Q0  : new target (for codebook search)  */

+     Word16 * y,                           /* (i) Q0  : filtered adaptive codebook vector */

+     Word16 gain,                          /* (i) Q14 : adaptive codebook gain            */

+     Word16 L                              /* (i)     : subframe size                     */

+);

+Word16 voice_factor(                       /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */

+     Word16 exc[],                         /* (i) Q_exc: pitch excitation                */

+     Word16 Q_exc,                         /* (i)     : exc format                       */

+     Word16 gain_pit,                      /* (i) Q14 : gain of pitch                    */

+     Word16 code[],                        /* (i) Q9  : Fixed codebook excitation        */

+     Word16 gain_code,                     /* (i) Q0  : gain of code                     */

+     Word16 L_subfr                        /* (i)     : subframe length                  */

+);

+void Scale_sig(

+     Word16 x[],                           /* (i/o) : signal to scale               */

+     Word16 lg,                            /* (i)   : size of x[]                   */

+     Word16 exp                            /* (i)   : exponent: x = round(x << exp) */

+);

+

+void Scale_sig_opt(

+     Word16 x[],                           /* (i/o) : signal to scale               */

+     Word16 lg,                            /* (i)   : size of x[]                   */

+     Word16 exp                            /* (i)   : exponent: x = round(x << exp) */

+);

+

+Word16 Random(Word16 * seed);

+

+void Init_gp_clip(

+     Word16 mem[]                          /* (o) : memory of gain of pitch clipping algorithm */

+);

+Word16 Gp_clip(

+     Word16 mem[]                          /* (i/o) : memory of gain of pitch clipping algorithm */

+);

+void Gp_clip_test_isf(

+     Word16 isf[],                         /* (i)   : isf values (in frequency domain)           */

+     Word16 mem[]                          /* (i/o) : memory of gain of pitch clipping algorithm */

+);

+void Gp_clip_test_gain_pit(

+     Word16 gain_pit,                      /* (i)   : gain of quantized pitch                    */

+     Word16 mem[]                          /* (i/o) : memory of gain of pitch clipping algorithm */

+);

+

+

+#endif   //__ACELP_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
new file mode 100644
index 0000000..6a2f860
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
@@ -0,0 +1,1094 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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 __BASIC_OP_H__

+#define __BASIC_OP_H__

+

+#include <stdio.h>

+#include <stdlib.h>

+#include "typedef.h"

+

+#define MAX_32 (Word32)0x7fffffffL

+#define MIN_32 (Word32)0x80000000L

+

+#define MAX_16 (Word16)+32767	/* 0x7fff */

+#define MIN_16 (Word16)-32768	/* 0x8000 */

+

+

+#ifdef LINUX

+#define  static_vo  static __inline__

+#else

+#define  static_vo  static __inline

+#endif 

+

+#define saturate(L_var1) (((L_var1) > 0X00007fffL) ? (MAX_16): (((L_var1) < (Word32) 0xffff8000L) ? (MIN_16): ((L_var1) & 0xffff)))

+

+#define abs_s(x)       ((Word16)(((x) != MIN_16) ? (((x) >= 0) ? (x) : (-(x))) : MAX_16))  /* Short abs,           1   */

+#define L_deposit_h(x) (((Word32)(x)) << 16)                                               /* 16 bit var1 -> MSB,     2 */

+#define L_deposit_l(x) ((Word32)(x))                                                       /* 16 bit var1 -> LSB,     2 */

+#define L_abs(x) (((x) != MIN_32) ? (((x) >= 0) ? (x) : (-(x))) : MAX_32)                  /* Long abs,              3*/

+#define negate(var1) ((Word16)(((var1) == MIN_16) ? MAX_16 : (-(var1))))                   /* Short negate,        1*/

+#define L_negate(L_var1) (((L_var1) == (MIN_32)) ? (MAX_32) : (-(L_var1)))                 /* Long negate,     2*/

+

+

+#define extract_h(a)			((Word16)(a >> 16))

+#define extract_l(x)            	(Word16)((x))

+#define add1(a,b)			(a + b)

+#define vo_L_msu(a,b,c)			( a - (( b * c ) << 1) )

+#define vo_mult32(a, b)         ((a) * (b))

+#define vo_mult(a,b)			(( a * b ) >> 15 )

+#define	vo_L_mult(a,b)	    		(((a) * (b)) << 1)

+#define vo_shr_r(var1, var2)   		((var1+((Word16)(1L<<(var2-1))))>>var2)

+#define vo_sub(a,b)			(a - b)

+#define vo_L_deposit_h(a)		((Word32)((a) << 16))

+#define vo_round(a)			((a + 0x00008000) >> 16)

+#define vo_extract_l(a)			((Word16)(a))

+#define vo_L_add(a,b)			(a + b)

+#define vo_L_sub(a,b)			(a - b)

+#define vo_mult_r(a,b)			((( a * b ) + 0x4000 ) >> 15 )

+#define vo_negate(a)		        (-a)

+#define vo_L_shr_r(L_var1, var2)        ((L_var1+((Word32)(1L<<(var2-1))))>>var2)

+

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Prototypes for basic arithmetic operators                               |

+|___________________________________________________________________________|

+*/

+static_vo Word16 add (Word16 var1, Word16 var2);				/* Short add,1 */

+static_vo Word16 sub (Word16 var1, Word16 var2);				/* Short sub,1 */

+static_vo Word16 shl (Word16 var1, Word16 var2);                                /* Short shift left,    1   */

+static_vo Word16 shr (Word16 var1, Word16 var2);                                /* Short shift right,   1   */

+static_vo Word16 mult (Word16 var1, Word16 var2);                               /* Short mult,          1   */

+static_vo Word32 L_mult (Word16 var1, Word16 var2);                             /* Long mult,           1   */

+static_vo Word16 voround (Word32 L_var1);                                       /* Round,               1   */

+static_vo Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2);            	/* Mac,  1  */

+static_vo Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2);   		/* Msu,  1  */

+static_vo Word32 L_add (Word32 L_var1, Word32 L_var2);   		 	/* Long add,        2 */

+static_vo Word32 L_sub (Word32 L_var1, Word32 L_var2);   			/* Long sub,        2 */

+static_vo Word16 mult_r (Word16 var1, Word16 var2);      		 	/* Mult with round, 2 */

+static_vo Word32 L_shl2(Word32 L_var1, Word16 var2);             		/* var2 > 0*/

+static_vo Word32 L_shl (Word32 L_var1, Word16 var2);    	 	 	/* Long shift left, 2 */

+static_vo Word32 L_shr (Word32 L_var1, Word16 var2);    	 	 	/* Long shift right, 2*/

+static_vo Word32 L_shr_r (Word32 L_var1, Word16 var2); 				/* Long shift right with round,  3   */

+static_vo Word16 norm_s (Word16 var1);             				/* Short norm,           15  */

+static_vo Word16 div_s (Word16 var1, Word16 var2); 				/* Short division,       18  */

+static_vo Word16 norm_l (Word32 L_var1);           				/* Long norm,            30  */   

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Functions                                                               |

+|___________________________________________________________________________|

+*/

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : add                                                     |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|    Performs the addition (var1+var2) with overflow control and saturation;|

+|    the 16 bit result is set at +32767 when overflow occurs or at -32768   |

+|    when underflow occurs.                                                 |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+|___________________________________________________________________________|

+*/

+static_vo Word16 add (Word16 var1, Word16 var2)

+{

+	Word16 var_out;

+	Word32 L_sum;

+	L_sum = (Word32) var1 + var2;

+	var_out = saturate (L_sum);

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : sub                                                     |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|    Performs the subtraction (var1+var2) with overflow control and satu-   |

+|    ration; the 16 bit result is set at +32767 when overflow occurs or at  |

+|    -32768 when underflow occurs.                                          |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 sub (Word16 var1, Word16 var2)

+{

+	Word16 var_out;

+	Word32 L_diff;

+	L_diff = (Word32) var1 - var2;

+	var_out = saturate (L_diff);

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : shl                                                     |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|

+|   the var2 LSB of the result. If var2 is negative, arithmetically shift   |

+|   var1 right by -var2 with sign extension. Saturate the result in case of |

+|   underflows or overflows.                                                |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 shl (Word16 var1, Word16 var2)

+{

+	Word16 var_out;

+	Word32 result;

+	if (var2 < 0)

+	{

+		if (var2 < -16)

+			var2 = -16;

+		var_out = var1 >> ((Word16)-var2);

+	}

+	else

+	{

+		result = (Word32) var1 *((Word32) 1 << var2);

+		if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))

+		{

+			var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);

+		}

+		else

+		{

+			var_out = extract_l (result);

+		}

+	}

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : shr                                                     |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Arithmetically shift the 16 bit input var1 right var2 positions with    |

+|   sign extension. If var2 is negative, arithmetically shift var1 left by  |

+|   -var2 with sign extension. Saturate the result in case of underflows or |

+|   overflows.                                                              |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 shr (Word16 var1, Word16 var2)

+{

+	Word16 var_out;

+	if (var2 < 0)

+	{

+		if (var2 < -16)

+			var2 = -16;

+		var_out = shl(var1, (Word16)-var2);

+	}

+	else

+	{

+		if (var2 >= 15)

+		{

+			var_out = (Word16)((var1 < 0) ? -1 : 0);

+		}

+		else

+		{

+			if (var1 < 0)

+			{

+				var_out = (Word16)(~((~var1) >> var2));

+			}

+			else

+			{

+				var_out = (Word16)(var1 >> var2);

+			}

+		}

+	}

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : mult                                                    |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|    Performs the multiplication of var1 by var2 and gives a 16 bit result  |

+|    which is scaled i.e.:                                                  |

+|             mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and  |

+|             mult(-32768,-32768) = 32767.                                  |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 mult (Word16 var1, Word16 var2)

+{

+	Word16 var_out;

+	Word32 L_product;

+	L_product = (Word32) var1 *(Word32) var2;

+	L_product = (L_product & (Word32) 0xffff8000L) >> 15;

+	if (L_product & (Word32) 0x00010000L)

+		L_product = L_product | (Word32) 0xffff0000L;

+	var_out = saturate (L_product);

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : L_mult                                                  |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   L_mult is the 32 bit result of the multiplication of var1 times var2    |

+|   with one shift left i.e.:                                               |

+|        L_mult(var1,var2) = L_shl((var1 times var2),1) and                   |

+|        L_mult(-32768,-32768) = 2147483647.                                |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    L_var_out                                                              |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+|___________________________________________________________________________|

+*/

+

+static_vo Word32 L_mult (Word16 var1, Word16 var2)

+{

+	Word32 L_var_out;

+	L_var_out = (Word32) var1 *(Word32) var2;

+	if (L_var_out != (Word32) 0x40000000L)

+	{

+		L_var_out *= 2;

+	}

+	else

+	{

+		L_var_out = MAX_32;

+	}

+	return (L_var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : round                                                   |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Round the lower 16 bits of the 32 bit input number into the MS 16 bits  |

+|   with saturation. Shift the resulting bits right by 16 and return the 16 |

+|   bit number:                                                             |

+|               round(L_var1) = extract_h(L_add(L_var1,32768))              |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var1                                                                 |

+|             32 bit long signed integer (Word32 ) whose value falls in the |

+|             range : 0x8000 0000 <= L_var1 <= 0x7fff ffff.                 |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 voround (Word32 L_var1)

+{

+	Word16 var_out;

+	Word32 L_rounded;

+	L_rounded = L_add (L_var1, (Word32) 0x00008000L);

+	var_out = extract_h (L_rounded);

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : L_mac                                                   |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Multiply var1 by var2 and shift the result left by 1. Add the 32 bit    |

+|   result to L_var3 with saturation, return a 32 bit result:               |

+|        L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)).         |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var3   32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    L_var_out                                                              |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+|___________________________________________________________________________|

+*/

+

+static_vo Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)

+{

+	Word32 L_var_out;

+	Word32 L_product;

+	L_product = ((var1 * var2) << 1);

+	L_var_out = L_add (L_var3, L_product);

+	return (L_var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : L_msu                                                   |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Multiply var1 by var2 and shift the result left by 1. Subtract the 32   |

+|   bit result to L_var3 with saturation, return a 32 bit result:           |

+|        L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)).         |

+|                                                                           |

+|   Complexity weight : 1                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var3   32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    L_var_out                                                              |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+|___________________________________________________________________________|

+*/

+

+static_vo Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)

+{

+	Word32 L_var_out;

+	Word32 L_product;

+	L_product = (var1 * var2)<<1;

+	L_var_out = L_sub (L_var3, L_product);

+	return (L_var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : L_add                                                   |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   32 bits addition of the two 32 bits variables (L_var1+L_var2) with      |

+|   overflow control and saturation; the result is set at +2147483647 when  |

+|   overflow occurs or at -2147483648 when underflow occurs.                |

+|                                                                           |

+|   Complexity weight : 2                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+|                                                                           |

+|    L_var2   32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    L_var_out                                                              |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+|___________________________________________________________________________|

+*/

+

+static_vo Word32 L_add (Word32 L_var1, Word32 L_var2)

+{

+	Word32 L_var_out;

+	L_var_out = L_var1 + L_var2;

+	if (((L_var1 ^ L_var2) & MIN_32) == 0)

+	{

+		if ((L_var_out ^ L_var1) & MIN_32)

+		{

+			L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;

+		}

+	}

+	return (L_var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : L_sub                                                   |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with   |

+|   overflow control and saturation; the result is set at +2147483647 when  |

+|   overflow occurs or at -2147483648 when underflow occurs.                |

+|                                                                           |

+|   Complexity weight : 2                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+|                                                                           |

+|    L_var2   32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    L_var_out                                                              |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+|___________________________________________________________________________|

+*/

+

+static_vo Word32 L_sub (Word32 L_var1, Word32 L_var2)

+{

+	Word32 L_var_out;

+	L_var_out = L_var1 - L_var2;

+	if (((L_var1 ^ L_var2) & MIN_32) != 0)

+	{

+		if ((L_var_out ^ L_var1) & MIN_32)

+		{

+			L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;

+		}

+	}

+	return (L_var_out);

+}

+

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : mult_r                                                  |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Same as mult with rounding, i.e.:                                       |

+|     mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and  |

+|     mult_r(-32768,-32768) = 32767.                                        |

+|                                                                           |

+|   Complexity weight : 2                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var_out <= 0x0000 7fff.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 mult_r (Word16 var1, Word16 var2)

+{

+	Word16 var_out;

+	Word32 L_product_arr;

+	L_product_arr = (Word32) var1 *(Word32) var2;       /* product */

+	L_product_arr += (Word32) 0x00004000L;      /* round */

+	L_product_arr &= (Word32) 0xffff8000L;

+	L_product_arr >>= 15;       /* shift */

+	if (L_product_arr & (Word32) 0x00010000L)   /* sign extend when necessary */

+	{

+		L_product_arr |= (Word32) 0xffff0000L;

+	}

+	var_out = saturate (L_product_arr);

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : L_shl                                                   |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero  |

+|   fill the var2 LSB of the result. If var2 is negative, arithmetically    |

+|   shift L_var1 right by -var2 with sign extension. Saturate the result in |

+|   case of underflows or overflows.                                        |

+|                                                                           |

+|   Complexity weight : 2                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    L_var_out                                                              |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+|___________________________________________________________________________|

+*/

+

+static_vo Word32 L_shl (Word32 L_var1, Word16 var2)

+{

+	Word32 L_var_out = 0L;

+	if (var2 <= 0)

+	{

+		if (var2 < -32)

+			var2 = -32;

+		L_var_out = (L_var1 >> (Word16)-var2);

+	}

+	else

+	{

+		for (; var2 > 0; var2--)

+		{

+			if (L_var1 > (Word32) 0X3fffffffL)

+			{

+				L_var_out = MAX_32;

+				break;

+			}

+			else

+			{

+				if (L_var1 < (Word32) 0xc0000000L)

+				{

+					//Overflow = 1;

+					L_var_out = MIN_32;

+					break;

+				}

+			}

+			L_var1 *= 2;

+			L_var_out = L_var1;

+		}

+	}

+	return (L_var_out);

+}

+

+static_vo Word32 L_shl2(Word32 L_var1, Word16 var2)

+{

+	Word32 L_var_out = 0L;

+

+	for (; var2 > 0; var2--)

+	{

+		if (L_var1 > (Word32) 0X3fffffffL)

+		{

+			L_var_out = MAX_32;

+			break;

+		}

+		else

+		{

+			if (L_var1 < (Word32) 0xc0000000L)

+			{

+				L_var_out = MIN_32;

+				break;

+			}

+		}

+		L_var1 <<=1 ;

+		L_var_out = L_var1;

+	}

+	return (L_var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : L_shr                                                   |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Arithmetically shift the 32 bit input L_var1 right var2 positions with  |

+|   sign extension. If var2 is negative, arithmetically shift L_var1 left   |

+|   by -var2 and zero fill the -var2 LSB of the result. Saturate the result |

+|   in case of underflows or overflows.                                     |

+|                                                                           |

+|   Complexity weight : 2                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var1   32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var3 <= 0x7fff ffff.                 |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    L_var_out                                                              |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= L_var_out <= 0x7fff ffff.              |

+|___________________________________________________________________________|

+*/

+

+static_vo Word32 L_shr (Word32 L_var1, Word16 var2)

+{

+	Word32 L_var_out;

+	if (var2 < 0)

+	{

+		if (var2 < -32)

+			var2 = -32;

+		L_var_out = L_shl2(L_var1, (Word16)-var2);

+	}

+	else

+	{

+		if (var2 >= 31)

+		{

+			L_var_out = (L_var1 < 0L) ? -1 : 0;

+		}

+		else

+		{

+			if (L_var1 < 0)

+			{

+				L_var_out = ~((~L_var1) >> var2);

+			}

+			else

+			{

+				L_var_out = L_var1 >> var2;

+			}

+		}

+	}

+	return (L_var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : L_shr_r                                                 |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Same as L_shr(L_var1,var2) but with rounding. Saturate the result in    |

+|   case of underflows or overflows :                                       |

+|    - If var2 is greater than zero :                                       |

+|          if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|

+|          is equal to zero                                                 |

+|                     then                                                  |

+|                     L_shr_r(L_var1,var2) = L_shr(L_var1,var2)             |

+|                     else                                                  |

+|                     L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1)    |

+|    - If var2 is less than or equal to zero :                              |

+|                     L_shr_r(L_var1,var2) = L_shr(L_var1,var2).            |

+|                                                                           |

+|   Complexity weight : 3                                                   |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var1                                                                 |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    L_var_out                                                              |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= var_out <= 0x7fff ffff.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word32 L_shr_r (Word32 L_var1, Word16 var2)

+{

+	Word32 L_var_out;

+	if (var2 > 31)

+	{

+		L_var_out = 0;

+	}

+	else

+	{

+		L_var_out = L_shr (L_var1, var2);

+		if (var2 > 0)

+		{

+			if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)

+			{

+				L_var_out++;

+			}

+		}

+	}

+	return (L_var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : norm_s                                                  |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Produces the number of left shift needed to normalize the 16 bit varia- |

+|   ble var1 for positive values on the interval with minimum of 16384 and  |

+|   maximum of 32767, and for negative values on the interval with minimum  |

+|   of -32768 and maximum of -16384; in order to normalize the result, the  |

+|   following operation must be done :                                      |

+|                    norm_var1 = shl(var1,norm_s(var1)).                    |

+|                                                                           |

+|   Complexity weight : 15                                                  |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0xffff 8000 <= var1 <= 0x0000 7fff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0x0000 0000 <= var_out <= 0x0000 000f.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 norm_s (Word16 var1)

+{

+	Word16 var_out = 0;

+	if (var1 == 0)

+	{

+		var_out = 0;

+	}

+	else

+	{

+		if (var1 == -1)

+		{

+			var_out = 15;

+		}

+		else

+		{

+			if (var1 < 0)

+			{

+				var1 = (Word16)~var1;

+			}

+			for (var_out = 0; var1 < 0x4000; var_out++)

+			{

+				var1 <<= 1;

+			}

+		}

+	}

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : div_s                                                   |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Produces a result which is the fractional integer division of var1  by  |

+|   var2; var1 and var2 must be positive and var2 must be greater or equal  |

+|   to var1; the result is positive (leading bit equal to 0) and truncated  |

+|   to 16 bits.                                                             |

+|   If var1 = var2 then div(var1,var2) = 32767.                             |

+|                                                                           |

+|   Complexity weight : 18                                                  |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    var1                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0x0000 0000 <= var1 <= var2 and var2 != 0.            |

+|                                                                           |

+|    var2                                                                   |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : var1 <= var2 <= 0x0000 7fff and var2 != 0.            |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0x0000 0000 <= var_out <= 0x0000 7fff.                |

+|             It's a Q15 value (point between b15 and b14).                 |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 div_s (Word16 var1, Word16 var2)

+{

+	Word16 var_out = 0;

+	Word16 iteration;

+	Word32 L_num;

+	Word32 L_denom;

+	if ((var1 < 0) || (var2 < 0))

+	{

+		var_out = MAX_16;

+		return var_out;

+	}

+	if (var2 == 0)

+	{

+		var_out = MAX_16;

+		return var_out;

+	}

+	if (var1 == 0)

+	{

+		var_out = 0;

+	}

+	else

+	{

+		if (var1 == var2)

+		{

+			var_out = MAX_16;

+		}

+		else

+		{

+			L_num = L_deposit_l (var1);

+			L_denom = L_deposit_l(var2);

+			for (iteration = 0; iteration < 15; iteration++)

+			{

+				var_out <<= 1;

+				L_num <<= 1;

+				if (L_num >= L_denom)

+				{

+					L_num -= L_denom;      

+					var_out += 1;          

+				}

+			}

+		}

+	}

+	return (var_out);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : norm_l                                                  |

+|                                                                           |

+|   Purpose :                                                               |

+|                                                                           |

+|   Produces the number of left shifts needed to normalize the 32 bit varia-|

+|   ble L_var1 for positive values on the interval with minimum of          |

+|   1073741824 and maximum of 2147483647, and for negative values on the in-|

+|   terval with minimum of -2147483648 and maximum of -1073741824; in order |

+|   to normalize the result, the following operation must be done :         |

+|                   norm_L_var1 = L_shl(L_var1,norm_l(L_var1)).             |

+|                                                                           |

+|   Complexity weight : 30                                                  |

+|                                                                           |

+|   Inputs :                                                                |

+|                                                                           |

+|    L_var1                                                                 |

+|             32 bit long signed integer (Word32) whose value falls in the  |

+|             range : 0x8000 0000 <= var1 <= 0x7fff ffff.                   |

+|                                                                           |

+|   Outputs :                                                               |

+|                                                                           |

+|    none                                                                   |

+|                                                                           |

+|   Return Value :                                                          |

+|                                                                           |

+|    var_out                                                                |

+|             16 bit short signed integer (Word16) whose value falls in the |

+|             range : 0x0000 0000 <= var_out <= 0x0000 001f.                |

+|___________________________________________________________________________|

+*/

+

+static_vo Word16 norm_l (Word32 L_var1)

+{

+	Word16 var_out = 0;

+	if (L_var1 != 0)

+	{

+		var_out = 31;

+		if (L_var1 != (Word32) 0xffffffffL)

+		{

+			L_var1 ^= (L_var1 >>31);

+			for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)

+			{

+				L_var1 <<= 1;

+			}

+		}

+	}

+	return (var_out);

+}

+

+#endif //__BASIC_OP_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/bits.h b/media/libstagefright/codecs/amrwbenc/inc/bits.h
new file mode 100644
index 0000000..77146de
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/bits.h
@@ -0,0 +1,92 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*--------------------------------------------------------------------------*

+*                         BITS.H                                           *

+*--------------------------------------------------------------------------*

+*       Number of bits for different modes			           *

+*--------------------------------------------------------------------------*/

+

+#ifndef __BITS_H__

+#define __BITS_H__

+

+#include <stdio.h>

+#include "typedef.h"

+#include "cnst.h"

+#include "cod_main.h"

+

+#define NBBITS_7k     132                  /* 6.60k  */

+#define NBBITS_9k     177                  /* 8.85k  */

+#define NBBITS_12k    253                  /* 12.65k */

+#define NBBITS_14k    285                  /* 14.25k */

+#define NBBITS_16k    317                  /* 15.85k */

+#define NBBITS_18k    365                  /* 18.25k */

+#define NBBITS_20k    397                  /* 19.85k */

+#define NBBITS_23k    461                  /* 23.05k */

+#define NBBITS_24k    477                  /* 23.85k */

+

+#define NBBITS_SID    35

+#define NB_BITS_MAX   NBBITS_24k

+

+#define BIT_0     (Word16)-127

+#define BIT_1     (Word16)127

+#define BIT_0_ITU (Word16)0x007F

+#define BIT_1_ITU (Word16)0x0081

+

+#define SIZE_MAX1  (3+NB_BITS_MAX)          /* serial size max */

+#define TX_FRAME_TYPE (Word16)0x6b21

+#define RX_FRAME_TYPE (Word16)0x6b20

+

+static const Word16 nb_of_bits[NUM_OF_MODES] = {

+	NBBITS_7k,

+	NBBITS_9k,

+	NBBITS_12k,

+	NBBITS_14k,

+	NBBITS_16k,

+	NBBITS_18k,

+	NBBITS_20k,

+	NBBITS_23k,

+	NBBITS_24k,

+	NBBITS_SID

+};

+

+/*typedef struct

+{

+Word16 sid_update_counter;

+Word16 sid_handover_debt;

+Word16 prev_ft;

+} TX_State;

+*/

+

+//typedef struct

+//{

+//	Word16 prev_ft;

+//	Word16 prev_mode;

+//} RX_State;

+

+int PackBits(Word16 prms[], Word16 coding_mode, Word16 mode, Coder_State *st);

+

+

+void Parm_serial(

+		Word16 value,                         /* input : parameter value */

+		Word16 no_of_bits,                    /* input : number of bits  */

+		Word16 ** prms

+		);

+

+

+#endif  //__BITS_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/cnst.h b/media/libstagefright/codecs/amrwbenc/inc/cnst.h
new file mode 100644
index 0000000..ffdbd88
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/cnst.h
@@ -0,0 +1,81 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*--------------------------------------------------------------------------*

+ *                         CNST.H                                           *

+ *--------------------------------------------------------------------------*

+ *       Codec constant parameters (coder and decoder)                      *

+ *--------------------------------------------------------------------------*/

+

+#ifndef __CNST_H__

+#define __CNST_H__

+

+#define L_FRAME16k   320                   /* Frame size at 16kHz                        */

+#define L_FRAME      256                   /* Frame size                                 */

+#define L_SUBFR16k   80                    /* Subframe size at 16kHz                     */

+

+#define L_SUBFR      64                    /* Subframe size                              */

+#define NB_SUBFR     4                     /* Number of subframe per frame               */

+

+#define L_NEXT       64                    /* Overhead in LP analysis                    */

+#define L_WINDOW     384                   /* window size in LP analysis                 */

+#define L_TOTAL      384                   /* Total size of speech buffer.               */

+#define M            16                    /* Order of LP filter                         */

+#define M16k         20

+

+#define L_FILT16k    15                    /* Delay of down-sampling filter              */

+#define L_FILT       12                    /* Delay of up-sampling filter                */

+

+#define GP_CLIP      15565                 /* Pitch gain clipping = 0.95 Q14             */

+#define PIT_SHARP    27853                 /* pitch sharpening factor = 0.85 Q15         */

+

+#define PIT_MIN      34                    /* Minimum pitch lag with resolution 1/4      */

+#define PIT_FR2      128                   /* Minimum pitch lag with resolution 1/2      */

+#define PIT_FR1_9b   160                   /* Minimum pitch lag with resolution 1        */

+#define PIT_FR1_8b   92                    /* Minimum pitch lag with resolution 1        */

+#define PIT_MAX      231                   /* Maximum pitch lag                          */

+#define L_INTERPOL   (16+1)                /* Length of filter for interpolation         */

+

+#define OPL_DECIM    2                     /* Decimation in open-loop pitch analysis     */

+

+#define PREEMPH_FAC  22282                 /* preemphasis factor (0.68 in Q15)           */

+#define GAMMA1       30147                 /* Weighting factor (numerator) (0.92 in Q15) */

+#define TILT_FAC     22282                 /* tilt factor (denominator) (0.68 in Q15)    */

+

+#define Q_MAX        8                     /* scaling max for signal (see syn_filt_32)   */

+

+#define RANDOM_INITSEED  21845             /* own random init value                      */

+

+#define L_MEANBUF        3

+#define ONE_PER_MEANBUF 10923

+

+#define MODE_7k       0

+#define MODE_9k       1

+#define MODE_12k      2

+#define MODE_14k      3

+#define MODE_16k      4

+#define MODE_18k      5

+#define MODE_20k      6

+#define MODE_23k      7

+#define MODE_24k      8

+#define MRDTX         9

+#define NUM_OF_MODES  10                   /* see bits.h for bits definition             */

+

+#define EHF_MASK (Word16)0x0008            /* homing frame pattern                       */

+

+#endif //__CNST_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/cod_main.h b/media/libstagefright/codecs/amrwbenc/inc/cod_main.h
new file mode 100644
index 0000000..1fd5787
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/cod_main.h
@@ -0,0 +1,103 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*--------------------------------------------------------------------------*

+ *                         COD_MAIN.H                                       *

+ *--------------------------------------------------------------------------*

+ *       Static memory in the encoder				            *

+ *--------------------------------------------------------------------------*/

+#ifndef __COD_MAIN_H__

+#define __COD_MAIN_H__

+

+#include "cnst.h"                          /* coder constant parameters */

+

+#include "wb_vad.h"

+#include "dtx.h"

+#include "stream.h"

+#include "voAMRWB.h"

+

+typedef struct

+{

+    Word16 mem_decim[2 * L_FILT16k];       /* speech decimated filter memory */

+    Word16 mem_sig_in[6];                  /* hp50 filter memory */

+    Word16 mem_preemph;                    /* speech preemph filter memory */

+    Word16 old_speech[L_TOTAL - L_FRAME];  /* old speech vector at 12.8kHz */

+    Word16 old_wsp[PIT_MAX / OPL_DECIM];   /* old decimated weighted speech vector */

+    Word16 old_exc[PIT_MAX + L_INTERPOL];  /* old excitation vector */

+    Word16 mem_levinson[M + 2];            /* levinson routine memory */

+    Word16 ispold[M];                      /* old isp (immittance spectral pairs) */

+    Word16 ispold_q[M];                    /* quantized old isp */

+    Word16 past_isfq[M];                   /* past isf quantizer */

+    Word16 mem_wsp;                        /* wsp vector memory */

+    Word16 mem_decim2[3];                  /* wsp decimation filter memory */

+    Word16 mem_w0;                         /* target vector memory */

+    Word16 mem_syn[M];                     /* synthesis memory */

+    Word16 tilt_code;                      /* tilt of code */

+    Word16 old_wsp_max;                    /* old wsp maximum value */

+    Word16 old_wsp_shift;                  /* old wsp shift */

+    Word16 Q_old;                          /* old scaling factor */

+    Word16 Q_max[2];                       /* old maximum scaling factor */

+    Word16 gp_clip[2];                     /* gain of pitch clipping memory */

+    Word16 qua_gain[4];                    /* gain quantizer memory */

+

+    Word16 old_T0_med;

+    Word16 ol_gain;

+    Word16 ada_w;

+    Word16 ol_wght_flg;

+    Word16 old_ol_lag[5];

+    Word16 hp_wsp_mem[9];

+    Word16 old_hp_wsp[L_FRAME / OPL_DECIM + (PIT_MAX / OPL_DECIM)];

+    VadVars *vadSt;

+    dtx_encState *dtx_encSt;

+    Word16 first_frame;

+    Word16 isfold[M];                      /* old isf (frequency domain) */

+    Word32 L_gc_thres;                     /* threshold for noise enhancer */

+    Word16 mem_syn_hi[M];                  /* modified synthesis memory (MSB) */

+    Word16 mem_syn_lo[M];                  /* modified synthesis memory (LSB) */

+    Word16 mem_deemph;                     /* speech deemph filter memory */

+    Word16 mem_sig_out[6];                 /* hp50 filter memory for synthesis */

+    Word16 mem_hp400[6];                   /* hp400 filter memory for synthesis */

+    Word16 mem_oversamp[2 * L_FILT];       /* synthesis oversampled filter memory */

+    Word16 mem_syn_hf[M];                  /* HF synthesis memory */

+    Word16 mem_hf[2 * L_FILT16k];          /* HF band-pass filter memory */

+    Word16 mem_hf2[2 * L_FILT16k];         /* HF band-pass filter memory */

+    Word16 seed2;                          /* random memory for HF generation */

+    Word16 vad_hist;

+    Word16 gain_alpha;

+    /*  TX_State structure  */

+	Word16 sid_update_counter;

+    Word16 sid_handover_debt;

+    Word16 prev_ft;

+	Word16 allow_dtx;

+	/*some input/output buffer parameters */

+	unsigned char       *inputStream;

+	int			        inputSize;

+	VOAMRWBMODE  		mode;

+	VOAMRWBFRAMETYPE	frameType;

+	unsigned short      *outputStream;

+	int			        outputSize;

+	FrameStream         *stream;

+	VO_MEM_OPERATOR     *pvoMemop;

+	VO_MEM_OPERATOR     voMemoprator;

+	VO_PTR              hCheck;

+} Coder_State;

+

+typedef void* HAMRENC;

+

+#endif  //__COD_MAIN_H__

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/dtx.h b/media/libstagefright/codecs/amrwbenc/inc/dtx.h
new file mode 100644
index 0000000..e52c2d0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/dtx.h
@@ -0,0 +1,115 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*--------------------------------------------------------------------------*

+ *                         DTX.H					    *

+ *--------------------------------------------------------------------------*

+ *       Static memory, constants and frametypes for the DTX 		    *

+ *--------------------------------------------------------------------------*/

+

+#ifndef __DTX_H__

+#define __DTX_H__

+

+#define DTX_MAX_EMPTY_THRESH 50

+#define DTX_HIST_SIZE 8

+#define DTX_HIST_SIZE_MIN_ONE 7

+#define DTX_ELAPSED_FRAMES_THRESH (24 + 7 -1)

+#define DTX_HANG_CONST 7                   /* yields eight frames of SP HANGOVER  */

+#define INV_MED_THRESH 14564

+#define ISF_GAP  128                       /* 50 */

+#define ONE_MINUS_ISF_GAP 16384 - ISF_GAP

+#define ISF_GAP   128

+#define ISF_DITH_GAP   448

+#define ISF_FACTOR_LOW 256

+#define ISF_FACTOR_STEP 2

+#define GAIN_THR 180

+#define GAIN_FACTOR 75

+

+typedef struct

+{

+    Word16 isf_hist[M * DTX_HIST_SIZE];

+    Word16 log_en_hist[DTX_HIST_SIZE];

+    Word16 hist_ptr;

+    Word16 log_en_index;

+    Word16 cng_seed;

+    /* DTX handler stuff */

+    Word16 dtxHangoverCount;

+    Word16 decAnaElapsedCount;

+    Word32 D[28];

+    Word32 sumD[DTX_HIST_SIZE];

+} dtx_encState;

+

+#define SPEECH 0

+#define DTX 1

+#define DTX_MUTE 2

+

+#define TX_SPEECH 0

+#define TX_SID_FIRST 1

+#define TX_SID_UPDATE 2

+#define TX_NO_DATA 3

+

+#define RX_SPEECH_GOOD 0

+#define RX_SPEECH_PROBABLY_DEGRADED 1

+#define RX_SPEECH_LOST 2

+#define RX_SPEECH_BAD 3

+#define RX_SID_FIRST 4

+#define RX_SID_UPDATE 5

+#define RX_SID_BAD 6

+#define RX_NO_DATA 7

+

+/*****************************************************************************

+ *

+ * DEFINITION OF DATA TYPES

+ *****************************************************************************/

+

+Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[], VO_MEM_OPERATOR *pMemOP);

+Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[]);

+void dtx_enc_exit(dtx_encState ** st, VO_MEM_OPERATOR *pMemOP);

+

+Word16 dtx_enc(

+     dtx_encState * st,                    /* i/o : State struct                                         */

+     Word16 isf[M],                        /* o   : CN ISF vector                                        */

+     Word16 * exc2,                        /* o   : CN excitation                                        */

+     Word16 ** prms

+);

+

+Word16 dtx_buffer(

+     dtx_encState * st,                    /* i/o : State struct                    */

+     Word16 isf_new[],                     /* i   : isf vector                      */

+     Word32 enr,                           /* i   : residual energy (in L_FRAME)    */

+     Word16 codec_mode

+);

+

+void tx_dtx_handler(dtx_encState * st,     /* i/o : State struct           */

+     Word16 vad_flag,                      /* i   : vad decision           */

+     Word16 * usedMode                     /* i/o : mode changed or not    */

+);

+

+void Qisf_ns(

+     Word16 * isf1,                        /* input : ISF in the frequency domain (0..0.5) */

+     Word16 * isf_q,                       /* output: quantized ISF                        */

+     Word16 * indice                       /* output: quantization indices                 */

+);

+

+

+void Disf_ns(

+     Word16 * indice,                      /* input:  quantization indices                  */

+     Word16 * isf_q                        /* input : ISF in the frequency domain (0..0.5)  */

+);

+

+#endif  //__DTX_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/grid100.tab b/media/libstagefright/codecs/amrwbenc/inc/grid100.tab
new file mode 100644
index 0000000..efee18d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/grid100.tab
@@ -0,0 +1,53 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+

+/*-------------------------------------------------------------*

+ *  Table for az_isp()                                         *

+ *                                                             *

+ * Vector grid[] is in Q15                                     *

+ *                                                             *

+ * grid[0] = 1.0;                                              *

+ * grid[grid_points+1] = -1.0;                                 *

+ * for (i = 1; i < grid_points; i++)                           *

+ *   grid[i] = cos((6.283185307*i)/(2.0*grid_points));         *

+ *                                                             *

+ *-------------------------------------------------------------*/

+

+/* Version 101 points */

+

+#define   GRID_POINTS     100

+

+const Word16 vogrid[GRID_POINTS+1] ={

+    32767,     32751,     32703,     32622,     32509,     32364,

+    32187,     31978,     31738,     31466,     31164,     30830,

+    30466,     30072,     29649,     29196,     28714,     28204,

+    27666,     27101,     26509,     25891,     25248,     24579,

+    23886,     23170,     22431,     21669,     20887,     20083,

+    19260,     18418,     17557,     16680,     15786,     14876,

+    13951,     13013,     12062,     11099,     10125,      9141,

+     8149,      7148,      6140,      5126,      4106,      3083,

+     2057,      1029,         0,     -1029,     -2057,     -3083,

+    -4106,     -5126,     -6140,     -7148,     -8149,     -9141,

+   -10125,    -11099,    -12062,    -13013,    -13951,    -14876,

+   -15786,    -16680,    -17557,    -18418,    -19260,    -20083,

+   -20887,    -21669,    -22431,    -23170,    -23886,    -24579,

+   -25248,    -25891,    -26509,    -27101,    -27666,    -28204,

+   -28714,    -29196,    -29649,    -30072,    -30466,    -30830,

+   -31164,    -31466,    -31738,    -31978,    -32187,    -32364,

+   -32509,    -32622,    -32703,    -32751,    -32760};

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab b/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab
new file mode 100644
index 0000000..91f8690
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab
@@ -0,0 +1,73 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/* Hamming_cos window for LPC analysis.                 */

+/*   Create with function hamm_cos(window,384-128,128)  */

+

+#define L_WINDOW 384

+

+const Word16 vo_window[L_WINDOW] = {

+    2621,    2622,    2626,    2632,    2640,    2650,    2662,    2677,

+    2694,    2714,    2735,    2759,    2785,    2814,    2844,    2877,

+    2912,    2949,    2989,    3031,    3075,    3121,    3169,    3220,

+    3273,    3328,    3385,    3444,    3506,    3569,    3635,    3703,

+    3773,    3845,    3919,    3996,    4074,    4155,    4237,    4321,

+    4408,    4496,    4587,    4680,    4774,    4870,    4969,    5069,

+    5171,    5275,    5381,    5489,    5599,    5710,    5824,    5939,

+    6056,    6174,    6295,    6417,    6541,    6666,    6793,    6922,

+    7052,    7185,    7318,    7453,    7590,    7728,    7868,    8009,

+    8152,    8296,    8442,    8589,    8737,    8887,    9038,    9191,

+    9344,    9499,    9655,    9813,    9971,   10131,   10292,   10454,

+   10617,   10781,   10946,   11113,   11280,   11448,   11617,   11787,

+   11958,   12130,   12303,   12476,   12650,   12825,   13001,   13178,

+   13355,   13533,   13711,   13890,   14070,   14250,   14431,   14612,

+   14793,   14975,   15158,   15341,   15524,   15708,   15891,   16076,

+   16260,   16445,   16629,   16814,   16999,   17185,   17370,   17555,

+   17740,   17926,   18111,   18296,   18481,   18666,   18851,   19036,

+   19221,   19405,   19589,   19773,   19956,   20139,   20322,   20504,

+   20686,   20867,   21048,   21229,   21408,   21588,   21767,   21945,

+   22122,   22299,   22475,   22651,   22825,   22999,   23172,   23344,

+   23516,   23686,   23856,   24025,   24192,   24359,   24525,   24689,

+   24853,   25016,   25177,   25337,   25496,   25654,   25811,   25967,

+   26121,   26274,   26426,   26576,   26725,   26873,   27019,   27164,

+   27308,   27450,   27590,   27729,   27867,   28003,   28137,   28270,

+   28401,   28531,   28659,   28785,   28910,   29033,   29154,   29274,

+   29391,   29507,   29622,   29734,   29845,   29953,   30060,   30165,

+   30268,   30370,   30469,   30566,   30662,   30755,   30847,   30936,

+   31024,   31109,   31193,   31274,   31354,   31431,   31506,   31579,

+   31651,   31719,   31786,   31851,   31914,   31974,   32032,   32088,

+   32142,   32194,   32243,   32291,   32336,   32379,   32419,   32458,

+   32494,   32528,   32560,   32589,   32617,   32642,   32664,   32685,

+   32703,   32719,   32733,   32744,   32753,   32760,   32764,   32767,

+   32767,   32765,   32757,   32745,   32727,   32705,   32678,   32646,

+   32609,   32567,   32520,   32468,   32411,   32349,   32283,   32211,

+   32135,   32054,   31968,   31877,   31781,   31681,   31575,   31465,

+   31351,   31231,   31107,   30978,   30844,   30706,   30563,   30415,

+   30263,   30106,   29945,   29779,   29609,   29434,   29255,   29071,

+   28883,   28691,   28494,   28293,   28087,   27878,   27664,   27446,

+   27224,   26997,   26767,   26533,   26294,   26052,   25806,   25555,

+   25301,   25043,   24782,   24516,   24247,   23974,   23698,   23418,

+   23134,   22847,   22557,   22263,   21965,   21665,   21361,   21054,

+   20743,   20430,   20113,   19794,   19471,   19146,   18817,   18486,

+   18152,   17815,   17476,   17134,   16789,   16442,   16092,   15740,

+   15385,   15028,   14669,   14308,   13944,   13579,   13211,   12841,

+   12470,   12096,   11721,   11344,   10965,   10584,   10202,    9819,

+    9433,    9047,    8659,    8270,    7879,    7488,    7095,    6701,

+    6306,    5910,    5514,    5116,    4718,    4319,    3919,    3519,

+    3118,    2716,    2315,    1913,    1510,    1108,     705,     302};

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/homing.tab b/media/libstagefright/codecs/amrwbenc/inc/homing.tab
new file mode 100644
index 0000000..2963da7
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/homing.tab
@@ -0,0 +1,123 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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 DHF_PARMS_MAX 32               /* homing frame pattern  */

+#define NUM_OF_SPMODES 9

+

+#define PRML 15

+#define PRMN_7k NBBITS_7k/PRML + 1

+#define PRMN_9k NBBITS_9k/PRML + 1

+#define PRMN_12k NBBITS_12k/PRML + 1

+#define PRMN_14k NBBITS_14k/PRML + 1

+#define PRMN_16k NBBITS_16k/PRML + 1

+#define PRMN_18k NBBITS_18k/PRML + 1

+#define PRMN_20k NBBITS_20k/PRML + 1

+#define PRMN_23k NBBITS_23k/PRML + 1

+#define PRMN_24k NBBITS_24k/PRML + 1

+

+static const Word16 dfh_M7k[PRMN_7k] =

+{

+  3168, 29954, 29213, 16121, 

+	64, 13440, 30624, 16430, 

+ 19008

+};

+

+static const Word16 dfh_M9k[PRMN_9k] =

+{

+   3168, 31665,  9943, 9123, 

+  15599,  4358, 20248, 2048, 

+  17040, 27787, 16816, 13888

+};

+

+static const Word16 dfh_M12k[PRMN_12k] =

+{

+  3168, 31665,  9943,  9128, 

+  3647,  8129, 30930, 27926, 

+ 18880, 12319,   496,  1042, 

+  4061, 20446, 25629, 28069, 

+ 13948

+};

+

+static const Word16 dfh_M14k[PRMN_14k] =

+{

+    3168, 31665,  9943,  9131, 

+   24815,   655, 26616, 26764, 

+    7238, 19136,  6144,    88, 

+	4158, 25733, 30567, 30494, 

+	221, 20321, 17823

+};

+

+static const Word16 dfh_M16k[PRMN_16k] =

+{

+    3168, 31665,  9943,  9131, 

+   24815,   700,  3824,  7271, 

+   26400,  9528,  6594, 26112, 

+     108,  2068, 12867, 16317, 

+   23035, 24632,  7528,  1752, 

+    6759, 24576

+};

+

+static const Word16 dfh_M18k[PRMN_18k] =

+{

+     3168, 31665,  9943,  9135, 

+	14787, 14423, 30477, 24927, 

+	25345, 30154,   916,  5728, 

+	18978,  2048,   528, 16449, 

+	 2436,  3581, 23527, 29479, 

+	 8237, 16810, 27091, 19052, 

+	    0

+};

+

+static const Word16 dfh_M20k[PRMN_20k] =

+{

+     3168, 31665,  9943,  9129, 

+	 8637, 31807, 24646,   736, 

+	28643,  2977,  2566, 25564, 

+	12930, 13960,  2048,   834, 

+	 3270,  4100, 26920, 16237, 

+	31227, 17667, 15059, 20589, 

+	30249, 29123, 0

+};

+

+static const Word16 dfh_M23k[PRMN_23k] =

+{

+	 3168, 31665,  9943,  9132, 

+	16748,  3202, 28179, 16317, 

+	30590, 15857, 19960,  8818, 

+	21711, 21538,  4260, 16690, 

+	20224,  3666,  4194,  9497, 

+	16320, 15388,  5755, 31551, 

+	14080,  3574, 15932,    50, 

+	23392, 26053, 31216

+};

+

+static const Word16 dfh_M24k[PRMN_24k] =

+{

+	 3168, 31665,  9943,  9134, 

+	24776,  5857, 18475, 28535, 

+	29662, 14321, 16725,  4396, 

+	29353, 10003, 17068, 20504, 

+	  720,     0,  8465, 12581, 

+	28863, 24774,  9709, 26043, 

+	 7941, 27649, 13965, 15236, 

+	18026, 22047, 16681,  3968

+};

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab b/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab
new file mode 100644
index 0000000..ff20e38
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab
@@ -0,0 +1,62 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*-----------------------------------------------------*

+ | Tables for function Isf_isp() and Isp_isf()         |

+ *-----------------------------------------------------*/

+

+/* table of cos(x) in Q15 */

+

+const static Word16 table[129] = {

+  32767,

+  32758,  32729,  32679,  32610,  32522,  32413,  32286,  32138,

+  31972,  31786,  31581,  31357,  31114,  30853,  30572,  30274,

+  29957,  29622,  29269,  28899,  28511,  28106,  27684,  27246,

+  26791,  26320,  25833,  25330,  24812,  24279,  23732,  23170,

+  22595,  22006,  21403,  20788,  20160,  19520,  18868,  18205,

+  17531,  16846,  16151,  15447,  14733,  14010,  13279,  12540,

+  11793,  11039,  10279,   9512,   8740,   7962,   7180,   6393,

+   5602,   4808,   4011,   3212,   2411,   1608,    804,      0,

+   -804,  -1608,  -2411,  -3212,  -4011,  -4808,  -5602,  -6393,

+  -7180,  -7962,  -8740,  -9512, -10279, -11039, -11793, -12540,

+ -13279, -14010, -14733, -15447, -16151, -16846, -17531, -18205,

+ -18868, -19520, -20160, -20788, -21403, -22006, -22595, -23170,

+ -23732, -24279, -24812, -25330, -25833, -26320, -26791, -27246,

+ -27684, -28106, -28511, -28899, -29269, -29622, -29957, -30274,

+ -30572, -30853, -31114, -31357, -31581, -31786, -31972, -32138,

+ -32286, -32413, -32522, -32610, -32679, -32729, -32758, -32768};

+

+/* slope in Q11 used to compute y = acos(x) */

+

+const static Word16 slope[128] = { 

+ -26214, -9039, -5243, -3799, -2979, -2405, -2064, -1771,

+ -1579, -1409, -1279, -1170, -1079, -1004, -933, -880,

+ -827, -783, -743, -708, -676, -647, -621, -599,

+ -576, -557, -538, -521, -506, -492, -479, -466,

+ -456, -445, -435, -426, -417, -410, -402, -395,

+ -389, -383, -377, -372, -367, -363, -359, -355,

+ -351, -348, -345, -342, -340, -337, -335, -333,

+ -331, -330, -329, -328, -327, -326, -326, -326,

+ -326, -326, -326, -327, -328, -329, -330, -331,

+ -333, -335, -337, -340, -342, -345, -348, -351,

+ -355, -359, -363, -367, -372, -377, -383, -389,

+ -395, -402, -410, -417, -426, -435, -445, -456,

+ -466, -479, -492, -506, -521, -538, -557, -576,

+ -599, -621, -647, -676, -708, -743, -783, -827,

+ -880, -933, -1004, -1079, -1170, -1279, -1409, -1579,

+ -1771, -2064, -2405, -2979, -3799, -5243, -9039, -26214};

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab b/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab
new file mode 100644
index 0000000..4175d66
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab
@@ -0,0 +1,81 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*-----------------------------------------------------*

+ | Table of lag_window for autocorrelation.            |

+ | noise floor = 1.0001   = (0.9999  on r[1] ..r[16])  |

+ | Bandwidth expansion = 60 Hz                         |

+ | Sampling frequency  = 12800 Hz                      |

+ |                                                     |

+ | Special double precision format. See "math_op.c"    |

+ |                                                     |

+ | lag_wind[0] =  1.00000000    (not stored)           |

+ | lag_wind[1] =  0.99946642                           |

+ | lag_wind[2] =  0.99816680                           |

+ | lag_wind[3] =  0.99600452                           |

+ | lag_wind[4] =  0.99298513                           |

+ | lag_wind[5] =  0.98911655                           |

+ | lag_wind[6] =  0.98440880                           |

+ | lag_wind[7] =  0.97887397                           |

+ | lag_wind[8] =  0.97252619                           |

+ | lag_wind[9] =  0.96538186                           |

+ | lag_wind[10]=  0.95745903                           |

+ | lag_wind[11]=  0.94877797                           |

+ | lag_wind[12]=  0.93936038                           |

+ | lag_wind[13]=  0.92922986                           |

+ | lag_wind[14]=  0.91841155                           |

+ | lag_wind[15]=  0.90693212                           |

+ | lag_wind[16]=  0.89481968                           |

+ ------------------------------------------------------*/

+

+#define M 16

+

+static Word16 volag_h[M] = {

+      32750,

+      32707,

+      32637,

+      32538,

+      32411,

+      32257,

+      32075,

+      31867,

+      31633,

+      31374,

+      31089,

+      30780,

+      30449,

+      30094,

+      29718,

+      29321};

+

+static Word16 volag_l[M] = {

+      16896,

+      30464,

+       2496,

+       4480,

+      12160,

+       3520,

+      24320,

+      24192,

+      20736,

+        576,

+      18240,

+      31488,

+        128,

+      16704,

+      11520,

+      14784};

diff --git a/media/libstagefright/codecs/amrwbenc/inc/log2.h b/media/libstagefright/codecs/amrwbenc/inc/log2.h
new file mode 100644
index 0000000..91bdbec
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/log2.h
@@ -0,0 +1,62 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/********************************************************************************

+*

+*      File             : log2.h

+*      Purpose          : Computes log2(L_x)

+*

+********************************************************************************

+*/

+#ifndef __LOG2_H__

+#define __LOG2_H__

+ 

+/*

+********************************************************************************

+*                         INCLUDE FILES

+********************************************************************************

+*/

+#include "typedef.h"

+ 

+/*

+********************************************************************************

+*                         DEFINITION OF DATA TYPES

+********************************************************************************

+*/

+ 

+/*

+********************************************************************************

+*                         DECLARATION OF PROTOTYPES

+********************************************************************************

+*/

+void Log2 (

+		Word32 L_x,        /* (i) : input value                                 */

+		Word16 *exponent,  /* (o) : Integer part of Log2.   (range: 0<=val<=30) */

+		Word16 *fraction   /* (o) : Fractional part of Log2. (range: 0<=val<1)*/

+	  );

+

+void Log2_norm (

+		Word32 L_x,         /* (i) : input value (normalized)                    */

+		Word16 exp,         /* (i) : norm_l (L_x)                                */

+		Word16 *exponent,   /* (o) : Integer part of Log2.   (range: 0<=val<=30) */

+		Word16 *fraction    /* (o) : Fractional part of Log2. (range: 0<=val<1)  */

+	       );

+

+#endif  //__LOG2_H__

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h b/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h
new file mode 100644
index 0000000..7761ae6
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h
@@ -0,0 +1,35 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+

+/*******************************************************************************

+*

+*      File             : log2.tab

+*      Purpose          : Table for routine Log2().

+*      $Id $

+*

+********************************************************************************

+*/

+static const Word16 table[33] =

+{

+    0, 1455, 2866, 4236, 5568, 6863, 8124, 9352, 10549, 11716,

+    12855, 13967, 15054, 16117, 17156, 18172, 19167, 20142, 21097, 22033,

+    22951, 23852, 24735, 25603, 26455, 27291, 28113, 28922, 29716, 30497,

+    31266, 32023, 32767

+};

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/main.h b/media/libstagefright/codecs/amrwbenc/inc/main.h
new file mode 100644
index 0000000..d7e7c67
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/main.h
@@ -0,0 +1,45 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*--------------------------------------------------------------------------*

+ *                         MAIN.H	                                    *

+ *--------------------------------------------------------------------------*

+ *       Main functions							    *

+ *--------------------------------------------------------------------------*/

+

+#ifndef __MAIN_H__

+#define __MAIN_H__

+

+void coder(

+     Word16 * mode,                        /* input :  used mode                             */

+     Word16 speech16k[],                   /* input :  320 new speech samples (at 16 kHz)    */

+     Word16 prms[],                        /* output:  output parameters           */

+     Word16 * ser_size,                    /* output:  bit rate of the used mode   */

+     void *spe_state,                      /* i/o   :  State structure                       */

+     Word16 allow_dtx                      /* input :  DTX ON/OFF                            */

+);

+

+

+

+void Reset_encoder(void *st, Word16 reset_all);

+

+

+Word16 encoder_homing_frame_test(Word16 input_frame[]);

+

+#endif //__MAIN_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/math_op.h b/media/libstagefright/codecs/amrwbenc/inc/math_op.h
new file mode 100644
index 0000000..25e29f7
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/math_op.h
@@ -0,0 +1,55 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*--------------------------------------------------------------------------*

+ *                         MATH_OP.H	                                    *

+ *--------------------------------------------------------------------------*

+ *       Mathematical operations					    *

+ *--------------------------------------------------------------------------*/

+

+#ifndef __MATH_OP_H__

+#define __MATH_OP_H__

+

+Word32 Isqrt(                              /* (o) Q31 : output value (range: 0<=val<1)         */

+		Word32 L_x                            /* (i) Q0  : input value  (range: 0<=val<=7fffffff) */

+	    );

+

+void Isqrt_n(

+		Word32 * frac,                        /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */

+		Word16 * exp                          /* (i/o)    : exponent (value = frac x 2^exponent) */

+	    );

+

+Word32 Pow2(                               /* (o) Q0  : result       (range: 0<=val<=0x7fffffff) */

+		Word16 exponant,                      /* (i) Q0  : Integer part.      (range: 0<=val<=30)   */

+		Word16 fraction                       /* (i) Q15 : Fractionnal part.  (range: 0.0<=val<1.0) */

+	   );

+

+Word32 Dot_product12(                      /* (o) Q31: normalized result (1 < val <= -1) */

+		Word16 x[],                           /* (i) 12bits: x vector                       */

+		Word16 y[],                           /* (i) 12bits: y vector                       */

+		Word16 lg,                            /* (i)    : vector length                     */

+		Word16 * exp                          /* (o)    : exponent of result (0..+30)       */

+		);

+

+Word32 Dot_product12_asm(                      /* (o) Q31: normalized result (1 < val <= -1) */

+		Word16 x[],                           /* (i) 12bits: x vector                       */

+		Word16 y[],                           /* (i) 12bits: y vector                       */

+		Word16 lg,                            /* (i)    : vector length                     */

+		Word16 * exp                          /* (o)    : exponent of result (0..+30)       */

+		);

+#endif //__MATH_OP_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/mem_align.h b/media/libstagefright/codecs/amrwbenc/inc/mem_align.h
new file mode 100644
index 0000000..d6ddec3
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/mem_align.h
@@ -0,0 +1,35 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		mem_align.h

+

+	Content:	Memory alloc alignments functions

+

+*******************************************************************************/

+

+#ifndef __VO_MEM_ALIGN_H__

+#define __VO_MEM_ALIGN_H__

+

+#include "voMem.h"

+#include "typedef.h"

+

+extern void *mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID);

+extern void mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID);

+

+#endif	/* __VO_MEM_ALIGN_H__ */

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab b/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab
new file mode 100644
index 0000000..ffc86a1
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab
@@ -0,0 +1,368 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+#include <stdio.h>

+#include "typedef.h"

+

+static UWord8 toc_byte[16] = {0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x34, 0x3C,

+                              0x44, 0x4C, 0x54, 0x5C, 0x64, 0x6C, 0x74, 0x7C};

+

+/* number of speech bits for all modes */

+static Word16 unpacked_size[16] = {132,  177, 253, 285, 317, 365, 397, 461,

+                                   477,   35,   0,   0,   0,   0,   0,   0};

+

+/* size of packed frame for each mode, excluding TOC byte */

+static Word16 packed_size[16] = {17, 23, 32, 36, 40, 46, 50, 58,

+                                 60,  5,  0,  0,  0,  0,  0,  0};

+

+/* number of unused speech bits in packed format for each mode */

+static Word16 unused_size[16] = {4, 7, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0};

+

+/* sorting tables for all modes */

+

+static Word16 sort_660[132] = {

+     0,   5,   6,   7,  61,  84, 107, 130,  62,  85,

+     8,   4,  37,  38,  39,  40,  58,  81, 104, 127,

+    60,  83, 106, 129, 108, 131, 128,  41,  42,  80,

+   126,   1,   3,  57, 103,  82, 105,  59,   2,  63,

+   109, 110,  86,  19,  22,  23,  64,  87,  18,  20,

+    21,  17,  13,  88,  43,  89,  65, 111,  14,  24,

+    25,  26,  27,  28,  15,  16,  44,  90,  66, 112,

+     9,  11,  10,  12,  67, 113,  29,  30,  31,  32,

+    34,  33,  35,  36,  45,  51,  68,  74,  91,  97,

+   114, 120,  46,  69,  92, 115,  52,  75,  98, 121,

+    47,  70,  93, 116,  53,  76,  99, 122,  48,  71,

+    94, 117,  54,  77, 100, 123,  49,  72,  95, 118,

+    55,  78, 101, 124,  50,  73,  96, 119,  56,  79,

+   102, 125

+};

+

+static Word16 sort_885[177] = {

+     0,   4,   6,   7,   5,   3,  47,  48,  49, 112,

+   113, 114,  75, 106, 140, 171,  80, 111, 145, 176,

+    77, 108, 142, 173,  78, 109, 143, 174,  79, 110,

+   144, 175,  76, 107, 141, 172,  50, 115,  51,   2,

+     1,  81, 116, 146,  19,  21,  12,  17,  18,  20,

+    16,  25,  13,  10,  14,  24,  23,  22,  26,   8,

+    15,  52, 117,  31,  82, 147,   9,  33,  11,  83,

+   148,  53, 118,  28,  27,  84, 149,  34,  35,  29,

+    46,  32,  30,  54, 119,  37,  36,  39,  38,  40,

+    85, 150,  41,  42,  43,  44,  45,  55,  60,  65,

+    70,  86,  91,  96, 101, 120, 125, 130, 135, 151,

+   156, 161, 166,  56,  87, 121, 152,  61,  92, 126,

+   157,  66,  97, 131, 162,  71, 102, 136, 167,  57,

+    88, 122, 153,  62,  93, 127, 158,  67,  98, 132,

+   163,  72, 103, 137, 168,  58,  89, 123, 154,  63,

+    94, 128, 159,  68,  99, 133, 164,  73, 104, 138,

+   169,  59,  90, 124, 155,  64,  95, 129, 160,  69,

+   100, 134, 165,  74, 105, 139, 170

+};

+

+static Word16 sort_1265[253] = {

+     0,   4,   6,  93, 143, 196, 246,   7,   5,   3,

+    47,  48,  49,  50,  51, 150, 151, 152, 153, 154,

+    94, 144, 197, 247,  99, 149, 202, 252,  96, 146,

+   199, 249,  97, 147, 200, 250, 100, 203,  98, 148,

+   201, 251,  95, 145, 198, 248,  52,   2,   1, 101,

+   204, 155,  19,  21,  12,  17,  18,  20,  16,  25,

+    13,  10,  14,  24,  23,  22,  26,   8,  15,  53,

+   156,  31, 102, 205,   9,  33,  11, 103, 206,  54,

+   157,  28,  27, 104, 207,  34,  35,  29,  46,  32,

+    30,  55, 158,  37,  36,  39,  38,  40, 105, 208,

+    41,  42,  43,  44,  45,  56, 106, 159, 209,  57,

+    66,  75,  84, 107, 116, 125, 134, 160, 169, 178,

+   187, 210, 219, 228, 237,  58, 108, 161, 211,  62,

+   112, 165, 215,  67, 117, 170, 220,  71, 121, 174,

+   224,  76, 126, 179, 229,  80, 130, 183, 233,  85,

+   135, 188, 238,  89, 139, 192, 242,  59, 109, 162,

+   212,  63, 113, 166, 216,  68, 118, 171, 221,  72,

+   122, 175, 225,  77, 127, 180, 230,  81, 131, 184,

+   234,  86, 136, 189, 239,  90, 140, 193, 243,  60,

+   110, 163, 213,  64, 114, 167, 217,  69, 119, 172,

+   222,  73, 123, 176, 226,  78, 128, 181, 231,  82,

+   132, 185, 235,  87, 137, 190, 240,  91, 141, 194,

+   244,  61, 111, 164, 214,  65, 115, 168, 218,  70,

+   120, 173, 223,  74, 124, 177, 227,  79, 129, 182,

+   232,  83, 133, 186, 236,  88, 138, 191, 241,  92,

+   142, 195, 245                         

+};

+

+static Word16 sort_1425[285] = {

+     0,   4,   6, 101, 159, 220, 278,   7,   5,   3,

+    47,  48,  49,  50,  51, 166, 167, 168, 169, 170,

+   102, 160, 221, 279, 107, 165, 226, 284, 104, 162,

+   223, 281, 105, 163, 224, 282, 108, 227, 106, 164,

+   225, 283, 103, 161, 222, 280,  52,   2,   1, 109,

+   228, 171,  19,  21,  12,  17,  18,  20,  16,  25,

+    13,  10,  14,  24,  23,  22,  26,   8,  15,  53,

+   172,  31, 110, 229,   9,  33,  11, 111, 230,  54,

+   173,  28,  27, 112, 231,  34,  35,  29,  46,  32,

+    30,  55, 174,  37,  36,  39,  38,  40, 113, 232,

+    41,  42,  43,  44,  45,  56, 114, 175, 233,  62,

+   120, 181, 239,  75, 133, 194, 252,  57, 115, 176,

+   234,  63, 121, 182, 240,  70, 128, 189, 247,  76,

+   134, 195, 253,  83, 141, 202, 260,  92, 150, 211,

+   269,  84, 142, 203, 261,  93, 151, 212, 270,  85,

+   143, 204, 262,  94, 152, 213, 271,  86, 144, 205,

+   263,  95, 153, 214, 272,  64, 122, 183, 241,  77,

+   135, 196, 254,  65, 123, 184, 242,  78, 136, 197,

+   255,  87, 145, 206, 264,  96, 154, 215, 273,  58,

+   116, 177, 235,  66, 124, 185, 243,  71, 129, 190,

+   248,  79, 137, 198, 256,  88, 146, 207, 265,  97,

+   155, 216, 274,  59, 117, 178, 236,  67, 125, 186,

+   244,  72, 130, 191, 249,  80, 138, 199, 257,  89,

+   147, 208, 266,  98, 156, 217, 275,  60, 118, 179,

+   237,  68, 126, 187, 245,  73, 131, 192, 250,  81,

+   139, 200, 258,  90, 148, 209, 267,  99, 157, 218,

+   276,  61, 119, 180, 238,  69, 127, 188, 246,  74,

+   132, 193, 251,  82, 140, 201, 259,  91, 149, 210,

+   268, 100, 158, 219, 277

+};

+

+static Word16 sort_1585[317] = {

+     0,   4,   6, 109, 175, 244, 310,   7,   5,   3,

+    47,  48,  49,  50,  51, 182, 183, 184, 185, 186,

+   110, 176, 245, 311, 115, 181, 250, 316, 112, 178,

+   247, 313, 113, 179, 248, 314, 116, 251, 114, 180,

+   249, 315, 111, 177, 246, 312,  52,   2,   1, 117,

+   252, 187,  19,  21,  12,  17,  18,  20,  16,  25,

+    13,  10,  14,  24,  23,  22,  26,   8,  15,  53,

+   188,  31, 118, 253,   9,  33,  11, 119, 254,  54,

+   189,  28,  27, 120, 255,  34,  35,  29,  46,  32,

+    30,  55, 190,  37,  36,  39,  38,  40, 121, 256,

+    41,  42,  43,  44,  45,  56, 122, 191, 257,  63,

+   129, 198, 264,  76, 142, 211, 277,  89, 155, 224,

+   290, 102, 168, 237, 303,  57, 123, 192, 258,  70,

+   136, 205, 271,  83, 149, 218, 284,  96, 162, 231,

+   297,  62, 128, 197, 263,  75, 141, 210, 276,  88,

+   154, 223, 289, 101, 167, 236, 302,  58, 124, 193,

+   259,  71, 137, 206, 272,  84, 150, 219, 285,  97,

+   163, 232, 298,  59, 125, 194, 260,  64, 130, 199,

+   265,  67, 133, 202, 268,  72, 138, 207, 273,  77,

+   143, 212, 278,  80, 146, 215, 281,  85, 151, 220,

+   286,  90, 156, 225, 291,  93, 159, 228, 294,  98,

+   164, 233, 299, 103, 169, 238, 304, 106, 172, 241,

+   307,  60, 126, 195, 261,  65, 131, 200, 266,  68,

+   134, 203, 269,  73, 139, 208, 274,  78, 144, 213,

+   279,  81, 147, 216, 282,  86, 152, 221, 287,  91,

+   157, 226, 292,  94, 160, 229, 295,  99, 165, 234,

+   300, 104, 170, 239, 305, 107, 173, 242, 308,  61,

+   127, 196, 262,  66, 132, 201, 267,  69, 135, 204,

+   270,  74, 140, 209, 275,  79, 145, 214, 280,  82,

+   148, 217, 283,  87, 153, 222, 288,  92, 158, 227,

+   293,  95, 161, 230, 296, 100, 166, 235, 301, 105,

+   171, 240, 306, 108, 174, 243, 309

+};

+

+static Word16 sort_1825[365] = {

+     0,   4,   6, 121, 199, 280, 358,   7,   5,   3,

+    47,  48,  49,  50,  51, 206, 207, 208, 209, 210,

+   122, 200, 281, 359, 127, 205, 286, 364, 124, 202,

+   283, 361, 125, 203, 284, 362, 128, 287, 126, 204,

+   285, 363, 123, 201, 282, 360,  52,   2,   1, 129,

+   288, 211,  19,  21,  12,  17,  18,  20,  16,  25,

+    13,  10,  14,  24,  23,  22,  26,   8,  15,  53,

+   212,  31, 130, 289,   9,  33,  11, 131, 290,  54,

+   213,  28,  27, 132, 291,  34,  35,  29,  46,  32,

+    30,  55, 214,  37,  36,  39,  38,  40, 133, 292,

+    41,  42,  43,  44,  45,  56, 134, 215, 293, 198,

+   299, 136, 120, 138,  60, 279,  58,  62, 357, 139,

+   140, 295, 156,  57, 219, 297,  63, 217, 137, 170,

+   300, 222,  64, 106,  61,  78, 294,  92, 142, 141,

+   135, 221, 296, 301, 343,  59, 298, 184, 329, 315,

+   220, 216, 265, 251, 218, 237, 352, 223, 157,  86,

+   171,  87, 164, 351, 111, 302,  65, 178, 115, 323,

+    72, 192, 101, 179,  93,  73, 193, 151, 337, 309,

+   143, 274,  69, 324, 165, 150,  97, 338, 110, 310,

+   330, 273,  68, 107, 175, 245, 114,  79, 113, 189,

+   246, 259, 174,  71, 185,  96, 344, 100, 322,  83,

+   334, 316, 333, 252, 161, 348, 147,  82, 269, 232,

+   260, 308, 353, 347, 163, 231, 306, 320, 188, 270,

+   146, 177, 266, 350, 256,  85, 149, 116, 191, 160,

+   238, 258, 336, 305, 255,  88, 224,  99, 339, 230,

+   228, 227, 272, 242, 241, 319, 233, 311, 102,  74,

+   180, 275,  66, 194, 152, 325, 172, 247, 244, 261,

+   117, 158, 166, 354,  75, 144, 108, 312,  94, 186,

+   303,  80, 234,  89, 195, 112, 340, 181, 345, 317,

+   326, 276, 239, 167, 118, 313,  70, 355, 327, 253,

+   190, 176, 271, 104,  98, 153, 103,  90,  76, 267,

+   277, 248, 225, 262, 182,  84, 154, 235, 335, 168,

+   331, 196, 341, 249, 162, 307, 148, 349, 263, 321,

+   257, 243, 229, 356, 159, 119,  67, 187, 173, 145,

+   240,  77, 304, 332, 314, 342, 109, 254,  81, 278,

+   105,  91, 346, 318, 183, 250, 197, 328,  95, 155,

+   169, 268, 226, 236, 264                 

+};

+

+static Word16 sort_1985[397] = {

+     0,   4,   6, 129, 215, 304, 390,   7,   5,   3,

+    47,  48,  49,  50,  51, 222, 223, 224, 225, 226,

+   130, 216, 305, 391, 135, 221, 310, 396, 132, 218,

+   307, 393, 133, 219, 308, 394, 136, 311, 134, 220,

+   309, 395, 131, 217, 306, 392,  52,   2,   1, 137,

+   312, 227,  19,  21,  12,  17,  18,  20,  16,  25,

+    13,  10,  14,  24,  23,  22,  26,   8,  15,  53,

+   228,  31, 138, 313,   9,  33,  11, 139, 314,  54,

+   229,  28,  27, 140, 315,  34,  35,  29,  46,  32,

+    30,  55, 230,  37,  36,  39,  38,  40, 141, 316,

+    41,  42,  43,  44,  45,  56, 142, 231, 317,  63,

+    73,  92, 340,  82, 324, 149, 353, 159, 334, 165,

+   338, 178, 163, 254,  77, 168, 257, 153, 343,  57,

+   248, 238,  79, 252, 166,  67,  80, 201, 101, 267,

+   143, 164, 341, 255, 339, 187, 376, 318,  78, 328,

+   362, 115, 232, 242, 253, 290, 276,  62,  58, 158,

+    68,  93, 179, 319, 148, 169, 154,  72, 385, 329,

+   333, 344, 102,  83, 144, 233, 323, 124, 243, 192,

+   354, 237,  64, 247, 202, 209, 150, 116, 335, 268,

+   239, 299, 188, 196, 298,  94, 195, 258, 123, 363,

+   384, 109, 325, 371, 170, 370,  84, 110, 295, 180,

+    74, 210, 191, 106, 291, 205, 367, 381, 377, 206,

+   355, 122, 119, 120, 383, 160, 105, 108, 277, 380,

+   294, 284, 285, 345, 208, 269, 249, 366, 386, 300,

+   297, 259, 125, 369, 197,  97, 194, 286, 211, 281,

+   280, 183, 372,  87, 155, 283,  59, 348, 327, 184,

+    76, 111, 330, 203, 349,  69,  98, 152, 145, 189,

+    66, 320, 337, 173, 358, 251, 198, 174, 263, 262,

+   126, 241, 193,  88, 388, 117,  95, 387, 112, 359,

+   287, 244, 103, 272, 301, 171, 162, 234, 273, 127,

+   373, 181, 292,  85, 378, 302, 121, 107, 364, 346,

+   356, 212, 278, 213,  65, 382, 288, 207, 113, 175,

+    99, 296, 374, 368, 199, 260, 185, 336, 331, 161,

+   270, 264, 250, 240,  75, 350, 151,  60,  89, 321,

+   156, 274, 360, 326,  70, 282, 167, 146, 352,  81,

+    91, 389, 266, 245, 177, 235, 190, 256, 204, 342,

+   128, 118, 303, 104, 379, 182, 114, 375, 200,  96,

+   293, 172, 214, 365, 279,  86, 289, 351, 347, 357,

+   261, 186, 176, 271,  90, 100, 147, 322, 275, 361,

+    71, 332,  61, 265, 157, 246, 236         

+};

+

+static Word16 sort_2305[461] = {

+     0,   4,   6, 145, 247, 352, 454,   7,   5,   3,

+    47,  48,  49,  50,  51, 254, 255, 256, 257, 258,

+   146, 248, 353, 455, 151, 253, 358, 460, 148, 250,

+   355, 457, 149, 251, 356, 458, 152, 359, 150, 252,

+   357, 459, 147, 249, 354, 456,  52,   2,   1, 153,

+   360, 259,  19,  21,  12,  17,  18,  20,  16,  25,

+    13,  10,  14,  24,  23,  22,  26,   8,  15,  53,

+   260,  31, 154, 361,   9,  33,  11, 155, 362,  54,

+   261,  28,  27, 156, 363,  34,  35,  29,  46,  32,

+    30,  55, 262,  37,  36,  39,  38,  40, 157, 364,

+    41,  42,  43,  44,  45,  56, 158, 263, 365, 181,

+   192, 170,  79,  57, 399,  90, 159, 297, 377, 366,

+   275,  68, 183, 388, 286, 194, 299, 92 ,  70, 182,

+   401, 172,  59,  91,  58, 400, 368, 161,  81, 160,

+   264, 171,  80, 389, 390, 378, 379, 193, 298,  69,

+   266, 265, 367, 277, 288, 276, 287, 184,  60, 195,

+    82,  93,  71, 369, 402, 173, 162, 444, 300, 391,

+    98,  76, 278,  61, 267, 374, 135, 411, 167, 102,

+   380, 200,  87, 178,  65,  94, 204, 124,  72, 342,

+   189, 305, 381, 396, 433, 301, 226, 407, 289, 237,

+   113, 215, 185, 128, 309, 403, 116, 320, 196, 331,

+   370, 422, 174,  64, 392,  83, 425, 219, 134, 188,

+   432, 112, 427, 139, 279, 163, 436, 208, 447, 218,

+   236, 229,  97, 294, 385, 230, 166, 268, 177, 443,

+   225, 426, 101, 272, 138, 127, 290, 117, 347, 199,

+   414,  95, 140, 240, 410, 395, 209, 129, 283, 346,

+   105, 241, 437,  86, 308, 448, 203, 345, 186, 107,

+   220, 415, 334, 319, 106, 313, 118, 123,  73, 207,

+   421, 214, 384, 373, 438,  62, 371, 341,  75, 449,

+   168, 323, 164, 242, 416, 324, 304, 197, 335, 404,

+   271,  63, 191, 325,  96, 169, 231, 280, 312, 187,

+   406,  84, 201, 100,  67, 382, 175, 336, 202, 330,

+   269, 393, 376, 383, 293, 307, 409, 179, 285, 314,

+   302, 372, 398, 190, 180,  89,  99, 103, 232,  78,

+    88,  77, 136, 387, 165, 198, 394, 125, 176, 428,

+    74, 375, 238, 227,  66, 273, 282, 141, 306, 412,

+   114,  85, 130, 348, 119, 291, 296, 386, 233, 397,

+   303, 405, 284, 445, 423, 221, 210, 205, 450, 108,

+   274, 434, 216, 343, 337, 142, 243, 321, 408, 451,

+   310, 292, 120, 109, 281, 439, 270, 429, 332, 295,

+   418, 211, 315, 222, 326, 131, 430, 244, 327, 349,

+   417, 316, 143, 338, 440, 234, 110, 212, 452, 245,

+   121, 419, 350, 223, 132, 441, 328, 413, 317, 339,

+   126, 104, 137, 446, 344, 239, 435, 115, 333, 206,

+   322, 217, 228, 424, 453, 311, 351, 111, 442, 224,

+   213, 122, 431, 340, 235, 246, 133, 144, 420, 329,

+   318

+};

+

+static Word16 sort_2385[477] = {

+     0,   4,   6, 145, 251, 360, 466,   7,   5,   3,

+    47,  48,  49,  50,  51, 262, 263, 264, 265, 266,

+   146, 252, 361, 467, 151, 257, 366, 472, 148, 254,

+   363, 469, 149, 255, 364, 470, 156, 371, 150, 256,

+   365, 471, 147, 253, 362, 468,  52,   2,   1, 157,

+   372, 267,  19,  21,  12,  17,  18,  20,  16,  25,

+    13,  10,  14,  24,  23,  22,  26,   8,  15,  53,

+   268,  31, 152, 153, 154, 155, 258, 259, 260, 261,

+   367, 368, 369, 370, 473, 474, 475, 476, 158, 373,

+     9,  33,  11, 159, 374,  54, 269,  28,  27, 160,

+   375,  34,  35,  29,  46,  32,  30,  55, 270, 37,

+    36,  39,  38,  40, 161, 376,  41,  42,  43,  44,

+    45,  56, 162, 271, 377, 185, 196, 174,  79,  57,

+   411,  90, 163, 305, 389, 378, 283,  68, 187, 400,

+   294, 198, 307,  92,  70, 186, 413, 176,  59,  91,

+    58, 412, 380, 165,  81, 164, 272, 175,  80, 401,

+   402, 390, 391, 197, 306,  69, 274, 273, 379, 285,

+   296, 284, 295, 188,  60, 199,  82,  93,  71, 381,

+   414, 177, 166, 456, 308, 403,  98,  76, 286,  61,

+   275, 386, 135, 423, 171, 102, 392, 204,  87, 182,

+    65,  94, 208, 124,  72, 350, 193, 313, 393, 408,

+   445, 309, 230, 419, 297, 241, 113, 219, 189, 128,

+   317, 415, 116, 328, 200, 339, 382, 434, 178,  64,

+   404,  83, 437, 223, 134, 192, 444, 112, 439, 139,

+   287, 167, 448, 212, 459, 222, 240, 233,  97, 302,

+   397, 234, 170, 276, 181, 455, 229, 438, 101, 280,

+   138, 127, 298, 117, 355, 203, 426,  95, 140, 244,

+   422, 407, 213, 129, 291, 354, 105, 245, 449,  86,

+   316, 460, 207, 353, 190, 107, 224, 427, 342, 327,

+   106, 321, 118, 123,  73, 211, 433, 218, 396, 385,

+   450,  62, 383, 349,  75, 461, 172, 331, 168, 246,

+   428, 332, 312, 201, 343, 416, 279,  63, 195, 333,

+    96, 173, 235, 288, 320, 191, 418,  84, 205, 100,

+    67, 394, 179, 344, 206, 338, 277, 405, 388, 395,

+   301, 315, 421, 183, 293, 322, 310, 384, 410, 194,

+   184,  89,  99, 103, 236,  78,  88,  77, 136, 399,

+   169, 202, 406, 125, 180, 440,  74, 387, 242, 231,

+    66, 281, 290, 141, 314, 424, 114,  85, 130, 356,

+   119, 299, 304, 398, 237, 409, 311, 417, 292, 457,

+   435, 225, 214, 209, 462, 108, 282, 446, 220, 351,

+   345, 142, 247, 329, 420, 463, 318, 300, 120, 109,

+   289, 451, 278, 441, 340, 303, 430, 215, 323, 226,

+   334, 131, 442, 248, 335, 357, 429, 324, 143, 346,

+   452, 238, 110, 216, 464, 249, 121, 431, 358, 227,

+   132, 453, 336, 425, 325, 347, 126, 104, 137, 458,

+   352, 243, 447, 115, 341, 210, 330, 221, 232, 436,

+   465, 319, 359, 111, 454, 228, 217, 122, 443, 348,

+   239, 250, 133, 144, 432, 337, 326         

+};

+

+static Word16 sort_SID[35] = {

+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9,

+   10, 11, 12, 13, 14, 15, 16, 17, 18, 19,

+   20, 21, 22, 23, 24, 25, 26, 27, 28, 29,

+   30, 31, 32, 33, 34

+};

+

+/* pointer table for bit sorting tables */

+static Word16 *sort_ptr[16] = { sort_660, sort_885, sort_1265, sort_1425, sort_1585, sort_1825, sort_1985, sort_2305,

+                               sort_2385, sort_SID,      NULL,      NULL,      NULL,      NULL,      NULL,      NULL};

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h b/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h
new file mode 100644
index 0000000..4159d84
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h
@@ -0,0 +1,31 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/* Double precision operations */

+/* $Id$ */

+

+#ifndef __OPER_32B_H__

+#define __OPER_32B_H__

+

+void VO_L_Extract (Word32 L_32, Word16 *hi, Word16 *lo);

+Word32 L_Comp (Word16 hi, Word16 lo);

+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);

+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n);

+Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo);

+

+#endif //__OPER_32B_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h b/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h
new file mode 100644
index 0000000..27c4c7e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h
@@ -0,0 +1,52 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/*--------------------------------------------------------------------------*

+ *                         P_MED_O.H                                        *

+ *--------------------------------------------------------------------------*

+ *       Median open-loop lag search				            *

+ *--------------------------------------------------------------------------*/

+

+#ifndef __P_MED_O_H__

+#define __P_MED_O_H__

+

+Word16 Pitch_med_ol(                       /* output: open loop pitch lag                        */

+		Word16 wsp[],                         /* input : signal used to compute the open loop pitch */

+		/* wsp[-pit_max] to wsp[-1] should be known   */

+		Word16 L_min,                         /* input : minimum pitch lag                          */

+		Word16 L_max,                         /* input : maximum pitch lag                          */

+		Word16 L_frame,                       /* input : length of frame to compute pitch           */

+		Word16 L_0,                           /* input : old_ open-loop pitch                       */

+		Word16 * gain,                        /* output: normalize correlation of hp_wsp for the Lag */

+		Word16 * hp_wsp_mem,                  /* i:o   : memory of the hypass filter for hp_wsp[] (lg=9)   */

+		Word16 * old_hp_wsp,                  /* i:o   : hypass wsp[]                               */

+		Word16 wght_flg                       /* input : is weighting function used                 */

+		);

+

+Word16 Med_olag(                           /* output : median of  5 previous open-loop lags       */

+		Word16 prev_ol_lag,                   /* input  : previous open-loop lag                     */

+		Word16 old_ol_lag[5]

+	       );

+

+void Hp_wsp(

+		Word16 wsp[],                         /* i   : wsp[]  signal       */

+		Word16 hp_wsp[],                      /* o   : hypass wsp[]        */

+		Word16 lg,                            /* i   : lenght of signal    */

+		Word16 mem[]                          /* i/o : filter memory [9]   */

+	   );

+

+#endif  //__P_MED_O_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab b/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab
new file mode 100644
index 0000000..14bd1d5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab
@@ -0,0 +1,47 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*-----------------------------------------------------*

+ | Table for function Pitch_med_ol()				   |

+ *-----------------------------------------------------*/

+

+ static Word16 corrweight[199]= {

+

+ 10772, 10794, 10816, 10839, 10862, 10885, 10908, 10932, 10955, 10980,

+ 11004, 11029, 11054, 11079, 11105, 11131, 11157, 11183, 11210, 11238,

+ 11265, 11293, 11322, 11350, 11379, 11409, 11439, 11469, 11500, 11531,

+ 11563, 11595, 11628, 11661, 11694, 11728, 11763, 11798, 11834, 11870,

+ 11907, 11945, 11983, 12022, 12061, 12101, 12142, 12184, 12226, 12270,

+ 12314, 12358, 12404, 12451, 12498, 12547, 12596, 12647, 12699, 12751,

+ 12805, 12861, 12917, 12975, 13034, 13095, 13157, 13221, 13286, 13353,

+ 13422, 13493, 13566, 13641, 13719, 13798, 13880, 13965, 14053, 14143,

+ 14237, 14334, 14435, 14539, 14648, 14761, 14879, 15002, 15130, 15265,

+ 15406, 15554, 15710, 15874, 16056, 16384, 16384, 16384, 16384, 16384,

+ 16384, 16384, 16056, 15874, 15710, 15554, 15406, 15265, 15130, 15002,

+ 14879, 14761, 14648, 14539, 14435, 14334, 14237, 14143, 14053, 13965,

+ 13880, 13798, 13719, 13641, 13566, 13493, 13422, 13353, 13286, 13221,

+ 13157, 13095, 13034, 12975, 12917, 12861, 12805, 12751, 12699, 12647,

+ 12596, 12547, 12498, 12451, 12404, 12358, 12314, 12270, 12226, 12184,

+ 12142, 12101, 12061, 12022, 11983, 11945, 11907, 11870, 11834, 11798,

+ 11763, 11728, 11694, 11661, 11628, 11595, 11563, 11531, 11500, 11469,

+ 11439, 11409, 11379, 11350, 11322, 11293, 11265, 11238, 11210, 11183,

+ 11157, 11131, 11105, 11079, 11054, 11029, 11004, 10980, 10955, 10932,

+ 10908, 10885, 10862, 10839, 10816, 10794, 10772, 10750, 10728};

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab b/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab
new file mode 100644
index 0000000..1a0deee
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab
@@ -0,0 +1,228 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*------------------------------------------------------*

+ * Tables for function q_gain2()                        *

+ *                                                      *

+ *  g_pitch(Q14),  g_code(Q11)                          *

+ *                                                      *

+ * pitch gain are ordered in table to reduce complexity *

+ * during quantization of gains.                        *

+ *------------------------------------------------------*/

+

+#define nb_qua_gain6b  64     /* Number of quantization level */

+#define nb_qua_gain7b  128    /* Number of quantization level */

+

+

+static Word16 t_qua_gain6b[64*2] = {

+   1566,  1332,

+   1577,  3557,

+   3071,  6490,

+   4193, 10163,

+   4496,  2534,

+   5019,  4488,

+   5586, 15614,

+   5725,  1422,

+   6453,   580,

+   6724,  6831,

+   7657,  3527,

+   8072,  2099,

+   8232,  5319,

+   8827,  8775,

+   9740,  2868,

+   9856,  1465,

+  10087, 12488,

+  10241,  4453,

+  10859,  6618,

+  11321,  3587,

+  11417,  1800,

+  11643,  2428,

+  11718,   988,

+  12312,  5093,

+  12523,  8413,

+  12574, 26214,

+  12601,  3396,

+  13172,  1623,

+  13285,  2423,

+  13418,  6087,

+  13459, 12810,

+  13656,  3607,

+  14111,  4521,

+  14144,  1229,

+  14425,  1871,

+  14431,  7234,

+  14445,  2834,

+  14628, 10036,

+  14860, 17496,

+  15161,  3629,

+  15209,  5819,

+  15299,  2256,

+  15518,  4722,

+  15663,  1060,

+  15759,  7972,

+  15939, 11964,

+  16020,  2996,

+  16086,  1707,

+  16521,  4254,

+  16576,  6224,

+  16894,  2380,

+  16906,   681,

+  17213,  8406,

+  17610,  3418,

+  17895,  5269,

+  18168, 11748,

+  18230,  1575,

+  18607, 32767,

+  18728, 21684,

+  19137,  2543,

+  19422,  6577,

+  19446,  4097,

+  19450,  9056,

+  20371, 14885};

+

+static Word16 t_qua_gain7b[128*2] = {

+    204,   441,

+    464,  1977,

+    869,  1077,

+   1072,  3062,

+   1281,  4759,

+   1647,  1539,

+   1845,  7020,

+   1853,   634,

+   1995,  2336,

+   2351, 15400,

+   2661,  1165,

+   2702,  3900,

+   2710, 10133,

+   3195,  1752,

+   3498,  2624,

+   3663,   849,

+   3984,  5697,

+   4214,  3399,

+   4415,  1304,

+   4695,  2056,

+   5376,  4558,

+   5386,   676,

+   5518, 23554,

+   5567,  7794,

+   5644,  3061,

+   5672,  1513,

+   5957,  2338,

+   6533,  1060,

+   6804,  5998,

+   6820,  1767,

+   6937,  3837,

+   7277,   414,

+   7305,  2665,

+   7466, 11304,

+   7942,   794,

+   8007,  1982,

+   8007,  1366,

+   8326,  3105,

+   8336,  4810,

+   8708,  7954,

+   8989,  2279,

+   9031,  1055,

+   9247,  3568,

+   9283,  1631,

+   9654,  6311,

+   9811,  2605,

+  10120,   683,

+  10143,  4179,

+  10245,  1946,

+  10335,  1218,

+  10468,  9960,

+  10651,  3000,

+  10951,  1530,

+  10969,  5290,

+  11203,  2305,

+  11325,  3562,

+  11771,  6754,

+  11839,  1849,

+  11941,  4495,

+  11954,  1298,

+  11975, 15223,

+  11977,   883,

+  11986,  2842,

+  12438,  2141,

+  12593,  3665,

+  12636,  8367,

+  12658,  1594,

+  12886,  2628,

+  12984,  4942,

+  13146,  1115,

+  13224,   524,

+  13341,  3163,

+  13399,  1923,

+  13549,  5961,

+  13606,  1401,

+  13655,  2399,

+  13782,  3909,

+  13868, 10923,

+  14226,  1723,

+  14232,  2939,

+  14278,  7528,

+  14439,  4598,

+  14451,   984,

+  14458,  2265,

+  14792,  1403,

+  14818,  3445,

+  14899,  5709,

+  15017, 15362,

+  15048,  1946,

+  15069,  2655,

+  15405,  9591,

+  15405,  4079,

+  15570,  7183,

+  15687,  2286,

+  15691,  1624,

+  15699,  3068,

+  15772,  5149,

+  15868,  1205,

+  15970,   696,

+  16249,  3584,

+  16338,  1917,

+  16424,  2560,

+  16483,  4438,

+  16529,  6410,

+  16620, 11966,

+  16839,  8780,

+  17030,  3050,

+  17033, 18325,

+  17092,  1568,

+  17123,  5197,

+  17351,  2113,

+  17374,   980,

+  17566, 26214,

+  17609,  3912,

+  17639, 32767,

+  18151,  7871,

+  18197,  2516,

+  18202,  5649,

+  18679,  3283,

+  18930,  1370,

+  19271, 13757,

+  19317,  4120,

+  19460,  1973,

+  19654, 10018,

+  19764,  6792,

+  19912,  5135,

+  20040,  2841,

+  21234, 19833};

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h b/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h
new file mode 100644
index 0000000..baf5525
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h
@@ -0,0 +1,66 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*--------------------------------------------------------------------------*

+ *                         Q_PULSE.H                                        *

+ *--------------------------------------------------------------------------*

+ * Coding and decoding of algebraic codebook			            *

+ *--------------------------------------------------------------------------*/

+

+#ifndef  __Q_PULSE_H__

+#define  __Q_PULSE_H__

+

+#include "typedef.h"

+

+Word32 quant_1p_N1(                        /* (o) return (N+1) bits           */

+		Word16 pos,                           /* (i) position of the pulse       */

+		Word16 N);                            /* (i) number of bits for position */

+

+Word32 quant_2p_2N1(                       /* (o) return (2*N)+1 bits         */

+		Word16 pos1,                          /* (i) position of the pulse 1     */

+		Word16 pos2,                          /* (i) position of the pulse 2     */

+		Word16 N);                            /* (i) number of bits for position */

+

+Word32 quant_3p_3N1(                       /* (o) return (3*N)+1 bits         */

+		Word16 pos1,                          /* (i) position of the pulse 1     */

+		Word16 pos2,                          /* (i) position of the pulse 2     */

+		Word16 pos3,                          /* (i) position of the pulse 3     */

+		Word16 N);                            /* (i) number of bits for position */

+

+Word32 quant_4p_4N1(                       /* (o) return (4*N)+1 bits         */

+		Word16 pos1,                          /* (i) position of the pulse 1     */

+		Word16 pos2,                          /* (i) position of the pulse 2     */

+		Word16 pos3,                          /* (i) position of the pulse 3     */

+		Word16 pos4,                          /* (i) position of the pulse 4     */

+		Word16 N);                            /* (i) number of bits for position */

+

+Word32 quant_4p_4N(                        /* (o) return 4*N bits             */

+		Word16 pos[],                         /* (i) position of the pulse 1..4  */

+		Word16 N);                            /* (i) number of bits for position */

+

+Word32 quant_5p_5N(                        /* (o) return 5*N bits             */

+		Word16 pos[],                         /* (i) position of the pulse 1..5  */

+		Word16 N);                            /* (i) number of bits for position */

+

+Word32 quant_6p_6N_2(                      /* (o) return (6*N)-2 bits         */

+		Word16 pos[],                         /* (i) position of the pulse 1..6  */

+		Word16 N);                            /* (i) number of bits for position */

+

+

+#endif //__Q_PULSE_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab b/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab
new file mode 100644
index 0000000..52f0daf
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab
@@ -0,0 +1,347 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*-------------------------------------------------------------------*

+ *                         qisf_ns.h

+ *-------------------------------------------------------------------*

+ * Quantization tables for split by 5 VQ of ISFs for a background noise database

+ * Version whith no prediction

+ *-------------------------------------------------------------------*/

+

+#define ORDER   16            /* order of linear prediction filter */

+#define ISF_GAP 128

+

+#define SIZE_BK_NOISE1  64

+#define SIZE_BK_NOISE2  64

+#define SIZE_BK_NOISE3  64

+#define SIZE_BK_NOISE4  32

+#define SIZE_BK_NOISE5  32

+

+

+/* means of ISFs */

+ static Word16 mean_isf_noise[ORDER] = {

+

+   478,  1100,  2213,  3267,  4219,  5222,  6198,  7240,

+  8229,  9153, 10098, 11108, 12144, 13184, 14165,  3803};

+

+

+/* 28 bits */

+/*-------------------------------------------------------------------*

+ *  isf codebooks:  split-by-5 VQ                                    *

+ *                                                                   *

+ *  codebook   vector dimension    number of vectors                 *

+ *  ~~~~~~~~   ~~~~~~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~                 *

+ *     1            2                  64                            *

+ *     2            3                  64                            *

+ *     3            3                  64                            *

+ *     4            4                  32                            *

+ *     5            4                  32                            *

+ *-------------------------------------------------------------------*/

+

+/*------------------------------------------------*

+ * 1st split:   isf0 to isf1

+ *------------------------------------------------*/

+

+

+ static Word16 dico1_isf_noise[SIZE_BK_NOISE1*2] = {

+

+  -269,  -673,

+  -222,  -537,

+  -233,  -430,

+  -138,  -451,

+  -212,  -331,

+  -192,  -241,

+   -87,  -231,

+  -191,  -128,

+   -70,  -106,

+  -164,    -6,

+    74,  -179,

+    27,   -33,

+  -102,    74,

+  -162,   115,

+   -94,   172,

+    -6,   130,

+  -143,   234,

+    14,   218,

+   -65,   270,

+    88,   182,

+  -124,   341,

+   -44,   381,

+    38,   335,

+   117,   274,

+  -112,   454,

+    74,   431,

+    -5,   488,

+   175,   384,

+   -83,   561,

+   122,   529,

+    21,   601,

+   229,   481,

+   231,   303,

+   226,   608,

+   300,   372,

+   210,   187,

+   306,   265,

+   328,   473,

+   382,   331,

+   371,   132,

+   139,    58,

+   365,    21,

+   250,   -82,

+   443,   218,

+   483,   110,

+   426,   415,

+   579,   222,

+   518,   333,

+   573,   448,

+   455,   529,

+   685,   329,

+   332,   580,

+   595,   593,

+   468,   645,

+   762,   517,

+   326,   709,

+   485,   793,

+   130,   684,

+   671,   737,

+   354,   876,

+    88,   806,

+   -65,   706,

+   -35,  1016,

+   266,  1123};

+

+

+/*------------------------------------------------*

+ * 2nd split:   isf2 to isf4

+ *------------------------------------------------*/

+

+ static Word16 dico2_isf_noise[SIZE_BK_NOISE2*3] = {

+

+  -824,  -884,  -949,

+  -805,  -456,  -418,

+  -442,  -438,  -541,

+  -217,  -578,  -793,

+  -168,  -444,  -582,

+  -287,  -492,  -274,

+  -552,  -297,  -300,

+  -163,  -333,  -358,

+  -370,  -232,  -232,

+  -175,  -358,  -159,

+  -381,   -21,  -357,

+  -184,  -159,  -162,

+   -53,  -191,  -280,

+    18,  -267,  -215,

+  -138,    61,  -283,

+    71,   -95,  -294,

+    13,  -156,  -546,

+     0,   -83,   -79,

+    44,    97,  -316,

+   178,   -52,  -213,

+   222,  -261,  -422,

+   237,  -118,   -44,

+   141,   145,  -132,

+   363,    81,  -287,

+   213,    65,    34,

+  -107,    94,    -5,

+    91,   -29,   126,

+  -355,    51,   -41,

+  -219,   -76,   145,

+   -63,   100,   244,

+  -719,    44,    27,

+  -572,  -124,   155,

+  -423,   133,   315,

+  -917,    71,   224,

+  -268,   318,   131,

+   -93,  -190,   420,

+   -97,   122,   491,

+   -79,   317,   355,

+   130,   100,   325,

+    86,  -293,   210,

+   133,   258,   161,

+   176,   -73,   465,

+   195,   300,   384,

+   348,    22,   221,

+   376,   183,   409,

+   377,   286,   202,

+   242,   213,   659,

+   257,   565,   248,

+   344,   408,   -76,

+   405,   440,   509,

+   612,   385,   379,

+   536,   607,   216,

+   -56,   582,   192,

+   100,   517,   567,

+  -365,   448,   445,

+   728,   347,    10,

+   505,   357,   759,

+   636,   582,   658,

+   335,   517,   852,

+   378,   809,   572,

+  -195,   878,   829,

+   529,   707,   987,

+   918,   726,   392,

+  1250,   997,  1063};

+

+/*------------------------------------------------*

+ * 3rd split:   isf5 to isf7

+ *------------------------------------------------*/

+

+ static Word16 dico3_isf_noise[SIZE_BK_NOISE3*3] = {

+

+  -805,  -838,  -774,

+  -522,  -627,  -828,

+  -477,  -486,  -603,

+  -295,  -481,  -634,

+  -366,  -384,  -393,

+  -186,  -414,  -396,

+  -237,  -394,  -106,

+  -252,  -202,  -275,

+   -61,  -177,  -442,

+   -84,  -198,  -199,

+  -179,  -125,   -31,

+   -72,   -47,  -163,

+  -298,  -220,   215,

+   -64,  -168,   251,

+  -133,   156,   -59,

+   -30,    -2,   127,

+    54,    66,   -61,

+  -233,    21,   251,

+   209,   -50,    32,

+    33,   194,   136,

+  -117,   -18,   475,

+   202,    46,   309,

+   256,   185,    53,

+    35,   200,   390,

+   200,   263,   242,

+  -216,   302,   294,

+   128,   358,     0,

+    19,   431,   287,

+   224,   447,   280,

+   367,   165,   213,

+   397,   314,   319,

+   383,   379,    75,

+   277,   325,   462,

+   394,   505,   334,

+   251,    98,  -213,

+   450,   153,   448,

+   565,   226,    76,

+   470,   383,   502,

+   635,   390,   278,

+   237,   135,   620,

+   342,   401,   649,

+   331,   551,   518,

+   130,   418,   592,

+   531,   306,   737,

+   729,   389,   580,

+   497,   557,   699,

+   296,   383,   874,

+   283,   624,   759,

+   126,   622,   476,

+   559,   595,   472,

+   382,   770,   616,

+   719,   613,   745,

+   540,   639,   928,

+   517,   826,   801,

+   684,   811,   604,

+   752,   786,   857,

+   933,   661,   350,

+   694,   450,  1061,

+   562,   911,  1051,

+   824,   813,  1104,

+   758,  1047,   882,

+  1140,   917,   889,

+  1039,  1246,  1426,

+  1483,  1666,  1876};

+

+/*------------------------------------------------*

+ * 4th split:   isf8 to isf11

+ *------------------------------------------------*/

+

+ static Word16 dico4_isf_noise[SIZE_BK_NOISE4*4] = {

+

+  -776,  -854,  -891,  -920,

+  -552,  -610,  -663,  -741,

+  -321,  -370,  -476,  -565,

+   274,  -160,  -456,   201,

+   265,    67,  -160,  -306,

+    -8,  -210,    79,   272,

+   163,   236,   307,   308,

+   578,   317,    64,   298,

+    -9,   197,   342,   620,

+   343,   232,   314,   622,

+   173,   149,   548,   527,

+   356,   370,   481,   376,

+   135,   444,   488,   556,

+   391,   471,   487,   653,

+   228,   424,   576,   835,

+   422,   372,   722,   682,

+   295,   673,   693,   635,

+   539,   596,   590,   449,

+   475,   618,   659,   818,

+   735,   517,   491,   673,

+   602,   346,   257,   877,

+   625,   635,   849,   720,

+   727,   818,   698,   595,

+   653,   481,   690,  1139,

+   814,   762,   704,   908,

+   507,   747,   898,   936,

+   848,   855,   924,   785,

+   646,  1037,   882,   795,

+   772,   845,  1024,  1151,

+  1133,   983,   818,   921,

+   940,  1068,  1252,  1302,

+  1588,  1767,  1718,  1513};

+

+/*------------------------------------------------*

+ * 5th split:   isf12 to isf15

+ *------------------------------------------------*/

+

+ static Word16 dico5_isf_noise[SIZE_BK_NOISE5*4] = {

+  -810,  -879,  -945,  -254,

+   248,   184,   671,   128,

+   288,   703,   918,    99,

+   658,   558,   662,   219,

+   552,   585,   910,   208,

+   559,   804,   759,   119,

+   606,   774,   921,  -139,

+   782,   761,   748,   208,

+   756,   708,   983,    56,

+   544,   864,  1010,   152,

+   737,   698,   987,   299,

+   771,   924,   879,   103,

+   536,   785,   961,   405,

+   667,   916,   801,   328,

+   738,   705,   773,   439,

+   823,   871,   992,   355,

+   640,  1004,  1052,   369,

+   724,   822,   949,   597,

+   415,   655,   729,   482,

+  1009,   896,   793,   363,

+   908,   803,   687,   -25,

+  1016,   838,  1011,   189,

+   947,  1112,   942,   222,

+   914,  1049,   981,   527,

+   956,   987,  1011,  -120,

+   781,  1049,  1121,    92,

+  1178,  1053,   884,    47,

+  1123,  1059,  1182,   118,

+   933,   972,  1277,   357,

+  1109,   918,  1101,   503,

+  1039,  1286,  1220,   317,

+  1351,  1207,  1010,   326};

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab b/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab
new file mode 100644
index 0000000..4d869a4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab
@@ -0,0 +1,1360 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*-------------------------------------------------------------------*

+ *                         qpisf_2s.h

+ *-------------------------------------------------------------------*

+ * Quantization tables for two-stage of ISFs (split by 2 in 1st stage)

+ * Version whith prediction MU = 0.25

+ *-------------------------------------------------------------------*/

+

+#define ORDER   16            /* order of linear prediction filter */

+#define ISF_GAP 128           /* 50 Hz */

+#define N_SURV  4

+

+#define SIZE_BK1  256

+#define SIZE_BK2  256

+#define SIZE_BK21 64

+#define SIZE_BK22 128

+#define SIZE_BK23 128

+#define SIZE_BK24 32

+#define SIZE_BK25 32

+

+#define SIZE_BK21_36b 128

+#define SIZE_BK22_36b 128

+#define SIZE_BK23_36b 64

+

+/* means of ISFs */

+static Word16 mean_isf[ORDER] = {

+

+   738,  1326,  2336,  3578,  4596,  5662,  6711,  7730,

+  8750,  9753, 10705, 11728, 12833, 13971, 15043,  4037};

+

+/* 46 bits */

+/*-------------------------------------------------------------------*

+ *  isf codebooks:  two-stage VQ with split-by-5 in 2nd stage        *

+ *                                                                   *

+ *  codebook   vector dimension    number of vectors                 *

+ *  ~~~~~~~~   ~~~~~~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~                 *

+ *     1_1            9                  256                         *

+ *     1_2            7                  256                         *

+ *     2_1            3                  64                          *

+ *     2_2            3                  128                         *

+ *     2_3            3                  128                         *

+ *     2_4            3                  32                          *

+ *     2_5            4                  32                          *

+ *-------------------------------------------------------------------*/

+

+/*------------------------------------------------*

+ * 1st stage codebook; 1st split:   isf0 to isf8

+ *------------------------------------------------*/

+

+static Word16 dico1_isf[SIZE_BK1*9] = {

+

+   579,  1081,  1035,   390,     3,  -263,  -198,   -82,    38,

+    18,   -68,   -12,   313,   761,   405,   249,   111,   -76,

+   740,  1263,  1292,  1006,   997,  1019,  1017,   976,   923,

+   -91,   827,   948,   648,   613,   535,   522,   490,   421,

+    41,   -44,  -281,  -472,   652,   534,   193,   135,   -90,

+    41,  -121,  -356,   -60,   663,   307,    61,   -48,  -344,

+   557,   946,  1049,   867,   846,   990,  1112,  1262,  1241,

+  -118,  -204,   328,   512,   870,   793,   610,   402,   186,

+   156,   293,    74,  -338,  -475,  -897,  -594,  -161,  -497,

+   226,   131,  -138,   307,   169,  -271,  -164,  -387,  -624,

+    62,   -32,   -61,  -252,  -541,  -828, -1027,  -523,  -662,

+   102,   -61,   141,   112,  -270,  -251,  -541,    25,  -150,

+     6,  -132,  -356,  -686,   -96,  -322,  -522,   -31,  -326,

+   -36,  -209,  -521,  -229,   307,  -132,    -5,   -99,  -384,

+    60,   -51,  -237,  -668,  -973,  -407,  -708,   -75,  -172,

+    26,  -138,  -266,   111,  -302,    43,  -278,  -356,  -359,

+   570,   822,   496,  -154,  -312,   -92,   137,   279,   371,

+  -146,   368,   409,    68,     6,    77,   167,   202,   162,

+   633,   898,   996,   756,   662,   683,   783,   909,   996,

+  -103,   294,   607,   415,   483,   462,   480,   431,   408,

+  -120,  -338,  -612,  -524,   584,   331,    92,   433,   276,

+  -178,  -293,  -154,   -41,   269,   100,    -9,   213,   160,

+   830,   736,   278,   820,  1254,   686,   712,  1039,   473,

+  -218,  -304,   463,   454,   397,   273,   202,   286,   273,

+  -232,     7,     6,  -388,  -472,  -427,  -378,  -167,  -100,

+  -294,  -183,   134,   -47,   101,   -88,   -84,  -117,    -3,

+    57,    17,  -202,  -634,  -989, -1119,  -533,   176,   -36,

+   120,   -28,    23,   111,  -319,   318,   -22,   -77,   266,

+  -271,  -464,  -434,  -658,  -640,  -385,  -385,   -99,   -69,

+  -198,  -259,  -266,   -44,   -39,  -139,  -137,   171,    66,

+     9,  -145,  -377,  -846, -1000,  -111,  -325,   342,   135,

+   -81,  -286,  -380,   192,   -57,   307,    76,   -24,  -140,

+   677,   702,   247,    56,   249,   141,  -105,  -236,   -99,

+    36,   -39,   -69,   348,   198,   -93,   322,    91,   -72,

+   503,   885,  1508,  1307,  1282,  1172,  1119,  1209,  1061,

+   416,   719,   989,  1227,  1001,  1052,   954,   741,  1044,

+  -127,  -376,  -657,   139,   623,   223,   501,   306,   220,

+  -113,  -384,  -796,   504,   438,    85,   213,   -83,  -194,

+   585,  1132,  1233,  1091,  1247,  1433,  1512,  1448,  1314,

+  -174,  -422,     7,  1155,  1089,  1182,  1003,   945,   806,

+     8,  -126,  -317,  -103,  -351,  -695,   -98,  -268,  -537,

+    33,  -103,  -290,   167,   -39,  -407,    44,  -208,  -375,

+   104,   -23,   -64,  -291,  -637,  -851, -1084,   -61,  -112,

+   -75,  -306,  -434,   218,  -148,  -354,  -680,  -133,  -216,

+  -121,  -377,  -718,   -97,  -130,  -361,  -156,  -379,  -599,

+   -56,  -254,  -586,   235,   157,  -214,    11,  -260,  -149,

+  -124,  -267,  -397,  -580,  -593,  -527,  -805,  -385,   346,

+  -193,  -440,  -708,  -351,  -141,  -255,  -499,  -147,  -185,

+   448,   660,   494,   208,   509,   461,   338,   291,   149,

+  -223,    88,   335,   159,   212,   191,   286,   308,   205,

+   -31,   469,   803,   659,   619,   658,   843,   987,  1113,

+  -171,  -242,   514,   362,   295,   524,   552,   694,   585,

+   -64,  -308,  -448,   -21,   284,   786,   446,   289,    92,

+  -218,  -390,    -7,   169,   206,   330,   352,   408,   358,

+   -36,   702,   959,   859,   861,  1115,  1269,  1357,  1305,

+  -133,  -341,   -65,   678,   417,   440,   486,   518,   780,

+    33,   -44,  -191,  -344,  -461,  -755,  -201,   217,   -31,

+  -353,  -547,   -44,   123,   -61,   -68,   -79,    29,    60,

+    73,   -57,  -406,  -766, -1243, -1203,   240,   400,   165,

+   -73,  -282,  -601,  -213,  -171,  -375,   332,    35,  -103,

+   -29,  -207,  -553,  -476,  -638,  -908,   172,   -22,  -135,

+  -192,  -239,  -164,  -103,  -111,   -47,   153,   125,   110,

+    -1,  -203,  -570, -1030, -1424,  -535,   155,     1,   147,

+  -333,  -653,  -865,  -197,  -158,   -21,   -44,    95,   108,

+   389,   588,   490,    33,  -237,  -524,  -628,  -136,  -260,

+    40,  -177,  -462,   453,   862,   380,   131,  -130,  -405,

+   842,  1678,  1841,  1549,  1474,  1256,  1082,   905,   742,

+   370,  1216,  1768,  1633,  1212,   636,    22,  -330,    71,

+   -76,  -281,  -741,  -742,   898,   619,   277,    71,  -222,

+   -32,  -265,  -556,   -25,   994,   682,   305,   126,  -165,

+    73,   738,   893,   968,   993,  1768,  2273,  1840,  1391,

+   -69,  -349,  -585,   234,  1158,   903,   626,   510,   251,

+    -1,   -99,  -272,  -210,  -603,  -351,  -540,  -811,  -383,

+   -16,  -230,  -504,   410,   149,  -205,  -343,  -651,  -639,

+   103,    -9,  -227,  -205,  -562,  -781, -1079, -1208,  -156,

+   143,    63,  -135,   -67,  -317,  -602,  -784, -1154,  -640,

+  -144,  -391,  -674,  -622,  -200,  -254,  -660,  -947,  -395,

+   -40,  -250,  -625,    27,   543,    94,  -131,  -386,  -673,

+  -123,  -371,  -757,  -451,  -564,  -614,  -415,  -711,   -35,

+  -116,  -309,  -593,  -268,   239,   -33,  -338,  -650,  -135,

+    94,   251,   554,    57,  -312,  -423,  -154,   -57,   235,

+  -268,   -71,   381,   114,   -44,   -87,   125,   173,   133,

+  1513,  1714,  1238,   534,   276,   315,   461,   459,   508,

+  -131,   -19,  1149,   670,   486,   356,   309,   369,   296,

+  -223,  -501,  -899,  -722,   -70,     6,   131,   310,   394,

+   -99,  -303,  -517,   249,    64,   -53,   135,   -11,   453,

+  -147,  -399,  -730,  -401,   817,   738,   802,   749,   575,

+  -154,  -435,  -739,   800,   593,   366,   529,   318,   326,

+  -224,    45,   -39,  -387,  -515,  -518,  -608,  -384,  -321,

+  -315,  -377,   143,  -101,  -113,  -377,  -177,  -144,   -12,

+   117,    40,  -239,  -651, -1051,  -581,  -737,  -990,  -328,

+    26,   -50,  -157,   -23,  -453,  -283,  -531,  -546,   192,

+  -252,  -501,  -743,  -589,  -627,  -499,  -328,  -118,   -72,

+  -324,  -494,  -244,  -306,  -144,  -177,  -262,  -135,   -78,

+   -36,  -234,  -519,  -961, -1290,  -314,  -479,  -371,   -45,

+   -95,  -292,  -535,    -8,  -300,   112,  -164,  -277,   198,

+   -99,  -128,   880,   836,   579,   351,    23,   -95,  -217,

+   -27,  -258,   124,  1011,   597,   425,   144,     7,   -73,

+   421,  1293,  1640,  1623,  1742,  1617,  1499,  1284,  1006,

+   -95,   752,  1680,  1569,  1618,  1436,  1200,   980,   712,

+   -69,  -300,  -683,  -435,  1132,   899,   504,   332,   109,

+   -74,  -323,  -637,   563,  1074,   608,   371,   105,   -49,

+   -78,   831,  1194,  1110,  1378,  1481,  1492,  1365,  1217,

+  -259,  -121,  1440,  1334,  1628,  1490,  1438,  1223,   933,

+   -82,  -306,  -613,  -222,  -378,  -675,  -545,  -671,  -845,

+    53,  -124,  -347,   422,    52,  -125,  -270,  -529,     9,

+    79,   -89,  -320,  -662,  -999, -1199, -1243,  -676,  -297,

+   -68,  -273,  -611,   137,  -146,  -397,  -627,  -845,  -220,

+  -112,  -346,  -797,  -826,   234,  -132,  -188,  -278,  -522,

+  -159,  -405,  -734,  -419,   293,    74,  -167,  -167,   184,

+  -153,  -437,  -833, -1080,  -336,  -472,  -561,  -340,  -253,

+  -169,  -423,  -820,  -904,  -131,   -19,  -346,  -604,    31,

+    33,   -31,   312,    62,  -148,    49,   -59,   564,   486,

+  -306,  -333,   194,   -44,    67,    72,   147,   205,   243,

+  -207,   -49,  1360,   983,   969,   991,  1014,  1110,   973,

+  -211,  -172,   883,   627,   711,   674,   705,   798,   746,

+   -88,  -325,  -763,  -974,   687,   908,   514,   382,   172,

+  -292,  -612,  -805,    63,   131,   270,   259,   352,   348,

+  -235,   -84,   955,   818,  1120,  1289,  1559,  1480,  1285,

+  -180,  -461,  -614,   657,   691,   745,   854,   783,   713,

+   -97,  -309,  -477,  -614,  -777,  -734,  -768,  -526,  -472,

+  -344,  -476,   -35,  -169,    49,   -77,  -150,  -240,  -141,

+   -52,  -268,  -639,  -919, -1278, -1113,  -342,  -333,  -151,

+   -68,  -242,  -585,   -73,  -209,  -478,  -159,  -429,   133,

+  -197,  -499, -1005, -1268,  -272,  -224,  -105,   -67,    17,

+  -363,  -618,  -414,  -116,   -62,    20,    10,   116,   108,

+  -195,  -475,  -906, -1260,  -891,  -441,  -277,  -142,   -28,

+  -226,  -519,  -950,  -700,  -275,  -266,  -116,  -105,    82,

+   404,   511,   520,   327,    17,  -194,  -333,  -536,  -586,

+  -114,  -130,   276,   237,   204,   342,   135,   -16,  -111,

+   670,  1208,  1168,   860,   742,   601,   528,   403,   309,

+   397,   621,   966,   752,   579,   398,   400,   329,   252,

+   191,   180,  -137,  -467,   272,   106,   -95,    17,  -192,

+   -80,  -290,  -626,   194,   598,   196,    21,  -281,    77,

+   510,   864,  1108,   807,   939,   902,   925,   717,   481,

+   137,   367,   534,   764,   670,   382,   296,   153,    84,

+   303,   497,   144,   -85,  -125,  -539,  -482,  -464,  -764,

+   233,   347,    68,  -147,   169,  -210,  -242,  -226,  -482,

+   307,   422,   154,  -175,  -386,  -722,  -724,  -904, -1015,

+   309,   308,   160,   -60,  -470,  -420,  -598,  -791,  -219,

+    68,   121,  -137,  -560,  -146,  -446,  -515,  -494,  -729,

+   130,    53,  -227,    46,   474,    32,  -161,  -192,  -490,

+   213,   164,   -71,  -465,  -876,  -161,  -456,  -587,   -48,

+   218,   117,    39,   177,  -194,   -88,  -226,  -418,    50,

+   210,   547,   569,   279,   121,   -44,   -50,    10,   -84,

+    58,   140,   182,    -5,   267,   117,   106,   211,   198,

+   539,   835,   913,   719,   617,   544,   591,   565,   642,

+   153,   559,   872,   460,   222,   108,   188,   180,   183,

+   158,   119,   284,  -153,  -271,   229,    87,   110,   -57,

+  -183,    82,   118,    21,    13,    40,   118,   191,   185,

+   162,   889,   654,   108,   -34,   244,   488,   561,   532,

+   163,    56,   609,   341,    50,   329,    68,   266,   218,

+   100,   206,    18,  -304,  -107,  -436,  -487,   -65,  -306,

+   -86,   154,   134,   -30,   -45,   -73,  -104,   -80,   -96,

+   245,   330,    10,  -440,  -849, -1082,    79,    40,  -265,

+   196,   372,   272,  -181,  -493,  -389,   275,    80,   -59,

+     2,   -12,  -246,  -505,  -100,  -436,    21,  -187,  -431,

+  -221,   -48,    36,  -271,  -186,  -147,  -109,    26,    71,

+   213,   140,    72,  -351,  -620,   -84,  -363,    69,    46,

+    91,   167,    -3,   -95,   -99,  -105,   -48,   114,   147,

+   259,   249,   172,   607,   406,    52,    59,  -189,  -320,

+   115,   -85,   -54,   574,   128,   226,   -59,  -253,   130,

+   -62,  1033,  1308,  1035,  1127,  1098,  1029,   961,   823,

+    39,   364,   757,   940,   728,   660,   659,   583,   770,

+  -115,  -338,  -760,  -471,   394,    37,   441,   178,     6,

+   -57,  -305,  -525,   796,   453,   188,    -4,  -114,   248,

+    71,   444,   797,   731,  1096,  1157,  1222,  1029,   811,

+   135,   359,   551,   425,   749,   815,   874,   704,   502,

+   132,   247,     0,  -206,  -449,  -750,  -258,  -514,  -633,

+   248,   249,    91,   121,  -195,  -499,   -90,  -282,  -435,

+    78,    20,  -277,  -623,  -983, -1224,  -415,  -458,  -639,

+   347,   509,   208,  -179,  -464,  -728,   -76,  -237,  -486,

+  -103,  -343,  -756,  -713,  -265,  -609,  -191,  -398,  -636,

+  -121,  -383,  -749,   567,   252,   -36,  -354,  -417,   -50,

+   204,   100,  -149,  -650, -1081,   -47,    -7,  -263,   111,

+   -46,  -180,  -267,  -324,  -562,  -394,  -692,   398,   292,

+   482,   670,   683,   624,   442,   165,   116,    36,  -149,

+   108,   247,   291,   247,   355,   122,   109,   224,   296,

+   -14,   945,   990,   801,   755,   815,   847,   913,   892,

+   292,   349,   725,   482,   388,   329,   429,   620,   667,

+   -34,   197,   213,  -127,    84,   494,   620,   575,   375,

+   126,   207,   172,   167,   362,   202,   296,   395,   455,

+    -6,   250,   539,   467,   636,   801,  1149,  1287,  1118,

+    27,   240,   369,   280,   440,   411,   634,   892,   953,

+   159,   170,   -58,  -395,  -797,  -690,    77,  -211,  -334,

+    -5,   -28,   -13,   -74,  -335,  -603,   300,    88,  -205,

+    82,   -33,  -364,  -698, -1203, -1153,   110,  -146,  -289,

+   113,     1,  -243,  -588,  -994,  -496,   414,   160,    42,

+   -56,  -247,  -440,  -693,  -996,  -479,    11,  -178,  -357,

+  -151,  -353,  -327,  -211,  -340,   141,    65,   425,   453,

+    34,  -169,  -455,  -932, -1215,   138,   499,   256,   324,

+    68,   139,   -15,  -547,  -478,    17,   306,   502,   481,

+   -32,  -134,   445,   129,  -143,  -244,  -503,  -507,  -599,

+    61,  -140,  -345,   496,   458,    -2,    20,  -227,  -514,

+   394,  1765,  1666,  1339,  1117,   806,   642,   479,   380,

+   215,   519,   920,  1053,  1090,   791,   528,   290,   155,

+   -54,  -233,  -647,  -602,   639,   294,    -2,  -167,  -442,

+   -78,  -315,  -791,  -113,   820,   403,   158,  -116,  -356,

+   529,  1851,  2003,  1228,   622,   -41,  -416,   344,   819,

+  -105,  -379,  -236,  1224,   893,   749,   568,   356,   214,

+   -17,  -199,  -144,    50,  -283,  -247,  -578,  -846, -1087,

+    69,   -11,  -381,  -206,   209,  -284,  -387,  -416,  -716,

+    39,    -5,  -145,  -374,  -682,  -909, -1074, -1169, -1066,

+   287,   226,    67,  -221,  -662,  -171,  -421,  -642,  -707,

+  -132,  -348,  -538,  -448,   -20,    -4,  -354,  -748,  -933,

+     4,   -75,  -289,  -598,   317,    52,  -208,  -297,  -559,

+   -88,  -264,  -358,  -589,  -631,  -248,  -523,  -822, -1071,

+    70,    -8,    54,  -314,  -515,    92,  -146,  -274,  -493,

+   199,    62,   391,   158,  -141,    71,  -219,  -203,  -207,

+   152,    40,   329,   162,   -29,    48,  -149,   108,   127,

+   635,  1058,   883,   492,   372,   312,   317,   274,   241,

+   267,   722,  1256,   882,   625,   248,     8,   -81,   -60,

+   -58,  -138,  -291,  -600,   -12,    -2,   -39,   147,   117,

+  -107,  -345,  -513,   459,    76,    92,  -272,   388,   262,

+   362,   516,   203,  -409,  -716,  -831,  -331,   185,   209,

+  -117,  -391,  -298,   671,   292,   538,   257,   166,   -38,

+  -102,  -319,  -194,  -283,  -573,  -262,  -579,  -219,  -444,

+  -235,    78,    11,  -168,  -101,  -229,  -263,  -321,  -123,

+    70,    50,  -170,  -599,  -996,  -588,  -263,  -516,  -455,

+   394,   363,   229,  -136,  -538,    21,  -183,  -348,  -201,

+  -124,  -368,  -640,  -879,  -847,  -209,  -409,  -494,  -515,

+  -127,  -341,  -541,  -425,  -510,   -10,  -252,  -473,  -291,

+    84,   -69,  -201,  -676,  -868,   103,  -311,  -132,  -320,

+     5,  -173,  -188,  -297,  -628,   197,   -57,     7,   -11,

+    49,  -160,    56,   558,   111,    33,  -311,  -440,  -463,

+    -1,  -246,  -307,   862,   453,   139,  -170,  -355,  -232,

+   279,   966,  1642,  1478,  1463,  1123,   795,   525,   339,

+  -197,   -38,  1702,  1331,  1252,   950,   692,   504,   426,

+  -108,  -344,  -861, -1172,   444,   354,    88,   -46,  -220,

+   -53,  -321,  -494,  1113,   744,   364,   198,   -34,   -75,

+   457,   955,  1177,  1214,  1427,  1457,  1345,   917,   539,

+   -69,   199,   897,  1140,  1343,  1183,   977,   742,   522,

+   122,    44,  -269,    27,  -155,  -562,  -307,  -590,  -773,

+   154,    42,  -160,   252,  -129,  -305,  -471,  -733,  -371,

+   135,   185,   -82,  -416,  -722,  -913,  -504,  -743,  -880,

+   149,   214,   -84,  -329,  -680,  -835,  -426,  -661,   -81,

+  -128,  -380,  -735,  -998,  -337,    17,  -182,  -467,  -697,

+   -84,  -290,  -510,  -592,    13,   440,   154,   -38,  -279,

+    70,   -61,  -246,  -727, -1047,   -80,  -381,  -535,  -704,

+   178,    -2,  -146,  -670,  -938,   482,   138,    63,    65,

+   -11,    15,   772,   443,   142,   -20,  -209,  -126,  -161,

+   -32,  -249,    95,   552,   124,    30,  -343,    82,   -86,

+   148,   751,  1515,  1105,   867,   606,   474,   448,   399,

+  -163,  -257,   899,  1097,   906,   751,   502,   390,   294,

+   -51,  -258,  -447,  -806,  -368,   763,   464,   364,   183,

+  -166,  -374,  -367,    87,    35,   399,   418,   856,   833,

+  -205,  -310,   588,   778,   785,  1065,  1118,  1245,  1157,

+  -173,  -312,   107,   345,   400,   790,   870,  1113,  1001,

+    -7,  -120,  -387,  -410,  -614,  -943,  -226,  -384,  -491,

+  -203,  -288,   -51,  -331,   -90,  -178,  -408,  -573,  -338,

+    56,   -29,  -273,  -627, -1041,  -798,  -247,  -467,   148,

+    66,    -2,  -205,  -205,  -575,  -349,   -57,  -352,   -58,

+   -45,  -225,  -471,  -924,  -497,    77,   -32,    44,  -135,

+  -277,  -491,  -497,  -502,  -424,  -202,  -137,    77,    96,

+    26,  -179,  -469, -1008, -1260,   262,   -35,  -132,  -259,

+   -66,  -232,  -447,  -533,  -789,  -191,  -100,  -267,   364};

+

+/*------------------------------------------------*

+ * 1st stage codebook; 2nd split:   isf9 to isf15

+ *------------------------------------------------*/

+

+static Word16 dico2_isf[SIZE_BK2*7] = {

+

+  1357,  1313,  1136,   784,   438,   181,   145,

+   636,   648,   667,   568,   442,   217,   362,

+   427,   440,   674,   524,   332,   117,  -417,

+   121,   295,   468,   465,   230,    44,  -221,

+  -147,  -240,   149,    80,   390,   278,   106,

+  -418,  -556,   552,   511,   235,   144,   -95,

+    43,   193,   274,   150,    67,    34,  -273,

+   -43,  -126,   171,   416,   282,    63,  -354,

+  -372,   -86,  -344,  -108,   -94,  -182,   -89,

+  -600,  -840,  -200,   465,   258,   -11,  -253,

+   -48,   329,    97,  -290,  -543,  -795,  -354,

+  -570,  -117,   187,    10,  -133,  -416,   -76,

+  -618,  -129,  -247,  -371,    45,   -76,   277,

+ -1022, -1079,   126,   474,   254,   127,    52,

+  -281,    76,  -167,  -361,  -283,  -551,  -283,

+  -119,   -52,    -1,   134,   -32,  -204,  -415,

+  1064,   827,   637,   684,   464,   209,    12,

+   482,   416,   449,   371,   335,   294,   194,

+   719,   576,   365,   135,   113,    91,  -199,

+   298,   176,   493,   366,   194,   163,    36,

+   -35,  -236,  -259,   -36,    -4,    99,   152,

+   -98,  -306,   -27,   228,    90,   111,   -86,

+    91,    13,  -211,  -258,  -106,    86,   -64,

+    73,   -35,   -57,   -31,   162,    35,  -192,

+  -109,  -335,  -629,   -66,   -61,  -128,   322,

+  -495,  -669,  -728,   193,    31,  -220,   122,

+   324,    95,   -89,   -91,  -409,  -710,  -154,

+     0,  -234,    92,    33,  -343,  -609,  -220,

+  -343,  -408,  -476,  -655,  -153,    82,   222,

+  -490,  -745,  -255,    49,   -48,   135,  -127,

+   119,   -67,  -328,  -390,  -272,  -545,   -56,

+   -57,  -130,   -10,    -7,  -164,   -47,   -22,

+   984,  1064,   961,   568,   210,   -27,    16,

+   811,   691,   754,   514,   224,   -35,   166,

+   662,   704,   618,   386,    57,  -211,  -257,

+   510,   359,   418,   393,    91,  -144,   -18,

+  -193,   -31,   -27,   223,    89,  -143,    24,

+  -112,   -98,   471,   319,   185,     3,   175,

+   252,   146,   -47,   272,    48,  -211,  -234,

+   146,    69,   203,   364,    68,   -52,    51,

+  -259,  -478,  -697,  -349,  -758,  -501,    63,

+  -501,  -769,  -289,    79,  -311,  -497,  -106,

+   251,    53,  -235,  -469,  -895,  -884,   145,

+  -416,  -551,   140,  -133,  -523,  -775,    44,

+  -326,  -423,  -713,  -497,   -86,  -431,    99,

+  -757,  -772,  -160,   -76,   -46,   -32,   379,

+    85,   -35,  -200,  -401,  -663, -1040,  -247,

+  -180,  -330,   -92,  -376,    27,  -183,  -110,

+  1279,  1086,   781,   502,   324,   164,   157,

+   682,   466,   449,   277,   146,    28,   409,

+   635,   472,   390,   107,  -232,  -538,  -139,

+   196,   396,   332,   213,   209,   -29,   -81,

+   150,   -95,  -312,    76,   -77,  -320,   -50,

+    46,     9,    47,   175,   139,    30,   384,

+   218,   206,   -24,  -250,   -96,  -276,  -183,

+    26,   119,    38,    14,    -4,  -133,   -52,

+  -477,  -614,  -987,  -715,  -631,  -813,   200,

+  -744, -1009, -1065,  -745,  -631,  -171,    18,

+  -137,  -251,  -483,  -613,  -980, -1203,    12,

+  -605,  -767,  -562,  -686, -1088,  -515,    58,

+  -202,  -428,  -782, -1072,   -96,  -234,  -179,

+  -480,  -709, -1070,  -897,  -131,   -92,   321,

+  -145,  -193,  -512,  -729,  -572,  -765,  -210,

+  -331,  -585,  -525,  -631,  -281,  -208,  -303,

+  1165,  1104,   939,   828,   716,   426,   155,

+     6,  -109,   820,   778,   415,   113,   -27,

+   381,   339,   314,   265,   121,    -9,  -474,

+  -373,    47,   584,   442,    99,  -231,  -113,

+  -496,   -38,  -285,   262,   305,   170,     4,

+  -587,  -556,    69,    66,   471,   354,    13,

+  -138,    70,   -18,   106,    67,   167,  -302,

+  -445,  -141,   185,   191,   151,    83,  -133,

+  -257,  -521,  -720,  -198,   134,   -46,  -182,

+  -819, -1168,  -777,   512,   359,    95,  -113,

+   137,    -2,   -74,  -138,  -401,  -114,  -371,

+  -242,  -466,   204,   223,   -31,  -212,  -192,

+  -532,  -637,  -466,  -686,   256,   277,  -139,

+ -1141, -1244,  -381,   -75,   -54,    14,    88,

+  -311,   115,  -143,  -499,  -343,   124,  -416,

+  -616,  -147,  -135,    43,    -4,   121,  -369,

+   835,   783,   641,   390,   355,   350,    64,

+    72,   194,   443,   467,   436,   219,   372,

+   464,   369,   192,     4,  -156,   -72,  -226,

+    57,   206,   303,   205,   188,   101,   265,

+   -40,  -205,  -488,  -184,   276,    64,   -26,

+  -217,  -433,  -297,   137,   328,   308,  -289,

+   378,    81,  -308,  -465,    57,   -37,   227,

+  -100,    24,   -36,  -151,   199,     8,   143,

+  -426,  -697, -1059,  -133,   388,   161,   321,

+  -644, -1023, -1271,    39,    66,  -123,    70,

+   372,   177,  -173,  -556,  -553,  -304,  -189,

+  -117,  -369,  -425,  -122,  -462,  -152,   -73,

+  -649,  -850, -1189,  -767,   497,   360,   222,

+  -798, -1139, -1455,  -190,   430,   234,   179,

+    42,   -94,  -405,  -692,    38,  -202,  -246,

+  -169,  -366,  -290,   -88,   -64,    32,  -292,

+  1010,   923,   938,   710,   465,   230,   342,

+   217,   300,  1054,   675,    68,  -458,  -179,

+    78,   453,   316,    18,  -237,  -496,  -243,

+   167,    21,   424,   215,   -91,  -303,  -170,

+  -290,   -81,   -70,   -67,    40,    54,   -59,

+  -353,  -427,   -90,    53,    94,     9,    54,

+   -28,   318,   283,    15,  -240,   -58,    79,

+   -75,  -121,   229,    35,    58,     6,  -133,

+  -351,  -514,  -744,  -834,  -705,  -137,   164,

+ -1124, -1388, -1055,  -230,   -73,    40,    36,

+  -163,  -233,  -532,  -785, -1170,  -697,    96,

+  -788,  -959,  -246,  -430,  -624,  -165,    -8,

+  -856,  -540,  -630,  -907,  -337,   -70,    76,

+  -937, -1042,  -659,  -733,  -208,   199,   -26,

+  -523,    78,   -98,  -501,  -869,  -890,   -81,

+  -624,  -703,   -45,  -348,   -25,    87,  -186,

+  1005,   823,   546,   249,    90,   -22,   207,

+   298,   397,   381,   319,   200,    62,   303,

+   473,   379,   133,  -247,  -632,  -441,    75,

+   284,   208,   391,   115,   -25,    44,    95,

+   -72,    79,   -95,   -63,  -129,  -293,   203,

+  -164,  -349,   115,   122,    69,    -1,   378,

+   348,   170,    99,    58,  -179,  -302,   188,

+  -190,    -2,   150,    23,   -51,   -11,   216,

+  -615,  -863, -1090, -1427,  -802,   -48,    -6,

+  -961, -1276, -1548,  -727,   -58,    56,   223,

+  -124,  -255,  -561,  -988, -1277,  -148,   -82,

+  -480,  -660,  -891, -1191, -1339,  -325,    20,

+  -621,  -917, -1296, -1350,   264,   289,    50,

+  -844, -1022, -1345, -1329,  -293,    46,   278,

+  -260,  -468,  -829, -1176,  -533,  -560,   -78,

+  -215,  -484,  -822, -1233,  -791,    15,  -138,

+  1301,  1317,  1262,  1048,   716,   357,   -64,

+   578,   824,   925,   802,   630,   362,   102,

+   470,   925,   767,   514,   327,   190,  -112,

+   225,   492,   495,   437,   598,   384,   -45,

+    43,    82,   -42,   175,   519,   342,   -64,

+  -304,  -154,   159,   576,   403,   221,   327,

+   214,   244,   122,   -62,   312,    92,  -160,

+   218,   208,   310,   268,   306,   323,  -199,

+  -285,  -269,   -79,  -124,  -143,  -153,   236,

+  -205,  -384,  -426,   344,    59,  -185,  -184,

+  -272,   247,   126,  -210,  -518,  -468,    78,

+   -99,  -120,   502,   160,  -280,  -557,   304,

+  -423,   -17,  -283,  -443,   215,   212,  -140,

+  -564,  -684,  -228,   510,   361,   130,   323,

+  -428,   335,    98,   -65,    36,  -215,  -246,

+  -362,    51,   364,   -16,  -234,   150,  -165,

+   914,   883,   751,   653,   676,   464,  -153,

+   631,   545,   535,   720,   596,   360,   -81,

+   783,   712,   512,   439,   341,   251,  -391,

+   497,   417,   249,   372,   295,   173,  -193,

+   128,  -110,  -385,    93,    39,   173,  -231,

+   216,   -59,  -253,   462,   389,   154,    69,

+   455,   270,    -4,  -337,   -49,   233,  -322,

+   307,   143,    53,   218,   128,   236,  -156,

+   -37,  -186,  -240,  -411,  -110,     9,   399,

+  -140,  -365,  -628,   258,   380,   214,   277,

+   131,   454,   177,  -285,  -520,   108,  -214,

+    77,  -141,   201,  -123,  -490,  -131,    60,

+   -14,  -194,  -521,  -741,   273,   362,   -33,

+  -362,  -566,  -287,  -228,   161,   237,   317,

+  -269,   195,   -75,  -375,  -204,    11,    77,

+  -128,  -264,  -156,  -223,  -475,   265,    27,

+  1238,  1147,   916,   689,   432,   210,  -280,

+   800,   664,   879,   726,   411,   160,  -164,

+   454,   686,   536,   275,   147,    46,   111,

+   303,   486,   512,   355,   241,   181,   -69,

+    79,    92,    29,   147,   233,    52,    17,

+  -171,   289,   131,   439,   271,     3,   -10,

+   413,   241,   144,   174,   155,    -2,    14,

+    58,   217,   247,   219,   149,   175,   -18,

+   228,    -8,  -240,  -206,  -513,  -191,   202,

+   -96,  -272,  -454,    33,  -300,  -575,    46,

+   -10,  -108,  -246,  -347,  -770,  -535,     9,

+  -326,  -430,   -61,  -321,  -704,  -299,   201,

+    -1,  -280,  -603,  -419,  -185,    18,   -36,

+  -516,  -522,  -379,  -291,  -181,   -97,    27,

+  -159,  -313,  -525,  -224,  -510,  -831,  -197,

+  -292,  -459,   -59,  -310,  -562,  -143,  -351,

+  1066,   912,   631,   389,   207,    86,  -224,

+   596,   512,   596,   505,   314,   122,   -48,

+   787,   861,   441,   -93,  -303,    33,  -190,

+   257,   469,   337,    51,    15,   298,   -93,

+   295,    73,  -119,    25,    36,    23,   108,

+   -28,    -3,   -32,   114,    21,   185,   107,

+   482,   305,    15,  -279,  -319,    52,    96,

+   226,    46,   115,    72,  -136,   133,  -125,

+    18,  -207,  -559,  -590,  -503,  -482,   321,

+  -571,  -789,  -951,  -172,  -441,  -538,   113,

+   181,    14,  -310,  -641, -1001,  -202,   159,

+  -136,  -393,  -433,  -513,  -911,  -144,   -22,

+    72,  -265,  -706,  -954,  -159,    53,   332,

+  -338,  -591,  -852,  -383,  -395,    56,    44,

+    43,  -158,  -464,  -897,  -631,  -157,  -294,

+  -161,  -128,  -328,  -573,  -483,  -125,    11,

+  1017,   906,  1051,  1005,   679,   341,  -102,

+   359,   334,  1567,  1314,   723,   105,    10,

+   -65,   726,   529,   301,   220,    43,  -273,

+  -510,   436,   719,   566,   358,   179,   114,

+  -560,   298,   133,  -120,   342,   225,    14,

+  -899,  -101,   217,   617,   400,   146,   -58,

+   -41,   352,    82,  -196,    39,   121,  -167,

+  -212,    59,   447,   284,   423,   250,  -169,

+  -371,  -484,  -596,    30,   -41,   249,    22,

+  -372,  -650,  -794,   477,   445,   216,   -79,

+  -352,   275,    17,  -443,  -929,    92,    19,

+  -699,  -696,   431,   264,   -49,  -310,   182,

+  -978,  -217,  -430,  -400,   101,   261,    72,

+  -929,  -889,  -357,   -13,   463,   378,   236,

+  -826,    56,    30,  -299,  -360,  -128,   -51,

+  -878,  -299,  -111,    75,    65,    36,     3,

+   817,   368,   -25,   354,   697,   591,  -173,

+   309,   212,   222,   751,   484,   140,   -56,

+   593,   379,    70,    -8,   258,   180,   110,

+   165,   -46,   255,   297,   219,   273,   105,

+   160,   -70,  -358,  -181,   379,   330,   319,

+  -238,  -369,  -198,   740,   580,   319,  -143,

+   201,   109,  -202,  -456,   328,   276,  -141,

+   203,   170,   111,    42,   207,   360,   188,

+  -345,  -399,  -513,  -233,   650,   422,    81,

+  -635,  -961, -1220,   463,   539,   204,   209,

+   202,   -25,  -194,  -498,  -787,   193,  -143,

+  -449,  -538,   195,  -106,  -331,    68,    62,

+  -228,  -477,  -840,  -576,   317,   128,   283,

+  -671,  -937,  -807,  -114,   391,   335,   -62,

+   246,     2,  -314,  -679,  -303,   180,   -88,

+  -107,  -272,    90,  -198,   -28,   290,  -112,

+   885,  1149,  1021,   712,   496,   281,   -83,

+   269,   492,   787,   643,   347,    70,   124,

+   336,   636,   499,    92,  -229,  -179,   191,

+    26,   402,   564,   340,   149,   -11,   135,

+  -440,   561,   470,   204,   -72,  -186,   140,

+  -720,    14,   355,   229,    68,  -133,   465,

+   110,   310,   103,    12,   106,    29,   158,

+  -178,   113,   161,   142,   121,   115,    27,

+  -651,  -414,  -645,  -152,  -164,   -13,  -429,

+  -639,  -944,  -681,  -104,   -81,    52,  -189,

+  -663,  -164,  -316,  -683,  -954,  -205,   -83,

+  -609,  -669,  -172,  -517,  -694,   283,   -80,

+  -646,  -152,  -383,  -678,  -246,   -40,  -143,

+  -747,  -796,  -745,  -390,   -98,    43,   275,

+  -599,  -199,  -398,  -433,  -436,  -538,    31,

+ -1107,  -568,  -376,  -265,  -126,   -21,     1,

+   847,   573,   308,   392,   305,   101,    55,

+   273,   293,   201,   267,   346,   201,   123,

+   727,   480,   226,     2,   -65,  -138,   164,

+   273,   208,   173,   292,    12,   253,   174,

+   340,   207,   180,    88,   116,    46,   475,

+  -460,  -166,   -30,    13,   110,   173,   396,

+   137,    88,    43,  -137,   -94,    34,   284,

+    96,   -14,   226,    40,    63,    70,   130,

+  -467,  -735, -1012, -1174,  -307,   305,   -67,

+  -612,  -920, -1146,  -567,    -8,    92,   -25,

+  -182,  -271,  -492,  -754,  -857,   287,   -75,

+  -494,  -787,  -689,  -683,  -709,   137,  -326,

+  -288,  -550,  -903, -1105,   334,   321,   -62,

+  -354,  -653,  -834,  -445,     1,   377,  -152,

+  -162,  -306,  -608,  -937,  -297,   247,  -192,

+  -234,  -477,  -244,  -488,  -266,   342,  -332};

+

+/*---------------------------------------------------*

+ * 2nd stage codebook; 1st split:   isf2_0 to isf2_2

+ *---------------------------------------------------*/

+

+

+static Word16 dico21_isf[SIZE_BK21*3] = {

+

+   329,   409,   249,

+   -33,   505,   160,

+   -29,   -14,   582,

+  -262,   127,   354,

+   145,   237,   175,

+  -152,   245,   122,

+    27,    42,   340,

+   -84,   -93,   311,

+   285,   222,  -156,

+    47,   -43,  -504,

+   234,   121,   385,

+   104,  -317,    45,

+   176,   195,     8,

+   104,   -59,   -94,

+   177,    53,   192,

+   -34,  -127,   152,

+   570,   277,   -34,

+   -67,  -329,  -639,

+  -157,  -272,   462,

+  -177,  -462,   198,

+   322,   179,   115,

+  -386,   171,    19,

+    19,   -12,   195,

+  -120,  -252,   201,

+   304,    36,  -336,

+  -128,  -221,  -380,

+   171,  -185,   296,

+  -242,  -312,    23,

+   198,    39,    16,

+    -3,  -177,  -111,

+   111,   -93,    76,

+   -92,  -223,     4,

+   177,   406,   -44,

+  -168,   380,  -149,

+    -4,   273,   331,

+  -420,   513,   277,

+    21,   247,    47,

+   -58,   131,    -2,

+    -3,   134,   180,

+  -145,    40,   175,

+   189,    74,  -145,

+   -27,   -45,  -325,

+   370,  -114,   -21,

+   -83,  -415,  -173,

+    77,    95,   -51,

+   -40,   -30,   -67,

+    71,    88,    86,

+   -35,   -98,    14,

+    69,   197,  -334,

+  -196,    79,  -231,

+  -348,  -137,   218,

+  -352,   -89,   -85,

+    47,   201,  -130,

+  -165,    37,   -15,

+   -43,     3,    86,

+  -161,  -108,    79,

+    83,    21,  -237,

+   -81,  -149,  -238,

+   150,  -186,  -251,

+  -186,  -249,  -162,

+   -19,    66,  -139,

+   -26,   -50,  -181,

+    24,    11,     0,

+  -130,  -105,   -98};

+

+

+

+/*---------------------------------------------------*

+ * 2nd stage codebook; 2nd split:   isf2_3 to isf2_5

+ *---------------------------------------------------*/

+

+

+static Word16 dico22_isf[SIZE_BK22*3] = {

+

+  -127,   310,    42,

+  -242,   197,     5,

+  -151,    84,   -17,

+  -214,   127,  -149,

+  -247,  -131,   159,

+  -268,  -267,   -95,

+  -217,     1,   -79,

+  -271,   -80,  -185,

+   -45,   436,   159,

+   165,   199,   391,

+   -33,    81,   187,

+   -66,   -42,   355,

+  -298,   -57,   343,

+  -108,  -537,   226,

+  -144,   -23,   193,

+   176,  -402,    87,

+    53,   296,    25,

+   -84,   253,  -104,

+   -58,   105,  -126,

+  -169,   174,  -314,

+   -48,    44,  -294,

+  -164,  -417,  -242,

+  -139,     3,  -194,

+  -155,  -207,  -211,

+   119,   322,   213,

+   333,    50,   380,

+   237,   247,    -2,

+   466,   -16,   201,

+   238,  -255,  -107,

+    67,  -440,  -149,

+   122,   -88,  -139,

+    88,  -247,   -73,

+   -41,   231,   167,

+   -62,   155,    16,

+   -65,    16,    77,

+   -68,    -2,   -63,

+  -151,  -300,   160,

+   -18,  -333,    54,

+   -56,   -94,     5,

+     2,  -190,    14,

+    92,   148,   209,

+   108,     9,   272,

+   108,    35,   110,

+   142,   -85,   145,

+    47,  -157,   279,

+     3,  -320,   246,

+    43,   -72,    68,

+    86,  -217,   135,

+    36,   140,    79,

+    56,   175,   -49,

+    26,    45,     3,

+    73,    55,  -101,

+   109,  -183,  -242,

+    -4,  -283,  -242,

+    48,   -68,   -48,

+    -6,  -153,  -122,

+   161,   196,    96,

+   232,    80,   190,

+   165,    97,    11,

+   258,   -31,    71,

+   267,   -77,   -91,

+   311,  -209,    87,

+   152,   -14,   -22,

+   150,  -149,     9,

+  -324,   557,   187,

+  -384,   307,    46,

+  -251,    27,    77,

+  -365,    77,   -52,

+  -482,   -84,   160,

+  -424,  -515,   -64,

+  -294,  -120,    -4,

+  -476,  -116,  -109,

+   -97,   318,   365,

+   106,   627,   445,

+  -190,   120,   287,

+  -146,    65,   619,

+  -427,   242,   363,

+  -361,  -371,   432,

+  -347,   102,   168,

+  -629,   195,   -14,

+   -65,   476,   -47,

+  -297,   320,  -168,

+   -55,   356,  -264,

+  -391,    82,  -286,

+   -51,   -31,  -556,

+  -178,  -399,  -586,

+  -205,   -49,  -360,

+  -343,  -238,  -337,

+   220,   457,    58,

+   561,   467,   259,

+   340,   270,  -168,

+   450,    77,  -280,

+    60,   167,  -413,

+   133,  -252,  -492,

+   216,   157,  -290,

+   282,     0,  -495,

+  -226,   293,   183,

+  -157,   135,   122,

+  -158,   -59,    39,

+  -133,  -118,   -97,

+  -332,  -309,   113,

+  -160,  -425,    -6,

+  -149,  -211,    24,

+   -80,  -277,   -90,

+   -11,   125,   338,

+   130,   -71,   465,

+     5,   -45,   184,

+   237,   -95,   253,

+  -139,  -197,   297,

+   -19,  -300,   511,

+   -63,  -152,   139,

+   250,  -289,   336,

+   124,   339,  -150,

+    34,   176,  -208,

+   171,   166,  -116,

+    94,    38,  -229,

+    75,   -65,  -339,

+   -78,  -205,  -385,

+     0,   -30,  -163,

+   -56,  -110,  -242,

+   321,   244,   194,

+   505,   238,    -1,

+   317,   116,    65,

+   309,    88,   -74,

+   452,   -51,   -50,

+   334,  -217,  -290,

+   211,    41,  -152,

+   238,   -55,  -260};

+

+

+/*---------------------------------------------------*

+ * 2nd stage codebook; 3rd split:   isf2_6 to isf2_8

+ *---------------------------------------------------*/

+

+

+static Word16 dico23_isf[SIZE_BK23*3] = {

+

+   -10,   151,   359,

+   136,   298,   223,

+   255,  -104,   290,

+   423,     6,   183,

+  -270,  -269,   -98,

+   -52,   -82,    13,

+   -82,  -274,   -97,

+    90,  -246,   -72,

+  -299,   -70,   421,

+   -88,   365,   430,

+   187,  -318,   381,

+   380,    37,   488,

+  -373,  -316,    79,

+  -308,  -101,     5,

+  -135,  -451,     8,

+    72,  -421,  -154,

+   180,   170,  -121,

+    62,   177,   -40,

+   326,    80,  -105,

+   248,   263,    -5,

+  -168,  -181,  -221,

+    -2,   -23,  -158,

+   -14,  -149,  -121,

+   119,   -91,  -147,

+   119,   332,  -153,

+    49,   303,    34,

+   442,   -55,   -69,

+   217,   454,    58,

+  -359,  -187,  -375,

+   -42,    50,  -274,

+    -8,  -267,  -249,

+    85,   -86,  -346,

+   -77,   -40,   345,

+    89,   134,   219,

+   156,   -80,   160,

+   108,    40,   116,

+  -158,  -206,    29,

+     5,   -32,   175,

+   -65,  -158,   146,

+    55,   -78,    73,

+  -114,  -222,   353,

+   -47,    81,   211,

+    49,  -151,   268,

+   105,     4,   302,

+  -263,  -132,   183,

+  -151,   -28,   201,

+  -177,  -307,   166,

+   101,  -221,   130,

+    74,    58,   -98,

+    32,    44,    13,

+   194,    30,  -142,

+   170,    96,     8,

+  -136,  -119,   -91,

+   -65,     8,   -55,

+     3,  -188,    12,

+    45,   -63,   -49,

+   149,   -21,   -19,

+    24,   144,    95,

+   254,   -22,    60,

+   161,   196,    96,

+  -158,   -61,    48,

+   -70,    33,    82,

+   -23,  -321,    58,

+   155,  -147,     5,

+  -364,   328,    77,

+   -21,   453,   173,

+  -108,    82,   630,

+   367,   263,   208,

+  -300,   -62,  -176,

+  -205,   143,  -158,

+  -169,  -410,  -264,

+   257,  -269,  -100,

+  -636,   289,    -2,

+  -292,   627,   173,

+  -382,  -363,   387,

+   248,   524,   447,

+  -521,  -111,  -107,

+  -395,   118,  -274,

+  -343,  -680,  -125,

+  -172,  -447,  -663,

+    75,   148,  -367,

+   -79,   263,   -94,

+   249,   148,  -286,

+   380,   271,  -162,

+  -142,    -4,  -186,

+   -57,   111,  -125,

+   -35,  -108,  -254,

+   100,    29,  -242,

+   -80,   303,  -264,

+   -78,   464,   -57,

+   248,   -22,  -494,

+   661,   662,    44,

+  -193,   -40,  -330,

+  -178,   145,  -337,

+   -90,  -199,  -400,

+   -40,   -23,  -498,

+  -192,   114,   315,

+   -41,   244,   190,

+    88,   -97,   485,

+   241,    80,   212,

+  -246,    40,    87,

+  -156,   147,   134,

+    -2,  -334,   239,

+   308,  -203,   110,

+  -459,   251,   422,

+  -218,   310,   228,

+   -86,  -346,   654,

+   184,   175,   425,

+  -481,   -63,   169,

+  -349,   117,   188,

+  -125,  -560,   310,

+   158,  -416,    94,

+    46,   171,  -192,

+   -63,   157,    14,

+   256,   -35,  -271,

+   322,   123,    53,

+  -214,     4,   -76,

+  -156,    86,   -18,

+   128,  -197,  -232,

+   265,   -90,   -98,

+  -308,   332,  -145,

+  -131,   308,    58,

+   509,    59,  -339,

+   562,   196,   -14,

+  -378,   100,   -47,

+  -234,   202,     1,

+   104,  -270,  -493,

+   319,  -210,  -325};

+

+

+/*---------------------------------------------------*

+ * 2nd stage codebook; 4th split:   isf2_9 to isf2_11

+ *---------------------------------------------------*/

+

+static Word16 dico24_isf[SIZE_BK24*3] = {

+

+   -79,   -89,    -4,

+  -171,    77,  -211,

+   160,  -193,    98,

+   120,  -103,   323,

+    32,   -22,  -129,

+    72,    78,  -268,

+   182,   -76,   -66,

+   309,    99,  -145,

+  -229,  -157,   -84,

+  -383,    98,   -71,

+   -90,  -352,    12,

+  -284,  -178,   178,

+   -65,  -125,  -166,

+   -87,  -175,  -351,

+    42,  -198,   -48,

+   154,  -140,  -243,

+   -77,    18,   108,

+   -39,   355,    91,

+    87,     8,   155,

+    -4,   158,   239,

+   128,    95,   -54,

+     7,   246,  -124,

+   258,    15,    89,

+   206,   216,    98,

+  -201,     9,    18,

+  -312,   233,   204,

+   -39,  -174,   155,

+  -144,    -9,   284,

+   -57,    70,   -69,

+  -157,   187,    18,

+    54,   -30,    23,

+    24,   135,    55};

+

+

+/*---------------------------------------------------*

+ * 2nd stage codebook; 5th split:   isf2_12 to isf2_15

+ *---------------------------------------------------*/

+

+static Word16 dico25_isf[SIZE_BK25*4] = {

+

+   169,   142,  -119,   115,

+   206,   -20,    94,   226,

+  -106,   313,   -21,    16,

+   -62,   161,    71,   255,

+   -89,   101,  -185,   125,

+    72,   -30,  -201,   344,

+  -258,    33,    -8,    81,

+  -104,  -154,    72,   296,

+   144,   -68,  -268,   -25,

+    81,   -78,   -87,   106,

+    22,   155,  -186,  -119,

+   -46,   -28,    27,    91,

+  -114,   -37,  -175,   -33,

+   -94,  -222,  -189,   122,

+  -132,  -119,  -191,  -270,

+  -172,  -173,    18,   -43,

+   279,   135,   -42,  -128,

+   187,   -86,   229,  -138,

+   159,   240,   140,    46,

+    69,    25,   227,    77,

+    21,   115,    13,     8,

+    68,  -248,   126,    81,

+  -150,   137,   207,    -9,

+  -154,  -133,   289,    67,

+   143,   -37,   -86,  -326,

+   180,   -32,    19,   -23,

+    26,   168,   116,  -233,

+   -32,   -26,   118,   -78,

+     3,    -8,   -45,  -115,

+    57,  -215,   -54,   -83,

+  -209,   112,   -22,  -167,

+   -91,  -151,   168,  -262};

+

+

+

+       /* 36 bit */

+/*-------------------------------------------------------------------*

+ *  isf codebooks:  two-stage VQ with split-by-3 in 2nd stage        *

+ *                1st stage is kept the same as the 46 bit quantizer *

+ *                                                                   *

+ *  codebook   vector dimension    number of vectors                 *

+ *  ~~~~~~~~   ~~~~~~~~~~~~~~~~    ~~~~~~~~~~~~~~~~~                 *

+ *     1_1            9                  256                         *

+ *     1_2            7                  256                         *

+ *     2_1            5                  128                         *

+ *     2_2            4                  128                         *

+ *     2_3            7                  64                          *

+ *-------------------------------------------------------------------*/

+

+static Word16 dico21_isf_36b[SIZE_BK21_36b*5] = {

+

+   -52,   -96,   212,   315,   -73,

+    82,  -204,   363,   136,  -197,

+  -126,  -331,   183,   218,   143,

+   -49,   -41,   557,   230,    72,

+     2,   -73,   163,   377,   221,

+   133,   111,   278,   215,  -110,

+  -102,   -20,   284,   113,   273,

+    84,   319,   290,    18,    85,

+   -25,    -5,   125,   132,  -204,

+   -38,    -5,   286,    -9,  -356,

+  -140,  -256,    92,   117,  -189,

+  -144,   191,   313,    51,   -98,

+   167,   -10,    44,   247,    36,

+   381,   197,   238,    74,     6,

+    38,  -408,    29,    -3,   -85,

+    92,   266,   157,   -25,  -200,

+   161,  -121,    70,    84,  -140,

+   -16,   -86,   112,   -94,  -189,

+  -269,  -270,   351,   107,   -24,

+   -68,   -67,   492,  -103,  -155,

+   -53,  -131,    62,   122,    10,

+   135,    84,   283,   -55,  -120,

+   -12,  -219,   331,   -81,   167,

+   220,  -136,   147,  -172,   -42,

+   140,   -95,  -109,   -88,  -194,

+     0,    -2,    -4,   -33,  -381,

+   -66,  -217,   152,  -186,  -402,

+   244,   108,   156,  -140,  -395,

+   113,  -136,  -196,   110,   -24,

+   214,   118,    11,   -64,  -131,

+  -110,  -286,    -6,  -332,    16,

+    94,    97,    79,  -291,  -205,

+    -5,   -39,   -20,   252,   -96,

+    76,   174,   101,   163,    61,

+   -69,  -239,   -55,   399,     6,

+  -115,   319,   164,   275,   196,

+   -15,    36,   -47,   331,   121,

+   226,   209,   271,   325,   184,

+    13,   -80,  -218,   471,   353,

+   288,   378,    16,   -51,   251,

+   174,   116,    52,   149,  -279,

+   235,   276,    39,   120,   -48,

+     0,  -108,  -108,   241,  -339,

+   -93,   534,    45,    33,   -87,

+   194,   149,   -71,   405,   -44,

+   409,   370,    81,  -186,  -154,

+    25,  -102,  -448,   124,  -173,

+    22,   408,  -110,  -310,  -214,

+   -26,    23,   -83,   114,    14,

+  -110,   164,    52,   223,   -82,

+    37,   -25,  -263,   306,   -15,

+  -466,   415,   292,   165,   -18,

+    29,   -19,  -171,   155,   182,

+   179,   144,   -27,   231,   258,

+  -103,  -247,  -396,   238,   113,

+   375,  -154,  -109,    -4,   156,

+    98,    85,  -292,    -5,  -124,

+   116,   139,  -116,   -98,  -294,

+   -14,   -83,  -278,  -117,  -378,

+   106,    33,  -106,  -344,  -484,

+   119,    17,  -412,   138,   166,

+   384,   101,  -204,    88,  -156,

+  -121,  -284,  -300,    -1,  -166,

+   280,    33,  -152,  -313,   -81,

+   -37,    22,   229,   153,    37,

+   -60,   -83,   236,    -8,   -41,

+  -169,  -228,   126,   -20,   363,

+  -235,    17,   364,  -156,   156,

+   -25,   -30,    72,   144,   156,

+   153,   -26,   256,    97,   144,

+   -21,   -37,    48,   -65,   250,

+    63,    77,   273,  -128,   124,

+  -129,   -26,    40,     9,  -115,

+    -6,    82,    38,   -90,  -182,

+  -336,   -13,    28,   158,    91,

+   -30,   241,   137,  -170,   -17,

+   146,    14,   -11,    33,    61,

+   192,   197,    54,   -84,    85,

+    23,  -200,   -78,   -29,   140,

+   122,   237,   106,  -341,   136,

+   -57,  -142,   -85,   -16,   -74,

+   -59,   -90,    -8,  -187,   -20,

+  -211,  -267,   216,  -179,  -110,

+   -50,    -7,   220,  -267,   -70,

+   -57,   -42,   -17,   -15,    71,

+    32,    21,    63,  -137,    33,

+  -137,  -175,   104,   -68,    97,

+   -67,   -43,   133,  -301,   221,

+  -116,  -200,   -81,   -92,  -272,

+   -64,   -41,   -54,  -244,  -220,

+  -287,  -242,   -50,   -87,   -89,

+  -245,   236,   102,  -166,  -295,

+    66,    24,  -162,   -71,    95,

+    66,   136,   -90,  -220,   -36,

+   -98,  -161,  -222,  -188,    29,

+   -18,    18,   -19,  -415,     9,

+    49,    61,   100,    39,   -56,

+  -111,    82,   135,   -31,    52,

+   -90,  -153,   -93,   189,   182,

+  -214,   295,   119,   -74,   284,

+     2,   137,    37,    47,   182,

+    92,   117,   184,   -53,   373,

+   -21,   -14,   -35,   136,   391,

+   146,   129,  -164,   -28,   333,

+    92,    80,   -84,   100,  -134,

+    -8,   217,   -32,     3,   -47,

+  -151,   251,  -215,   142,    92,

+  -224,   310,  -172,  -275,    98,

+   159,   155,  -177,   112,    53,

+   205,    27,     8,  -240,   192,

+   169,   120,  -319,  -201,   106,

+    11,    36,   -86,  -237,   455,

+  -109,  -154,  -163,   174,   -55,

+   -38,    32,  -101,   -78,   -59,

+  -205,  -321,   -97,    69,    79,

+  -310,    44,    18,  -185,    34,

+  -115,   -20,  -148,   -39,   203,

+   -29,   154,   -30,  -158,   166,

+   -45,  -131,  -317,   -24,   363,

+  -165,  -205,  -112,  -222,   265,

+   -32,   -44,  -150,    54,  -193,

+    -6,   -38,  -255,  -169,  -115,

+  -266,    87,  -189,   -36,  -169,

+   -60,   -87,  -266,  -436,  -170,

+   -68,   -81,  -278,    24,    38,

+   -23,   -19,  -155,  -256,   141,

+   -61,  -226,  -565,  -175,    71,

+     9,   -29,  -237,  -515,   263};

+

+static Word16 dico22_isf_36b[SIZE_BK22_36b*4] = {

+

+  -298,    -6,    95,    31,

+  -213,   -87,  -122,   261,

+     4,   -49,   208,    14,

+  -129,  -110,    30,   118,

+  -214,   258,   110,  -235,

+   -41,   -18,  -126,   120,

+   103,    65,   127,   -37,

+   126,   -36,   -24,    25,

+  -138,   -67,  -278,  -186,

+  -164,  -194,  -201,    78,

+  -211,   -87,   -51,  -221,

+  -174,   -79,   -94,   -39,

+    23,    -6,  -157,  -240,

+    22,  -110,  -153,   -68,

+   148,    -5,    -2,  -149,

+    -1,  -135,   -39,  -179,

+    68,   360,  -117,   -15,

+   137,    47,  -278,   146,

+   136,   260,   135,    65,

+    61,   116,   -45,    97,

+   231,   379,    87,  -120,

+   338,   177,  -272,     3,

+   266,   156,    28,   -69,

+   260,    84,   -85,    86,

+  -266,   154,  -256,  -182,

+   -17,   -65,  -304,    -6,

+   -40,   175,  -151,  -180,

+   -27,    27,   -87,   -63,

+   121,   114,  -166,  -469,

+   159,   -66,  -323,  -231,

+   214,   152,  -141,  -212,

+   137,    36,  -184,   -51,

+  -282,  -237,    40,    10,

+   -48,  -235,   -37,   251,

+   -54,  -323,   136,    29,

+   -88,  -174,   213,   198,

+  -390,    99,   -63,  -375,

+   107,  -169,  -164,   424,

+    69,  -111,   141,  -167,

+    74,  -129,    65,   144,

+  -353,  -207,  -205,  -109,

+  -160,  -386,  -355,    98,

+  -176,  -493,   -20,  -143,

+  -252,  -432,    -2,   216,

+   -90,  -174,  -168,  -411,

+    13,  -284,  -229,  -160,

+   -87,  -279,    34,  -251,

+   -75,  -263,   -58,   -42,

+   420,    53,  -211,  -358,

+   384,   -35,  -374,   396,

+    68,  -228,   323,    -2,

+   167,  -307,   192,   194,

+   459,   329,    -5,  -332,

+   375,    79,    -7,   313,

+   282,  -124,   200,   -92,

+   271,  -162,   -70,   180,

+  -157,  -298,  -514,  -309,

+    58,  -163,  -546,    18,

+   124,  -364,   167,  -238,

+    83,  -411,  -117,    96,

+   140,  -112,  -388,  -624,

+   259,  -133,  -317,    41,

+   163,  -130,   -64,  -334,

+   226,  -165,  -124,  -110,

+  -466,   -61,     6,   229,

+  -153,   205,  -145,   242,

+  -159,    48,   195,   148,

+   -58,    28,    31,   279,

+  -303,   185,   279,    -4,

+   -61,   197,    59,    86,

+  -114,   123,   168,   -52,

+    35,    36,   100,   126,

+  -407,   102,   -77,   -40,

+  -338,    -1,  -342,   156,

+  -179,   105,   -34,   -97,

+  -185,    84,   -35,   108,

+  -133,   107,   -91,  -357,

+  -180,    54,  -229,    24,

+   -44,    47,    47,  -182,

+   -66,    13,    45,     4,

+  -339,   251,    64,   226,

+   -42,   101,  -350,   275,

+   -99,   398,   142,   121,

+   111,    12,  -102,   260,

+     0,   505,   260,   -94,

+   161,   285,   -96,   224,

+    -4,   206,   314,    33,

+   167,   139,    88,   204,

+  -235,   316,   -60,   -25,

+    -8,  -150,  -312,   201,

+   -36,   292,    61,  -104,

+   -40,   174,  -162,    42,

+   -21,   402,   -29,  -351,

+    21,   152,  -360,   -93,

+    57,   191,   212,  -196,

+    76,   158,   -21,   -69,

+  -328,  -185,   331,   119,

+   -53,   285,    56,   337,

+  -107,   -24,   405,    29,

+   -18,   137,   272,   277,

+  -255,    22,   173,  -191,

+   295,   322,   325,   302,

+    21,   -27,   332,  -178,

+   119,    13,   271,   129,

+  -455,  -180,   116,  -191,

+  -227,    62,  -148,   524,

+  -176,  -287,   282,  -157,

+  -243,    13,   199,   430,

+   -59,   -49,   115,  -365,

+    72,  -172,  -137,    93,

+  -138,  -126,   141,   -84,

+     5,  -124,    38,   -20,

+  -258,   311,   601,   213,

+    94,   130,   -61,   502,

+    -1,  -157,   485,   313,

+   146,   -74,   158,   345,

+   276,   135,   280,   -57,

+   490,   252,    99,    43,

+   267,   -74,   429,   105,

+   278,   -23,   119,    94,

+  -542,   488,   257,  -115,

+   -84,  -244,  -438,   478,

+  -113,  -545,   387,   101,

+   -95,  -306,   111,   498,

+    95,   166,    22,  -301,

+   420,   -15,   -58,   -78,

+   270,    29,   122,  -282,

+   160,  -240,    50,   -38};

+

+static Word16 dico23_isf_36b[SIZE_BK23_36b*7] = {

+

+    81,   -18,    68,   -27,  -122,  -280,    -4,

+    45,  -177,   209,   -30,  -136,   -74,   131,

+   -44,   101,   -75,   -88,   -48,  -137,   -54,

+  -245,   -28,    63,   -18,  -112,  -103,    58,

+   -79,    -6,   220,   -65,   114,   -35,   -50,

+   109,   -65,   143,  -114,   129,    76,   125,

+   166,    90,   -61,  -242,   186,   -74,   -43,

+   -46,   -92,    49,  -227,    24,  -155,    39,

+    67,    85,    99,   -42,    53,  -184,  -281,

+   142,  -122,     0,    21,  -142,   -15,   -17,

+   223,    92,   -21,   -48,   -82,   -14,  -167,

+    51,   -37,  -243,   -30,   -90,    18,   -56,

+    54,   105,    74,    86,    69,    13,  -101,

+   196,    72,   -89,    43,    65,    19,    39,

+   121,    34,   131,   -82,    25,   213,  -156,

+   101,  -102,  -136,   -21,    57,   214,    22,

+    36,  -124,   205,   204,    58,  -156,   -83,

+    83,  -117,   137,   137,    85,   116,    44,

+   -92,  -148,   -68,    11,  -102,  -197,  -220,

+   -76,  -185,   -58,   132,   -26,  -183,    85,

+    -7,   -31,    -2,    23,   205,  -151,    10,

+   -27,   -37,    -5,   -18,   292,   131,     1,

+   117,  -168,     9,   -93,    80,   -59,  -125,

+  -182,  -244,    98,   -24,   135,   -22,    94,

+   221,    97,   106,    42,    43,  -160,    83,

+    25,   -64,   -21,     6,    14,   -15,   154,

+   126,    15,  -140,   150,   -10,  -207,  -114,

+    79,   -63,  -211,   -70,   -28,  -217,   165,

+    46,    38,   -22,   281,   132,   -62,   109,

+   112,    54,  -112,   -93,   208,    27,   296,

+   115,    10,  -147,    41,   216,    42,  -276,

+    50,  -115,  -254,   167,   117,    -2,    61,

+    17,   144,    34,   -72,  -186,  -150,   272,

+   -29,   -66,   -89,   -95,  -149,   129,   251,

+   122,     0,   -50,  -234,   -91,    36,    26,

+  -105,  -102,   -88,  -121,  -236,    -7,   -11,

+  -204,   109,     5,  -191,   105,   -15,   163,

+   -80,    32,   -24,  -209,    41,   294,    70,

+  -106,   -94,  -204,  -118,   120,   -50,   -37,

+   -82,  -241,    46,  -131,   -29,   150,   -55,

+    33,   155,   120,   -89,    -8,     7,    62,

+   213,    82,    61,    18,  -161,   144,   152,

+    30,   131,    65,   -87,  -255,   -17,  -107,

+    -8,    85,   -64,    51,  -162,   223,   -53,

+  -134,   261,    69,   -56,   218,    72,  -111,

+     2,   155,  -113,   -87,    49,    85,   -28,

+  -163,    42,    -1,  -196,     7,    39,  -245,

+    14,  -137,   -79,    11,  -160,   202,  -293,

+   -94,    33,   208,   100,    56,   -44,   326,

+   -78,   -41,   232,    13,  -142,   227,    80,

+   -16,   -87,   201,    33,  -133,    15,  -183,

+   -58,  -192,   -47,   184,  -128,   133,    99,

+  -205,    11,  -155,    78,    52,    72,   141,

+  -246,    26,    99,   151,    59,   115,   -64,

+   -79,   -47,   -16,   -14,     6,    47,   -43,

+   -72,  -178,   -27,   162,   112,    43,  -174,

+  -175,   238,   186,    71,   -54,  -188,   -76,

+  -225,   233,    39,   -39,  -158,   122,    44,

+   -26,    43,    84,   130,   -93,   -51,    22,

+     3,    92,  -150,   136,  -182,   -57,    97,

+  -131,   179,   -78,    80,    91,  -165,    90,

+    -2,   148,    15,   130,    65,   175,   117,

+  -138,   114,  -137,   132,     3,   -10,  -186,

+   140,    -4,   -37,   254,   -62,    92,  -109};

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/stream.h b/media/libstagefright/codecs/amrwbenc/inc/stream.h
new file mode 100644
index 0000000..edbc13a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/stream.h
@@ -0,0 +1,47 @@
+

+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/***********************************************************************

+File:		stream.h

+

+Contains:       VOME API Buffer Operator Implement Header

+

+************************************************************************/

+#ifndef __STREAM_H__

+#define __STREAM_H__

+

+#include "voMem.h"

+#define Frame_Maxsize  1024 * 2  //Work Buffer 10K 

+#define Frame_MaxByte  640        //AMR_WB Encoder one frame 320 samples = 640 Bytes

+#define MIN(a,b)	 ((a) < (b)? (a) : (b))

+

+typedef struct{

+	unsigned char *set_ptr;

+	unsigned char *frame_ptr;

+	unsigned char *frame_ptr_bk;

+	int  set_len;

+	int  framebuffer_len; 

+	int  frame_storelen;

+	int  used_len;

+}FrameStream;

+

+void voAWB_UpdateFrameBuffer(FrameStream *stream, VO_MEM_OPERATOR *pMemOP);

+void voAWB_InitFrameBuffer(FrameStream *stream);

+void voAWB_FlushFrameBuffer(FrameStream *stream);

+#endif //__STREAM_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/typedef.h b/media/libstagefright/codecs/amrwbenc/inc/typedef.h
new file mode 100644
index 0000000..aa8c098
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/typedef.h
@@ -0,0 +1,65 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*

+*      File             : typedef.c

+*      Purpose          : Basic types.

+*

+************************************************************************/

+

+#ifndef __TYPEDEF_H__

+#define __TYPEDEF_H__

+

+#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version

+                             of typedef.h                           */

+

+#ifdef ORIGINAL_TYPEDEF_H

+/*

+ * this is the original code from the ETSI file typedef.h

+ */

+   

+#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__)

+typedef signed char Word8;

+typedef short Word16;

+typedef long Word32;

+typedef int Flag;

+

+#elif defined(__sun)

+typedef signed char Word8;

+typedef short Word16;

+typedef long Word32;

+typedef int Flag;

+

+#elif defined(__unix__) || defined(__unix)

+typedef signed char Word8;

+typedef short Word16;

+typedef int Word32;

+typedef int Flag;

+

+#endif

+#else /* not original typedef.h */

+

+/*

+ * use (improved) type definition file typdefs.h and add a "Flag" type

+ */

+#include "typedefs.h"

+typedef int Flag;

+

+#endif

+

+#endif  //__TYPEDEF_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/typedefs.h b/media/libstagefright/codecs/amrwbenc/inc/typedefs.h
new file mode 100644
index 0000000..28b657e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/typedefs.h
@@ -0,0 +1,211 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/*

+*

+*      File             : typedefs.h

+*      Description      : Definition of platform independent data

+*                         types and constants

+*

+*

+*      The following platform independent data types and corresponding

+*      preprocessor (#define) constants are defined:

+*

+*        defined type  meaning           corresponding constants

+*        ----------------------------------------------------------

+*        Char          character         (none)

+*        Bool          boolean           true, false

+*        Word8         8-bit signed      minWord8,   maxWord8

+*        UWord8        8-bit unsigned    minUWord8,  maxUWord8

+*        Word16        16-bit signed     minWord16,  maxWord16

+*        UWord16       16-bit unsigned   minUWord16, maxUWord16

+*        Word32        32-bit signed     minWord32,  maxWord32

+*        UWord32       32-bit unsigned   minUWord32, maxUWord32

+*        Float         floating point    minFloat,   maxFloat

+*

+*

+*      The following compile switches are #defined:

+*

+*        PLATFORM      string indicating platform progam is compiled on

+*                      possible values: "OSF", "PC", "SUN"

+*

+*        OSF           only defined if the current platform is an Alpha

+*        PC            only defined if the current platform is a PC

+*        SUN           only defined if the current platform is a Sun

+*        

+*        LSBFIRST      is defined if the byte order on this platform is

+*                      "least significant byte first" -> defined on DEC Alpha

+*                      and PC, undefined on Sun

+*

+********************************************************************************

+*/

+

+#ifndef __TYPEDEFS_H__

+#define __TYPEDEFS_H__

+

+/*

+********************************************************************************

+*                         INCLUDE FILES

+********************************************************************************

+*/

+#include <float.h>

+#include <limits.h>

+

+

+

+/*

+********************************************************************************

+*                         DEFINITION OF CONSTANTS 

+********************************************************************************

+*/

+/*

+ ********* define char type

+ */

+typedef char Char;

+

+/*

+ ********* define 8 bit signed/unsigned types & constants

+ */

+#if SCHAR_MAX == 127

+typedef signed char Word8;

+#define minWord8  SCHAR_MIN

+#define maxWord8  SCHAR_MAX

+

+typedef unsigned char UWord8;

+#define minUWord8 0

+#define maxUWord8 UCHAR_MAX

+#else

+#error cannot find 8-bit type

+#endif

+

+

+/*

+ ********* define 16 bit signed/unsigned types & constants

+ */

+#if INT_MAX == 32767

+typedef int Word16;

+#define minWord16     INT_MIN

+#define maxWord16     INT_MAX

+typedef unsigned int UWord16;

+#define minUWord16    0

+#define maxUWord16    UINT_MAX

+#elif SHRT_MAX == 32767

+typedef short Word16;

+#define minWord16     SHRT_MIN

+#define maxWord16     SHRT_MAX

+typedef unsigned short UWord16;

+#define minUWord16    0

+#define maxUWord16    USHRT_MAX

+#else

+#error cannot find 16-bit type

+#endif

+

+

+/*

+ ********* define 32 bit signed/unsigned types & constants

+ */

+#if INT_MAX == 2147483647

+typedef int Word32;

+#define minWord32     INT_MIN

+#define maxWord32     INT_MAX

+typedef unsigned int UWord32;

+#define minUWord32    0

+#define maxUWord32    UINT_MAX

+#elif LONG_MAX == 2147483647

+typedef long Word32;

+#define minWord32     LONG_MIN

+#define maxWord32     LONG_MAX

+typedef unsigned long UWord32;

+#define minUWord32    0

+#define maxUWord32    ULONG_MAX

+#else

+#error cannot find 32-bit type

+#endif

+

+/*

+ ********* define floating point type & constants

+ */

+/* use "#if 0" below if Float should be double;

+   use "#if 1" below if Float should be float

+ */

+#if 0

+typedef float Float;

+#define maxFloat      FLT_MAX

+#define minFloat      FLT_MIN

+#else

+typedef double Float;

+#define maxFloat      DBL_MAX

+#define minFloat      DBL_MIN

+#endif

+

+/*

+ ********* define complex type

+ */

+typedef struct {

+  Float r;  /* real      part */

+  Float i;  /* imaginary part */

+} CPX;

+

+/*

+ ********* define boolean type

+ */

+typedef int Bool;

+#define false 0

+#define true 1

+

+/* ******Avoid function multiple definition****** */

+#define     Autocorr         voAWB_Autocorr

+#define     Convolve         voAWB_Convolve

+#define     cor_h_x          voAWB_cor_h_x

+#define     dtx_enc_init     voAWB_dtx_enc_init

+#define     dtx_enc_reset    voAWB_dtx_enc_reset

+#define     dtx_enc_exit     voAWB_dtx_enc_exit

+#define     dtx_enc          voAWB_dtx_enc

+#define     dtx_buffer       voAWB_dtx_buffer

+#define     tx_dtx_handler   voAWB_tx_dtx_handler

+#define     G_pitch          voAWB_G_pitch

+#define     Isp_Az           voAWB_Isp_Az

+#define     Lag_window       voAWB_Lag_window

+#define     Log2_norm        voAWB_Log2_norm

+#define     Log2             voAWB_Log2

+#define     Pow2             voAWB_Pow2

+#define     L_Comp           voAWB_L_Comp

+#define     Mpy_32           voAWB_Mpy_32

+#define     Mpy_32_16        voAWB_Mpy_32_16

+#define     Div_32           voAWB_Div_32

+#define     Pit_shrp         voAWB_Pit_shrp

+#define     Qisf_ns          voAWB_Qisf_ns

+#define     Disf_ns          voAWB_Disf_ns

+#define     Residu           voAWB_Residu

+#define     Syn_filt         voAWB_Syn_filt

+#define     Set_zero         voAWB_Set_zero

+#define     Copy             voAWB_Copy

+#define     voice_factor     voAWB_voice_factor

+#define     Syn_filt_32      voAWB_Syn_filt_32

+#define     Isf_isp          voAWB_Isf_isp

+#define     Levinson         voAWB_Levinson

+#define     median5          voAWB_median5           

+#define     Pred_lt4         voAWB_Pred_lt4

+#define     Reorder_isf      voAWB_Reorder_isf

+#define     Dpisf_2s_36b     voAWB_Dpisf_2s_36b

+#define     Dpisf_2s_46b     voAWB_Dpisf_2s_46b

+#define     Dot_product12    voAWB_Dot_product12

+#define     mem_malloc       voAWB_mem_malloc

+#define     mem_free         voAWB_mem_free

+/******************************************************/

+

+#endif  //#define __TYPEDEFS_H__

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h b/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h
new file mode 100644
index 0000000..b733afe
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h
@@ -0,0 +1,78 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*-------------------------------------------------------------------*

+ *                         WB_VAD.H                                  *

+ *-------------------------------------------------------------------*

+ * Functions and static memory for Voice Activity Detection.         *

+ *-------------------------------------------------------------------*/

+

+#ifndef __WB_VAD_H__

+#define __WB_VAD_H__

+

+/******************************************************************************

+ *                         INCLUDE FILES

+ ******************************************************************************/

+#include "typedef.h"

+#include "wb_vad_c.h"

+#include "voMem.h"

+

+/******************************************************************************

+ *                         DEFINITION OF DATA TYPES

+ ******************************************************************************/

+

+typedef struct

+{

+	Word16 bckr_est[COMPLEN];              /* background noise estimate                */

+	Word16 ave_level[COMPLEN];             /* averaged input components for stationary */

+	/* estimation                               */

+	Word16 old_level[COMPLEN];             /* input levels of the previous frame       */

+	Word16 sub_level[COMPLEN];             /* input levels calculated at the end of a frame (lookahead)  */

+	Word16 a_data5[F_5TH_CNT][2];          /* memory for the filter bank               */

+	Word16 a_data3[F_3TH_CNT];             /* memory for the filter bank               */

+

+	Word16 burst_count;                    /* counts length of a speech burst          */

+	Word16 hang_count;                     /* hangover counter                         */

+	Word16 stat_count;                     /* stationary counter                       */

+

+	/* Note that each of the following two variables holds 15 flags. Each flag reserves 1 bit of the

+	 * variable. The newest flag is in the bit 15 (assuming that LSB is bit 1 and MSB is bit 16). */

+	Word16 vadreg;                         /* flags for intermediate VAD decisions     */

+	Word16 tone_flag;                      /* tone detection flags                     */

+

+	Word16 sp_est_cnt;                     /* counter for speech level estimation      */

+	Word16 sp_max;                         /* maximum level                            */

+	Word16 sp_max_cnt;                     /* counts frames that contains speech       */

+	Word16 speech_level;                   /* estimated speech level                   */

+	Word32 prev_pow_sum;                   /* power of previous frame                  */

+

+} VadVars;

+

+/********************************************************************************

+ *

+ * DECLARATION OF PROTOTYPES

+ ********************************************************************************/

+

+Word16 wb_vad_init(VadVars ** st, VO_MEM_OPERATOR *pMemOP);

+Word16 wb_vad_reset(VadVars * st);

+void wb_vad_exit(VadVars ** st, VO_MEM_OPERATOR *pMemOP);

+void wb_vad_tone_detection(VadVars * st, Word16 p_gain);

+Word16 wb_vad(VadVars * st, Word16 in_buf[]);

+

+#endif  //__WB_VAD_H__

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h b/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h
new file mode 100644
index 0000000..39ef506
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h
@@ -0,0 +1,109 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/*-------------------------------------------------------------------*

+ *                         WB_VAD_C.H				     *

+ *-------------------------------------------------------------------*

+ * Constants for Voice Activity Detection.			     *

+ *-------------------------------------------------------------------*/

+

+#ifndef __WB_VAD_C_H__

+#define __WB_VAD_C_H__

+

+#define FRAME_LEN 256                      /* Length (samples) of the input frame          */

+#define COMPLEN 12                         /* Number of sub-bands used by VAD              */

+

+#define UNIRSHFT 7                         /* = log2(MAX_16/UNITY), UNITY = 256      */

+#define SCALE 128                          /* (UNITY*UNITY)/512 */

+

+#define TONE_THR (Word16)(0.65*MAX_16)     /* Threshold for tone detection   */

+

+/* constants for speech level estimation */

+#define SP_EST_COUNT 80

+#define SP_ACTIVITY_COUNT 25

+#define ALPHA_SP_UP (Word16)((1.0 - 0.85)*MAX_16)

+#define ALPHA_SP_DOWN (Word16)((1.0 - 0.85)*MAX_16)

+

+#define NOM_LEVEL 2050                     /* about -26 dBov Q15 */

+#define SPEECH_LEVEL_INIT NOM_LEVEL        /* initial speech level */

+#define MIN_SPEECH_LEVEL1  (Word16)(NOM_LEVEL * 0.063)  /* NOM_LEVEL -24 dB */

+#define MIN_SPEECH_LEVEL2  (Word16)(NOM_LEVEL * 0.2)    /* NOM_LEVEL -14 dB */

+#define MIN_SPEECH_SNR 4096                /* 0 dB, lowest SNR estimation, Q12 */

+

+/* Time constants for background spectrum update */

+#define ALPHA_UP1   (Word16)((1.0 - 0.95)*MAX_16)       /* Normal update, upwards:   */

+#define ALPHA_DOWN1 (Word16)((1.0 - 0.936)*MAX_16)      /* Normal update, downwards  */

+#define ALPHA_UP2   (Word16)((1.0 - 0.985)*MAX_16)      /* Forced update, upwards    */

+#define ALPHA_DOWN2 (Word16)((1.0 - 0.943)*MAX_16)      /* Forced update, downwards  */

+#define ALPHA3      (Word16)((1.0 - 0.95)*MAX_16)       /* Update downwards          */

+#define ALPHA4      (Word16)((1.0 - 0.9)*MAX_16)        /* For stationary estimation */

+#define ALPHA5      (Word16)((1.0 - 0.5)*MAX_16)        /* For stationary estimation */

+

+/* Constants for VAD threshold */

+#define THR_MIN  (Word16)(1.6*SCALE)       /* Minimum threshold               */

+#define THR_HIGH (Word16)(6*SCALE)         /* Highest threshold               */

+#define THR_LOW (Word16)(1.7*SCALE)        /* Lowest threshold               */

+#define NO_P1 31744                        /* ilog2(1), Noise level for highest threshold */

+#define NO_P2 19786                        /* ilog2(0.1*MAX_16), Noise level for lowest threshold */

+#define NO_SLOPE (Word16)(MAX_16*(float)(THR_LOW-THR_HIGH)/(float)(NO_P2-NO_P1))

+

+#define SP_CH_MIN (Word16)(-0.75*SCALE)

+#define SP_CH_MAX (Word16)(0.75*SCALE)

+#define SP_P1 22527                        /* ilog2(NOM_LEVEL/4) */

+#define SP_P2 17832                        /* ilog2(NOM_LEVEL*4) */

+#define SP_SLOPE (Word16)(MAX_16*(float)(SP_CH_MAX-SP_CH_MIN)/(float)(SP_P2-SP_P1))

+

+/* Constants for hangover length */

+#define HANG_HIGH  12                      /* longest hangover               */

+#define HANG_LOW  2                        /* shortest hangover               */

+#define HANG_P1 THR_LOW                    /* threshold for longest hangover */

+#define HANG_P2 (Word16)(4*SCALE)          /* threshold for shortest hangover */

+#define HANG_SLOPE (Word16)(MAX_16*(float)(HANG_LOW-HANG_HIGH)/(float)(HANG_P2-HANG_P1))

+

+/* Constants for burst length */

+#define BURST_HIGH 8                       /* longest burst length         */

+#define BURST_LOW 3                        /* shortest burst length        */

+#define BURST_P1 THR_HIGH                  /* threshold for longest burst */

+#define BURST_P2 THR_LOW                   /* threshold for shortest burst */

+#define BURST_SLOPE (Word16)(MAX_16*(float)(BURST_LOW-BURST_HIGH)/(float)(BURST_P2-BURST_P1))

+

+/* Parameters for background spectrum recovery function */

+#define STAT_COUNT 20                      /* threshold of stationary detection counter         */

+

+#define STAT_THR_LEVEL 184                 /* Threshold level for stationarity detection        */

+#define STAT_THR 1000                      /* Threshold for stationarity detection              */

+

+/* Limits for background noise estimate */

+#define NOISE_MIN 40                       /* minimum */

+#define NOISE_MAX 20000                    /* maximum */

+#define NOISE_INIT 150                     /* initial */

+

+/* Thresholds for signal power (now calculated on 2 frames) */

+#define VAD_POW_LOW (Word32)30000L         /* If input power is lower than this, VAD is set to 0 */

+#define POW_TONE_THR (Word32)686080L       /* If input power is lower,tone detection flag is ignored */

+

+/* Constants for the filter bank */

+#define COEFF3   13363                     /* coefficient for the 3rd order filter     */

+#define COEFF5_1 21955                     /* 1st coefficient the for 5th order filter */

+#define COEFF5_2 6390                      /* 2nd coefficient the for 5th order filter */

+#define F_5TH_CNT 5                        /* number of 5th order filters */

+#define F_3TH_CNT 6                        /* number of 3th order filters */

+

+#endif   //__WB_VAD_C_H__

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt b/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt
@@ -0,0 +1,9 @@
+
+THIS IS NOT A GRANT OF PATENT RIGHTS.
+
+Google makes no representation or warranty that the codecs for which
+source code is made available hereunder are unencumbered by
+third-party patents.  Those intending to use this source code in
+hardware or software products are advised that implementations of
+these codecs, including in open source software or shareware, may
+require patent licenses from the relevant patent holders.
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s
new file mode 100644
index 0000000..0eb5e9f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s
@@ -0,0 +1,104 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@void Deemph_32(

+@     Word16 x_hi[],                        /* (i)     : input signal (bit31..16) */

+@     Word16 x_lo[],                        /* (i)     : input signal (bit15..4)  */

+@     Word16 y[],                           /* (o)     : output signal (x16)      */

+@     Word16 mu,                            /* (i) Q15 : deemphasis factor        */

+@     Word16 L,                             /* (i)     : vector size              */

+@     Word16 * mem                          /* (i/o)   : memory (y[-1])           */

+@     )

+

+@x_hi     RN      R0

+@x_lo     RN      R1

+@y[]      RN      R2

+@*mem     RN      R3

+

+           .section  .text

+           .global   Deemph_32_asm

+	   

+Deemph_32_asm:

+

+           STMFD   	r13!, {r4 - r12, r14} 

+	   MOV          r4, #2                   @i=0

+	   LDRSH        r6, [r0], #2             @load x_hi[0]

+	   LDRSH        r7, [r1], #2             @load x_lo[0]

+	   LDR          r5, =22282               @r5---mu

+	   MOV          r11, #0x8000

+

+           @y[0]

+	   MOV          r10, r6, LSL #16         @L_tmp = x_hi[0]<<16

+	   MOV          r8,  r5, ASR #1          @fac = mu >> 1

+	   LDR          r5,  [r3]

+	   ADD          r12, r10, r7, LSL #4     @L_tmp += x_lo[0] << 4

+	   MOV          r10, r12, LSL #3         @L_tmp <<= 3

+	   MUL          r9, r5, r8

+	   LDRSH        r6, [r0], #2             @load x_hi[1] 

+	   QDADD        r10, r10, r9

+	   LDRSH        r7, [r1], #2             @load x_lo[1]  

+	   MOV          r12, r10, LSL #1         @L_tmp = L_mac(L_tmp, *mem, fac)

+	   QADD         r10, r12, r11

+	   MOV          r14, r10, ASR #16        @y[0] = round(L_tmp)

+

+

+	   MOV          r10, r6, LSL #16

+	   ADD          r12, r10, r7, LSL #4

+           STRH         r14, [r2], #2            @update y[0]

+	   MOV          r10, r12, LSL #3

+	   MUL          r9, r14, r8

+	   QDADD        r10, r10, r9

+	   MOV          r12, r10, LSL #1

+	   QADD         r10, r12, r11

+	   MOV          r14, r10, ASR #16        @y[1] = round(L_tmp)

+

+LOOP:

+           LDRSH        r6, [r0], #2             @load x_hi[]

+	   LDRSH        r7, [r1], #2

+	   STRH         r14, [r2], #2

+	   MOV          r10, r6, LSL #16

+	   ADD          r12, r10, r7, LSL #4

+	   MUL          r9, r14, r8

+	   MOV          r10, r12, LSL #3

+	   QDADD        r10, r10, r9

+           LDRSH        r6, [r0], #2             @load x_hi[]

+	   MOV          r12, r10, LSL #1

+	   QADD         r10, r12, r11

+	   LDRSH        r7, [r1], #2

+	   MOV          r14, r10, ASR #16

+

+	   MOV          r10, r6, LSL #16

+	   ADD          r12, r10, r7, LSL #4

+	   STRH         r14, [r2], #2

+	   MUL          r9, r14, r8

+	   MOV          r10, r12, LSL #3

+	   QDADD        r10, r10, r9

+           ADD          r4, r4, #2

+	   MOV          r12, r10, LSL #1

+	   QADD         r10, r12, r11

+           CMP          r4, #64

+	   MOV          r14, r10, ASR #16

+

+           BLT          LOOP

+           STR          r14, [r3]

+           STRH         r14, [r2]	   

+

+           LDMFD   	r13!, {r4 - r12, r15} 

+

+	   @ENDP

+	   .END

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s
new file mode 100644
index 0000000..0383269
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s
@@ -0,0 +1,80 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@Word32 Dot_product12(                      /* (o) Q31: normalized result (1 < val <= -1) */

+@       Word16 x[],                           /* (i) 12bits: x vector                       */

+@       Word16 y[],                           /* (i) 12bits: y vector                       */

+@       Word16 lg,                            /* (i)    : vector length                     */

+@       Word16 * exp                          /* (o)    : exponent of result (0..+30)       */

+@)

+@****************************************************************

+@  x[]   ---  r0

+@  y[]   ---  r1

+@  lg    ---  r2

+@  *exp  ---  r3

+

+          .section  .text

+ 	  .global   Dot_product12_asm

+

+Dot_product12_asm:

+

+          STMFD   	    r13!, {r4 - r12, r14} 

+          MOV               r4, #0                                 @ L_sum = 0

+          MOV               r5, #0                                 @ i = 0

+

+LOOP:

+          LDR           r6, [r0], #4

+          LDR           r7, [r1], #4

+          LDR           r8, [r0], #4

+          SMLABB        r4, r6, r7, r4

+          LDR           r9, [r1], #4

+	  SMLATT        r4, r6, r7, r4 

+

+	  LDR           r6, [r0], #4

+	  SMLABB        r4, r8, r9, r4

+

+	  LDR           r7, [r1], #4

+	  SMLATT        r4, r8, r9, r4	  

+	  LDR           r8, [r0], #4

+

+	  SMLABB        r4, r6, r7, r4

+	  LDR           r9, [r1], #4

+	  SMLATT        r4, r6, r7, r4

+	  ADD           r5, r5, #8

+	  SMLABB        r4, r8, r9, r4

+	  CMP           r5, r2

+	  SMLATT        r4, r8, r9, r4

+	  BLT           LOOP

+              

+          MOV           r12, r4, LSL #1

+          ADD           r12, r12, #1                         @ L_sum = (L_sum << 1)  + 1

+	  MOV           r4, r12

+

+          CMP           r12, #0

+	  RSBLT         r4, r12, #0

+          CLZ           r10, r4

+          SUB           r10, r10, #1                         @ sft = norm_l(L_sum)

+          MOV           r0, r12, LSL r10                     @ L_sum = L_sum << sft

+          RSB           r11, r10, #30                        @ *exp = 30 - sft

+          STRH          r11, [r3]                     

+

+Dot_product12_end:

+		     

+          LDMFD   	    r13!, {r4 - r12, r15} 

+          @ENDFUNC

+          .END

+ 

+

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
new file mode 100644
index 0000000..e6ebd73
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s
@@ -0,0 +1,185 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+

+@**********************************************************************/

+@void Filt_6k_7k(

+@     Word16 signal[],                      /* input:  signal                  */

+@     Word16 lg,                            /* input:  length of input         */

+@     Word16 mem[]                          /* in/out: memory (size=30)        */

+@)

+@******************************************************************

+@ r0    ---  signal[]

+@ r1    ---  lg

+@ r2    ---  mem[] 

+

+          .section  .text

+          .global  Filt_6k_7k_asm

+          .extern  voAWB_Copy

+          .extern  fir_6k_7k

+

+Filt_6k_7k_asm:

+

+          STMFD   		r13!, {r4 - r12, r14} 

+          SUB    		r13, r13, #240              @ x[L_SUBFR16k + (L_FIR - 1)]

+          MOV     		r8, r0                      @ copy signal[] address

+          MOV     		r4, r1                      @ copy lg address

+          MOV     		r5, r2                      @ copy mem[] address

+

+          MOV     		r1, r13

+          MOV     		r0, r2

+          MOV     		r2, #30                     @ L_FIR - 1

+          BL      		voAWB_Copy                   @ memcpy(x, mem, (L_FIR - 1)<<1)

+

+          LDR     		r10, Lable1                 @ get fir_7k address     

+

+          MOV           	r14, #0  

+          MOV                   r3, r8                      @ change myMemCopy to Copy, due to Copy will change r3 content

+          ADD     	    	r6, r13, #60                @ get x[L_FIR - 1] address

+          MOV           	r7, r3                      @ get signal[i]

+LOOP1:

+          LDRSH         	r8,  [r7], #2

+          LDRSH         	r9,  [r7], #2

+          MOV           	r8, r8, ASR #2

+          MOV           	r9, r9, ASR #2

+          LDRSH         	r11, [r7], #2

+          LDRSH         	r12, [r7], #2

+          MOV           	r11, r11, ASR #2

+          MOV           	r12, r12, ASR #2

+          STRH          	r8, [r6], #2

+          STRH          	r9, [r6], #2

+          STRH          	r11, [r6], #2

+          STRH          	r12, [r6], #2

+          LDRSH         	r8,  [r7], #2

+          LDRSH         	r9,  [r7], #2

+          MOV           	r8, r8, ASR #2

+          MOV           	r9, r9, ASR #2

+          LDRSH         	r11, [r7], #2

+          LDRSH         	r12, [r7], #2

+          MOV           	r11, r11, ASR #2

+          MOV           	r12, r12, ASR #2

+          STRH          	r8, [r6], #2

+          STRH          	r9, [r6], #2

+          STRH          	r11, [r6], #2

+          STRH          	r12, [r6], #2

+          ADD           	r14, r14, #8

+          CMP           	r14, #80

+          BLT           	LOOP1          

+

+

+          STR     		r5, [sp, #-4]               @ PUSH  r5 to stack

+

+          @ not use registers: r4, r10, r12, r14, r5

+          MOV     		r4, r13 

+          MOV     		r5, #0                      @ i = 0              

+LOOP2:

+          LDR           	r0, [r10]

+

+          LDRSH  	        r1, [r4]                   @ load x[i]

+          LDRSH   	        r2, [r4, #60]              @ load x[i + 30]

+          LDRSH                 r6, [r4, #2]               @ load x[i + 1]

+          LDRSH                 r7, [r4, #58]              @ load x[i + 29]

+          ADD                   r1, r1, r2                 @ x[i] + x[i + 30]

+          ADD                   r6, r6, r7                 @ x[i + 1] + x[i + 29]

+          LDRSH                 r8, [r4, #4]               @ load x[i + 2]

+          LDRSH                 r9, [r4, #56]              @ load x[i + 28]

+

+          SMULBB                r14, r1, r0                @ (x[i] + x[i + 30]) * fir_7k[0]

+          ADD                   r8, r8, r9                 @ x[i + 2] + x[i + 28]

+          SMLABT                r14, r6, r0, r14           @ (x[i + 1] + x[i + 29]) * fir_7k[1]

+

+          LDR                   r0, [r10, #4]

+          LDRSH                 r1, [r4, #6]               @ load x[i+3]

+          LDRSH                 r2, [r4, #54]              @ load x[i+27]

+          LDRSH                 r6, [r4, #8]               @ load x[i+4]

+          LDRSH                 r7, [r4, #52]              @ load x[i+26]

+          ADD                   r1, r1, r2                 @ x[i+3] + x[i+27]

+          ADD                   r6, r6, r7                 @ x[i+4] + x[i+26]

+          SMLABB                r14, r8, r0, r14           @ (x[i + 2] + x[i + 28]) * fir_7k[2]

+          LDRSH                 r8, [r4, #10]              @ load x[i+5]

+          LDRSH                 r9, [r4, #50]              @ load x[i+25]

+          SMLABT                r14, r1, r0, r14           @ (x[i+3] + x[i+27]) * fir_7k[3]

+          ADD                   r8, r8, r9                 @ x[i+5] + x[i+25] 

+ 

+          LDR                   r0, [r10, #8]

+          LDRSH                 r1, [r4, #12]              @ x[i+6]

+          LDRSH                 r2, [r4, #48]              @ x[i+24]

+          SMLABB                r14, r6, r0, r14           @ (x[i+4] + x[i+26]) * fir_7k[4]

+          LDRSH                 r6, [r4, #14]              @ x[i+7] 

+          LDRSH                 r7, [r4, #46]              @ x[i+23]

+          SMLABT                r14, r8, r0, r14           @ (x[i+5] + x[i+25]) * fir_7k[5]

+          LDR                   r0, [r10, #12]

+          ADD                   r1, r1, r2                 @ (x[i+6] + x[i+24])

+          ADD                   r6, r6, r7                 @ (x[i+7] + x[i+23])

+          SMLABB                r14, r1, r0, r14           @ (x[i+6] + x[i+24]) * fir_7k[6]

+          LDRSH                 r8, [r4, #16]              @ x[i+8]

+          LDRSH                 r9, [r4, #44]              @ x[i+22] 

+          SMLABT                r14, r6, r0, r14           @ (x[i+7] + x[i+23]) * fir_7k[7]  

+          LDR                   r0, [r10, #16]

+          LDRSH                 r1, [r4, #18]              @ x[i+9]

+          LDRSH                 r2, [r4, #42]              @ x[i+21]

+          LDRSH                 r6, [r4, #20]              @ x[i+10]

+          LDRSH                 r7, [r4, #40]              @ x[i+20]

+          ADD                   r8, r8, r9                 @ (x[i+8] + x[i+22])

+          ADD                   r1, r1, r2                 @ (x[i+9] + x[i+21])

+          ADD                   r6, r6, r7                 @ (x[i+10] + x[i+20])

+          SMLABB                r14, r8, r0, r14           @ (x[i+8] + x[i+22]) * fir_7k[8]

+          LDRSH                 r8, [r4, #22]              @ x[i+11]

+          LDRSH                 r9, [r4, #38]              @ x[i+19]

+          SMLABT                r14, r1, r0, r14           @ (x[i+9] + x[i+21]) * fir_7k[9]

+          LDR                   r0, [r10, #20]

+          LDRSH                 r1, [r4, #24]              @ x[i+12]

+          LDRSH                 r2, [r4, #36]              @ x[i+18]

+          SMLABB                r14, r6, r0, r14           @ (x[i+10] + x[i+20]) * fir_7k[10]

+          LDRSH                 r6, [r4, #26]              @ x[i+13]

+          ADD                   r8, r8, r9                 @ (x[i+11] + x[i+19])  

+          LDRSH                 r7, [r4, #34]              @ x[i+17]

+          SMLABT                r14, r8, r0, r14           @ (x[i+11] + x[i+19]) * fir_7k[11]

+          LDR                   r0, [r10, #24]

+          ADD                   r1, r1, r2                 @ x[i+12] + x[i+18]

+          LDRSH                 r8, [r4, #28]              @ x[i+14]

+          SMLABB                r14, r1, r0, r14           @ (x[i+12] + x[i+18]) * fir_7k[12]

+          ADD                   r6, r6, r7                 @ (x[i+13] + x[i+17])

+          LDRSH                 r9, [r4, #32]              @ x[i+16] 

+          SMLABT                r14, r6, r0, r14           @ (x[i+13] + x[i+17]) * fir_7k[13]

+          LDR                   r0, [r10, #28]         

+          ADD                   r8, r8, r9                 @ (x[i+14] + x[i+16])

+          LDRSH                 r1, [r4, #30]              @ x[i+15]

+          SMLABB                r14, r8, r0, r14           @ (x[i+14] + x[i+16]) * fir_7k[14]

+          SMLABT                r14, r1, r0, r14           @ x[i+15] * fir_7k[15]                              

+

+          ADD     		r5, r5, #1

+          ADD     		r14, r14, #0x4000

+          ADD     		r4, r4, #2                

+          MOV     		r1, r14, ASR #15

+          CMP     		r5, #80

+          STRH    		r1, [r3], #2               @signal[i] = (L_tmp + 0x4000) >> 15

+          BLT     		LOOP2      

+           

+          LDR     		r1, [sp, #-4]               @mem address

+          ADD     		r0, r13, #160               @x + lg

+          MOV     		r2, #30

+          BL      		voAWB_Copy

+                    

+Filt_6k_7k_end:

+          ADD     		r13, r13, #240  

+          LDMFD   		r13!, {r4 - r12, r15} 

+ 

+Lable1:

+          .word   		fir_6k_7k

+          @ENDFUNC

+          .END

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s
new file mode 100644
index 0000000..b440a31
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s
@@ -0,0 +1,231 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** 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.
+@ */
+
+@static void Norm_Corr (Word16 exc[],                    /* (i)     : excitation buffer          */
+@                       Word16 xn[],                     /* (i)     : target vector              */
+@                       Word16 h[],                      /* (i) Q15 : impulse response of synth/wgt filters */
+@                       Word16 L_subfr,                  /* (i)     : sub-frame length */
+@                       Word16 t_min,                    /* (i)     : minimum value of pitch lag.   */
+@                       Word16 t_max,                    /* (i)     : maximum value of pitch lag.   */
+@                       Word16 corr_norm[])              /* (o) Q15 : normalized correlation    */
+@
+
+@ r0 --- exc[]
+@ r1 --- xn[]
+@ r2 --- h[]
+@ r3 --- L_subfr
+@ r4 --- t_min
+@ r5 --- t_max
+@ r6 --- corr_norm[]
+
+
+	.section  .text 
+        .global   Norm_corr_asm 
+        .extern   Convolve_asm
+        .extern   Isqrt_n
+@******************************
+@ constant
+@******************************
+.equ         EXC           ,   0
+.equ         XN            ,   4
+.equ         H             ,   8
+.equ         L_SUBFR       ,   12
+.equ         voSTACK       ,   172
+.equ         T_MIN         ,   212
+.equ         T_MAX         ,   216
+.equ         CORR_NORM     ,   220
+                  
+Norm_corr_asm:
+
+        STMFD      r13!, {r4 - r12, r14}  
+        SUB        r13, r13, #voSTACK
+  
+        ADD        r8, r13, #20                 @get the excf[L_SUBFR]
+        LDR        r4, [r13, #T_MIN]            @get t_min
+        RSB        r11, r4, #0                  @k = -t_min
+        ADD        r5, r0, r11, LSL #1          @get the &exc[k]   
+        
+        @transfer Convolve function
+        STMFD       sp!, {r0 - r3}
+        MOV         r0, r5
+        MOV         r1, r2
+        MOV         r2, r8                       @r2 --- excf[]
+        BL          Convolve_asm
+        LDMFD       sp!, {r0 - r3}
+
+        @ r8 --- excf[]
+
+	MOV         r14, r1                       @copy xn[] address                      
+        MOV         r5, #64
+        MOV         r6, #0                       @L_tmp = 0
+        MOV         r7, #1
+
+LOOP1:
+        LDR         r9,  [r14], #4
+	LDR         r10, [r14], #4
+	LDR         r11, [r14], #4
+	LDR         r12, [r14], #4
+	SMLABB      r6, r9, r9, r6               @L_tmp += (xn[i] * xn[i])
+	SMLATT      r6, r9, r9, r6               @L_tmp += (xn[i+1] * xn[i+1])
+        SMLABB      r6, r10, r10, r6
+	SMLATT      r6, r10, r10, r6
+	SMLABB      r6, r11, r11, r6
+        SMLATT      r6, r11, r11, r6
+        SMLABB      r6, r12, r12, r6
+        SMLATT      r6, r12, r12, r6
+        SUBS        r5, r5, #8
+        BNE         LOOP1
+
+	ADD         r9, r7, r6, LSL #1           @L_tmp = (L_tmp << 1) + 1
+	CLZ         r7, r9
+	SUB         r6, r7, #1                   @exp = norm_l(L_tmp)
+        RSB         r7, r6, #32                  @exp = 32 - exp
+	MOV         r6, r7, ASR #1         
+	RSB         r7, r6, #0                   @scale = -(exp >> 1)
+	
+        @loop for every possible period
+	@for(t = t_min@ t <= t_max@ t++)
+	@r7 --- scale r4 --- t_min r8 --- excf[]
+
+LOOPFOR:	
+        MOV         r5, #0                       @L_tmp  = 0
+	MOV         r6, #0                       @L_tmp1 = 0
+	MOV         r9, #64  
+	MOV         r12, r1                      @copy of xn[]
+	ADD         r14, r13, #20                @copy of excf[]
+	MOV         r8, #0x8000
+        	
+LOOPi:
+	LDR         r11, [r14], #4               @load excf[i], excf[i+1]
+        LDR         r10, [r12], #4               @load xn[i], xn[i+1]
+	SMLABB      r6, r11, r11, r6             @L_tmp1 += excf[i] * excf[i]
+	SMLATT      r6, r11, r11, r6             @L_tmp1 += excf[i+1] * excf[i+1]
+        SMLABB      r5, r10, r11, r5             @L_tmp += xn[i] * excf[i]
+	SMLATT      r5, r10, r11, r5             @L_tmp += xn[i+1] * excf[i+1]
+	LDR         r11, [r14], #4               @load excf[i+2], excf[i+3]
+	LDR         r10, [r12], #4               @load xn[i+2], xn[i+3]
+        SMLABB      r6, r11, r11, r6
+	SMLATT      r6, r11, r11, r6
+	SMLABB      r5, r10, r11, r5
+	SMLATT      r5, r10, r11, r5
+	SUBS        r9, r9, #4
+        BNE         LOOPi
+
+	@r5 --- L_tmp, r6 --- L_tmp1
+	MOV         r10, #1
+	ADD         r5, r10, r5, LSL #1          @L_tmp = (L_tmp << 1) + 1
+	ADD         r6, r10, r6, LSL #1          @L_tmp1 = (L_tmp1 << 1) + 1
+ 
+	CLZ         r10, r5        
+	CMP         r5, #0
+	RSBLT       r11, r5, #0
+	CLZLT       r10, r11
+	SUB         r10, r10, #1                 @exp = norm_l(L_tmp)
+     
+	MOV         r5, r5, LSL r10              @L_tmp = (L_tmp << exp)
+	RSB         r10, r10, #30                @exp_corr = 30 - exp
+	MOV         r11, r5, ASR #16             @corr = extract_h(L_tmp)
+
+	CLZ         r5, r6
+	SUB         r5, r5, #1
+	MOV         r6, r6, LSL r5               @L_tmp = (L_tmp1 << exp)
+	RSB         r5, r5, #30                  @exp_norm = 30 - exp
+
+	@r10 --- exp_corr, r11 --- corr
+	@r6  --- L_tmp, r5 --- exp_norm
+
+	@Isqrt_n(&L_tmp, &exp_norm)
+
+	MOV         r14, r0
+	MOV         r12, r1 
+
+        STMFD       sp!, {r0 - r4, r7 - r12, r14}
+	ADD         r1, sp, #4
+	ADD         r0, sp, #0
+	STR         r6, [sp]
+	STRH        r5, [sp, #4]
+	BL          Isqrt_n
+	LDR         r6, [sp]
+	LDRSH       r5, [sp, #4]
+        LDMFD       sp!, {r0 - r4, r7 - r12, r14}
+	MOV         r0, r14
+	MOV         r1, r12
+
+
+	MOV         r6, r6, ASR #16              @norm = extract_h(L_tmp)
+	MUL         r12, r6, r11
+	ADD         r12, r12, r12                @L_tmp = vo_L_mult(corr, norm)
+  
+	ADD         r6, r10, r5
+	ADD         r6, r6, r7                   @exp_corr + exp_norm + scale
+
+        CMP         r6, #0
+        RSBLT       r6, r6, #0
+	MOVLT       r12, r12, ASR r6
+        MOVGT       r12, r12, LSL r6             @L_tmp = L_shl(L_tmp, exp_corr + exp_norm + scale)
+
+        ADD         r12, r12, r8
+        MOV         r12, r12, ASR #16            @vo_round(L_tmp)
+
+        LDR         r5, [r13, #CORR_NORM]        @ get corr_norm address
+	LDR         r6, [r13, #T_MAX]            @ get t_max
+	ADD         r10, r5, r4, LSL #1          @ get corr_norm[t] address
+	STRH        r12, [r10]                   @ corr_norm[t] = vo_round(L_tmp)
+
+	CMP         r4, r6
+	BEQ         Norm_corr_asm_end
+ 
+	ADD         r4, r4, #1                   @ t_min ++
+        
+	RSB         r5, r4, #0                   @ k
+
+	MOV         r6, #63                      @ i = 63
+	MOV         r8, r0                       @ exc[]
+	MOV         r9, r2                       @ h[]
+	ADD         r10, r13, #20                @ excf[]
+
+	ADD         r8, r8, r5, LSL #1           @ exc[k] address
+	ADD         r9, r9, r6, LSL #1           @ h[i] address
+	ADD         r10, r10, r6, LSL #1         @ excf[i] address
+	LDRSH       r11, [r8]                    @ tmp = exc[k]
+
+LOOPK:
+        LDRSH       r8, [r9], #-2                @ load h[i]
+	LDRSH       r12, [r10, #-2]              @ load excf[i - 1]
+	MUL         r14, r11, r8
+	MOV         r8, r14, ASR #15
+	ADD         r14, r8, r12
+	STRH        r14, [r10], #-2
+	SUBS        r6, r6, #1
+	BGT         LOOPK
+
+	LDRSH       r8, [r9]                     @ load h[0]
+	MUL         r14, r11, r8
+        LDR         r6, [r13, #T_MAX]            @ get t_max
+	MOV         r8, r14, ASR #15
+	STRH        r8, [r10]                    
+
+	CMP         r4, r6
+	BLE         LOOPFOR
+
+Norm_corr_asm_end: 
+        
+        ADD            r13, r13, #voSTACK      
+        LDMFD          r13!, {r4 - r12, r15}
+    
+        .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s
new file mode 100644
index 0000000..6416634
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s
@@ -0,0 +1,226 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@void Syn_filt_32(

+@     Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients */

+@     Word16 m,                             /* (i)     : order of LP filter             */

+@     Word16 exc[],                         /* (i) Qnew: excitation (exc[i] >> Qnew)    */

+@     Word16 Qnew,                          /* (i)     : exc scaling = 0(min) to 8(max) */

+@     Word16 sig_hi[],                      /* (o) /16 : synthesis high                 */

+@     Word16 sig_lo[],                      /* (o) /16 : synthesis low                  */

+@     Word16 lg                             /* (i)     : size of filtering              */

+@)

+@***************************************************************

+@

+@ a[]      --- r0

+@ m        --- r1

+@ exc[]    --- r2

+@ Qnew     --- r3

+@ sig_hi[] --- r4

+@ sig_lo[] --- r5

+@ lg       --- r6

+

+          .section  .text

+          .global  Syn_filt_32_asm

+

+Syn_filt_32_asm:

+

+          STMFD   	r13!, {r4 - r12, r14} 

+          LDR           r4,  [r13, #40]                  @ get sig_hi[] address

+          LDR           r5,  [r13, #44]                  @ get sig_lo[] address

+

+          LDRSH         r6,  [r0]                        @ load Aq[0]

+          ADD           r7,  r3, #4                      @ 4 + Q_new

+          MOV           r3, r6, ASR r7                   @ a0 = Aq[0] >> (4 + Q_new)

+

+          LDR           r14, =0xffff

+          LDRSH         r6, [r0, #2]                     @ load Aq[1]

+          LDRSH         r7, [r0, #4]                     @ load Aq[2]

+          LDRSH         r8, [r0, #6]                     @ load Aq[3]

+          LDRSH         r9, [r0, #8]                     @ load Aq[4]

+          AND           r6, r6, r14

+          AND           r8, r8, r14

+          ORR           r10, r6, r7, LSL #16             @ Aq[2] -- Aq[1]

+          ORR           r11, r8, r9, LSL #16             @ Aq[4] -- Aq[3]

+          STR           r10, [r13, #-4]                  

+          STR           r11, [r13, #-8]

+

+          LDRSH         r6, [r0, #10]                    @ load Aq[5]

+          LDRSH         r7, [r0, #12]                    @ load Aq[6]

+          LDRSH         r8, [r0, #14]                    @ load Aq[7]

+          LDRSH         r9, [r0, #16]                    @ load Aq[8]

+          AND           r6, r6, r14

+          AND           r8, r8, r14

+          ORR           r10, r6, r7, LSL #16             @ Aq[6] -- Aq[5]

+          ORR           r11, r8, r9, LSL #16             @ Aq[8] -- Aq[7]

+          STR           r10, [r13, #-12]

+          STR           r11, [r13, #-16]

+

+          LDRSH         r6, [r0, #18]                    @ load Aq[9]

+          LDRSH         r7, [r0, #20]                    @ load Aq[10]

+          LDRSH         r8, [r0, #22]                    @ load Aq[11]

+          LDRSH         r9, [r0, #24]                    @ load Aq[12]

+          AND           r6, r6, r14 

+          AND           r8, r8, r14

+          ORR           r10, r6, r7, LSL #16             @ Aq[10] -- Aq[9]

+          ORR           r11, r8, r9, LSL #16             @ Aq[12] -- Aq[11]

+          STR           r10, [r13, #-20]

+          STR           r11, [r13, #-24]  

+

+          LDRSH         r6, [r0, #26]                    @ load Aq[13]

+          LDRSH         r7, [r0, #28]                    @ load Aq[14]

+          LDRSH         r8, [r0, #30]                    @ load Aq[15]

+          LDRSH         r9, [r0, #32]                    @ load Aq[16]

+          AND           r6, r6, r14

+          AND           r8, r8, r14

+          ORR           r10, r6, r7, LSL #16             @ Aq[14] -- Aq[13]

+          ORR           r11, r8, r9, LSL #16             @ Aq[16] -- Aq[15]

+          STR           r10, [r13, #-28]

+          STR           r11, [r13, #-32]

+          

+          MOV           r8, #0                           @ i = 0

+              

+LOOP:            

+          LDRSH         r6, [r5, #-2]                    @ load sig_lo[i-1]

+          LDRSH         r7, [r5, #-4]                    @ load sig_lo[i-2]

+

+          LDR           r11, [r13, #-4]                  @ Aq[2] -- Aq[1]        

+          LDRSH         r9, [r5, #-6]                    @ load sig_lo[i-3]

+          LDRSH         r10, [r5, #-8]                   @ load sig_lo[i-4]

+

+          SMULBB        r12, r6, r11                     @ sig_lo[i-1] * Aq[1]

+

+          LDRSH         r6, [r5, #-10]                   @ load sig_lo[i-5]

+          SMLABT        r12, r7, r11, r12                @ sig_lo[i-2] * Aq[2]

+          LDR           r11, [r13, #-8]                  @ Aq[4] -- Aq[3]

+          LDRSH         r7, [r5, #-12]                   @ load sig_lo[i-6]

+          SMLABB        r12, r9, r11, r12                @ sig_lo[i-3] * Aq[3]

+          LDRSH         r9, [r5, #-14]                   @ load sig_lo[i-7]

+          SMLABT        r12, r10, r11, r12               @ sig_lo[i-4] * Aq[4]

+          LDR           r11, [r13, #-12]                 @ Aq[6] -- Aq[5]

+          LDRSH         r10, [r5, #-16]                  @ load sig_lo[i-8]

+          SMLABB        r12, r6, r11, r12                @ sig_lo[i-5] * Aq[5]

+          LDRSH         r6,  [r5, #-18]                  @ load sig_lo[i-9]

+          SMLABT        r12, r7, r11, r12                @ sig_lo[i-6] * Aq[6]

+          LDR           r11, [r13, #-16]                 @ Aq[8] -- Aq[7]

+          LDRSH         r7,  [r5, #-20]                  @ load sig_lo[i-10]

+          SMLABB        r12, r9, r11, r12                @ sig_lo[i-7] * Aq[7]

+          LDRSH         r9, [r5, #-22]                   @ load sig_lo[i-11]

+          SMLABT        r12, r10, r11, r12               @ sig_lo[i-8] * Aq[8]

+          LDR           r11, [r13, #-20]                 @ Aq[10] -- Aq[9]

+          LDRSH         r10,[r5, #-24]                   @ load sig_lo[i-12]

+          SMLABB        r12, r6, r11, r12                @ sig_lo[i-9] * Aq[9]

+          LDRSH         r6, [r5, #-26]                   @ load sig_lo[i-13]

+          SMLABT        r12, r7, r11, r12                @ sig_lo[i-10] * Aq[10]

+          LDR           r11, [r13, #-24]                 @ Aq[12] -- Aq[11]

+          LDRSH         r7, [r5, #-28]                   @ load sig_lo[i-14]

+          SMLABB        r12, r9, r11, r12                @ sig_lo[i-11] * Aq[11]

+          LDRSH         r9, [r5, #-30]                   @ load sig_lo[i-15]

+          SMLABT        r12, r10, r11, r12               @ sig_lo[i-12] * Aq[12]

+

+          LDR           r11, [r13, #-28]                 @ Aq[14] -- Aq[13]

+          LDRSH         r10, [r5, #-32]                  @ load sig_lo[i-16]

+          SMLABB        r12, r6, r11, r12                @ sig_lo[i-13] * Aq[13]

+          SMLABT        r12, r7, r11, r12                @ sig_lo[i-14] * Aq[14]

+ 

+          LDR           r11, [r13, #-32]                 @ Aq[16] -- Aq[15]

+          LDRSH         r6, [r2],#2                      @ load exc[i] 

+          SMLABB        r12, r9, r11, r12                @ sig_lo[i-15] * Aq[15]

+          SMLABT        r12, r10, r11, r12               @ sig_lo[i-16] * Aq[16]

+          MUL           r7, r6, r3                       @ exc[i] * a0 

+          RSB           r14, r12, #0                     @ L_tmp

+          MOV           r14, r14, ASR #11                @ L_tmp >>= 11

+          ADD           r14, r14, r7, LSL #1             @ L_tmp += (exc[i] * a0) << 1

+

+

+          LDRSH         r6, [r4, #-2]                    @ load sig_hi[i-1]

+          LDRSH         r7, [r4, #-4]                    @ load sig_hi[i-2]

+

+          LDR           r11, [r13, #-4]                  @ Aq[2] -- Aq[1]        

+          LDRSH         r9, [r4, #-6]                    @ load sig_hi[i-3]

+          LDRSH         r10, [r4, #-8]                   @ load sig_hi[i-4]

+          SMULBB        r12, r6, r11                     @ sig_hi[i-1] * Aq[1]

+          LDRSH         r6, [r4, #-10]                   @ load sig_hi[i-5]

+	  SMLABT        r12, r7, r11, r12                @ sig_hi[i-2] * Aq[2]

+

+          LDR           r11, [r13, #-8]                  @ Aq[4] -- Aq[3]

+          LDRSH         r7, [r4, #-12]                   @ load sig_hi[i-6]

+

+          SMLABB        r12, r9, r11, r12                @ sig_hi[i-3] * Aq[3]

+	  LDRSH         r9, [r4, #-14]                   @ load sig_hi[i-7]

+

+	  SMLABT        r12, r10, r11, r12               @ sig_hi[i-4] * Aq[4]

+

+          LDR           r11, [r13, #-12]                 @ Aq[6] -- Aq[5]

+          LDRSH         r10, [r4, #-16]                  @ load sig_hi[i-8]

+

+	  SMLABB        r12, r6, r11, r12                @ sig_hi[i-5] * Aq[5]

+

+	  LDRSH         r6,  [r4, #-18]                  @ load sig_hi[i-9]

+	  SMLABT        r12, r7, r11, r12                @ sig_hi[i-6] * Aq[6]

+

+          LDR           r11, [r13, #-16]                 @ Aq[8] -- Aq[7]

+          LDRSH         r7,  [r4, #-20]                  @ load sig_hi[i-10]

+

+	  SMLABB        r12, r9, r11, r12                @ sig_hi[i-7] * Aq[7]

+

+	  LDRSH         r9, [r4, #-22]                   @ load sig_hi[i-11]

+

+	  SMLABT        r12, r10, r11, r12               @ sig_hi[i-8] * Aq[8]

+

+          LDR           r11, [r13, #-20]                 @ Aq[10] -- Aq[9]

+          LDRSH         r10,[r4, #-24]                   @ load sig_hi[i-12]

+

+	  SMLABB        r12, r6, r11, r12                @ sig_hi[i-9] * Aq[9]

+          LDRSH         r6, [r4, #-26]                   @ load sig_hi[i-13]

+          SMLABT        r12, r7, r11, r12                @ sig_hi[i-10] * Aq[10]

+

+          LDR           r11, [r13, #-24]                 @ Aq[12] -- Aq[11]

+          LDRSH         r7, [r4, #-28]                   @ load sig_hi[i-14]

+          SMLABB        r12, r9, r11, r12                @ sig_hi[i-11] * Aq[11]

+          LDRSH         r9, [r4, #-30]                   @ load sig_hi[i-15]

+          SMLABT        r12, r10, r11, r12               @ sig_hi[i-12] * Aq[12]

+

+          LDR           r11, [r13, #-28]                 @ Aq[14] -- Aq[13]

+          LDRSH         r10, [r4, #-32]                  @ load sig_hi[i-16]

+          SMLABB        r12, r6, r11, r12                @ sig_hi[i-13] * Aq[13]

+          SMLABT        r12, r7, r11, r12                @ sig_hi[i-14] * Aq[14]

+ 

+          LDR           r11, [r13, #-32]                 @ Aq[16] -- Aq[15]

+          SMLABB        r12, r9, r11, r12                @ sig_hi[i-15] * Aq[15]

+          SMLABT        r12, r10, r11, r12               @ sig_hi[i-16] * Aq[16]       

+          ADD           r6, r12, r12                     @ r12 << 1

+          SUB           r14, r14, r6                     

+          MOV           r14, r14, LSL #3                 @ L_tmp <<=3

+  

+          MOV           r7, r14, ASR #16                 @ L_tmp >> 16

+

+          MOV           r14, r14, ASR #4                 @ L_tmp >>=4

+          STRH          r7, [r4], #2                         @ sig_hi[i] = L_tmp >> 16

+          SUB           r9, r14, r7, LSL #12             @ sig_lo[i] = L_tmp - (sig_hi[i] << 12)

+

+          ADD           r8, r8, #1

+          STRH          r9, [r5], #2   

+          CMP           r8, #64

+          BLT           LOOP                            

+         

+Syn_filt_32_end:

+		     

+          LDMFD   	    r13!, {r4 - r12, r15} 

+          @ENDFUNC

+          .END

+ 

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s
new file mode 100644
index 0000000..0228bda
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s
@@ -0,0 +1,186 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** 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.
+@ */
+
+
+@*void Convolve (
+@*    Word16 x[],        /* (i)     : input vector                           */
+@*    Word16 h[],        /* (i)     : impulse response                       */
+@*    Word16 y[],        /* (o)     : output vector                          */
+@*    Word16 L           /* (i)     : vector size                            */
+@*)
+@  r0 --- x[]
+@  r1 --- h[]
+@  r2 --- y[]
+@  r3 --- L
+
+	.section  .text
+        .global   Convolve_asm 
+
+Convolve_asm:
+
+        STMFD          r13!, {r4 - r12, r14}  
+        MOV            r3,  #0                           @ n
+	MOV            r11, #0x8000
+        
+LOOP: 
+        ADD            r4, r1, r3, LSL #1                @ tmpH address
+        ADD            r5, r3, #1                        @ i = n + 1
+        MOV            r6, r0                            @ tmpX = x
+        LDRSH          r9,  [r6], #2                     @ *tmpX++
+        LDRSH          r10, [r4], #-2                    @ *tmpH--
+        SUB            r5, r5, #1
+        MUL            r8,  r9, r10 
+
+LOOP1:                    
+        CMP            r5, #0
+        BLE            L1
+	LDRSH          r9,  [r6], #2                     @ *tmpX++
+	LDRSH          r10, [r4], #-2                    @ *tmpH--
+	LDRSH          r12, [r6], #2                     @ *tmpX++
+	LDRSH          r14, [r4], #-2                    @ *tmpH--
+	MLA            r8, r9, r10, r8
+	MLA            r8, r12, r14, r8
+	LDRSH          r9,  [r6], #2                     @ *tmpX++
+	LDRSH          r10, [r4], #-2                    @ *tmpH--
+	LDRSH          r12, [r6], #2                     @ *tmpX++
+	LDRSH          r14, [r4], #-2                    @ *tmpH--
+	MLA            r8, r9, r10, r8
+        SUBS           r5, r5, #4 
+	MLA            r8, r12, r14, r8
+    
+        B              LOOP1  
+
+L1:                  
+
+        ADD            r5, r11, r8, LSL #1
+        MOV            r5, r5, LSR #16                   @extract_h(s)
+        ADD            r3, r3, #1
+        STRH           r5, [r2], #2                      @y[n]
+
+
+        ADD            r4, r1, r3, LSL #1                @tmpH address
+        ADD            r5, r3, #1
+        MOV            r6, r0
+        LDRSH          r9,  [r6], #2                     @ *tmpX++
+        LDRSH          r10, [r4], #-2                     
+        LDRSH          r12, [r6], #2
+        LDRSH          r14, [r4], #-2
+
+        MUL            r8, r9, r10
+        SUB            r5, r5, #2
+        MLA            r8, r12, r14, r8
+        
+LOOP2:
+        CMP            r5, #0
+        BLE            L2
+	LDRSH          r9,  [r6], #2                     @ *tmpX++
+	LDRSH          r10, [r4], #-2                    @ *tmpH--
+	LDRSH          r12, [r6], #2                     @ *tmpX++
+	LDRSH          r14, [r4], #-2                    @ *tmpH--
+	MLA            r8, r9, r10, r8
+	MLA            r8, r12, r14, r8
+	LDRSH          r9,  [r6], #2                     @ *tmpX++
+	LDRSH          r10, [r4], #-2                    @ *tmpH--
+	LDRSH          r12, [r6], #2                     @ *tmpX++
+	LDRSH          r14, [r4], #-2                    @ *tmpH--
+	MLA            r8, r9, r10, r8
+        SUBS           r5, r5, #4 
+	MLA            r8, r12, r14, r8
+        B              LOOP2
+
+L2:
+        ADD            r8, r11, r8, LSL #1
+        MOV            r8, r8, LSR #16                   @extract_h(s)
+        ADD            r3, r3, #1  
+        STRH           r8, [r2], #2                      @y[n]
+
+        ADD            r4, r1, r3, LSL #1
+        ADD            r5, r3, #1
+        MOV            r6, r0
+        LDRSH          r9,  [r6], #2
+        LDRSH          r10, [r4], #-2
+        LDRSH          r12, [r6], #2
+        LDRSH          r14, [r4], #-2
+        MUL            r8, r9, r10
+        LDRSH          r9,  [r6], #2
+        LDRSH          r10, [r4], #-2
+        MLA            r8, r12, r14, r8 
+        SUB            r5, r5, #3
+        MLA            r8, r9, r10, r8
+
+LOOP3:
+        CMP            r5, #0
+        BLE            L3
+	LDRSH          r9,  [r6], #2                     @ *tmpX++
+	LDRSH          r10, [r4], #-2                    @ *tmpH--
+	LDRSH          r12, [r6], #2                     @ *tmpX++
+	LDRSH          r14, [r4], #-2                    @ *tmpH--
+	MLA            r8, r9, r10, r8
+	MLA            r8, r12, r14, r8
+	LDRSH          r9,  [r6], #2                     @ *tmpX++
+	LDRSH          r10, [r4], #-2                    @ *tmpH--
+	LDRSH          r12, [r6], #2                     @ *tmpX++
+	LDRSH          r14, [r4], #-2                    @ *tmpH--
+	MLA            r8, r9, r10, r8
+        SUBS           r5, r5, #4 
+	MLA            r8, r12, r14, r8 
+        B              LOOP3   
+
+L3:
+        ADD            r8, r11, r8, LSL #1
+        MOV            r8, r8, LSR #16                   @extract_h(s)
+        ADD            r3, r3, #1
+        STRH           r8, [r2], #2                      @y[n]
+
+        ADD            r5, r3, #1                        @ i = n + 1
+        ADD            r4, r1, r3, LSL #1                @ tmpH address
+        MOV            r6, r0
+        MOV            r8, #0
+
+LOOP4:                    
+        CMP            r5, #0
+        BLE            L4
+	LDRSH          r9,  [r6], #2                     @ *tmpX++
+	LDRSH          r10, [r4], #-2                    @ *tmpH--
+	LDRSH          r12, [r6], #2                     @ *tmpX++
+	LDRSH          r14, [r4], #-2                    @ *tmpH--
+	MLA            r8, r9, r10, r8
+	MLA            r8, r12, r14, r8
+	LDRSH          r9,  [r6], #2                     @ *tmpX++
+	LDRSH          r10, [r4], #-2                    @ *tmpH--
+	LDRSH          r12, [r6], #2                     @ *tmpX++
+	LDRSH          r14, [r4], #-2                    @ *tmpH--
+	MLA            r8, r9, r10, r8
+        SUBS           r5, r5, #4 
+	MLA            r8, r12, r14, r8        
+        B              LOOP4    
+L4:                  
+        ADD            r5, r11, r8, LSL #1
+        MOV            r5, r5, LSR #16                   @extract_h(s)
+        ADD            r3, r3, #1
+        STRH           r5, [r2], #2                      @y[n]
+        
+        CMP            r3, #64
+        BLT            LOOP
+                
+Convolve_asm_end: 
+ 
+        LDMFD      r13!, {r4 - r12, r15}
+    
+        @ENDFUNC
+        .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s
new file mode 100644
index 0000000..441b984
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s
@@ -0,0 +1,151 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@static void cor_h_vec_012(

+@		Word16 h[],                           /* (i) scaled impulse response                 */

+@		Word16 vec[],                         /* (i) scaled vector (/8) to correlate with h[] */

+@		Word16 track,                         /* (i) track to use                            */

+@		Word16 sign[],                        /* (i) sign vector                             */

+@		Word16 rrixix[][NB_POS],              /* (i) correlation of h[x] with h[x]      */

+@		Word16 cor_1[],                       /* (o) result of correlation (NB_POS elements) */

+@		Word16 cor_2[]                        /* (o) result of correlation (NB_POS elements) */

+@)

+@r0 ---- h[]

+@r1 ---- vec[]

+@r2 ---- track

+@r3 ---- sign[]

+@r4 ---- rrixix[][NB_POS]

+@r5 ---- cor_1[]

+@r6 ---- cor_2[]

+

+

+          .section  .text

+	  .global  cor_h_vec_012_asm

+

+cor_h_vec_012_asm:

+

+         STMFD         r13!, {r4 - r12, r14}

+	 LDR           r4, [r13, #40]                    @load rrixix[][NB_POS]

+	 ADD           r7, r4, r2, LSL #5                @r7 --- p0 = rrixix[track]

+         MOV           r4, #0                            @i=0

+

+	 @r0 --- h[], r1 --- vec[],  r2 --- pos

+	 @r3 --- sign[], r4 --- i, r7 --- p0

+LOOPi:

+         MOV           r5, #0                            @L_sum1 = 0

+         MOV           r6, #0                            @L_sum2 = 0

+         ADD           r9, r1, r2, LSL #1                @p2 = &vec[pos]

+         MOV           r10, r0                           @p1 = h

+         RSB           r11, r2, #62                      @j=62-pos

+

+LOOPj1:

+	 LDRSH         r12, [r10], #2  

+	 LDRSH         r8,  [r9], #2

+	 LDRSH         r14, [r9]

+	 SUBS          r11, r11, #1

+         MLA           r5, r12, r8, r5

+         MLA           r6, r12, r14, r6	 

+	 BGE           LOOPj1

+

+	 LDRSH         r12, [r10], #2                     @*p1++

+	 MOV           r6, r6, LSL #2                     @L_sum2 = (L_sum2 << 2)

+         MLA           r5, r12, r14, r5

+         MOV           r14, #0x8000

+         MOV           r5, r5, LSL #2                     @L_sum1 = (L_sum1 << 2)

+         ADD           r10, r6, r14         

+         ADD           r9, r5, r14

+         MOV           r5, r9, ASR #16

+         MOV           r6, r10, ASR #16

+         ADD           r9, r3, r2, LSL #1                 @address of sign[pos]

+         ADD           r8, r7, #32

+         LDRSH         r10, [r9], #2                 	  @sign[pos]

+	 LDRSH         r11, [r9]                          @sign[pos + 1]

+	 MUL           r12, r5, r10

+	 MUL           r14, r6, r11

+	 MOV           r5, r12, ASR #15

+	 MOV           r6, r14, ASR #15

+	 LDR           r9,  [r13, #44]                   

+	 LDR           r12, [r13, #48]

+         LDRSH         r10, [r7], #2                      @*p0++

+	 LDRSH         r11, [r8]                          @*p3++

+         ADD           r9, r9, r4, LSL #1

+	 ADD           r12, r12, r4, LSL #1

+	 ADD           r5, r5, r10

+	 ADD           r6, r6, r11

+	 STRH          r5, [r9]

+	 STRH          r6, [r12]

+

+         ADD           r2, r2, #4

+ 

+         MOV           r5, #0                            @L_sum1 = 0

+	 MOV           r6, #0                            @L_sum2 = 0

+	 ADD           r9, r1, r2, LSL #1                @p2 = &vec[pos]

+	 MOV           r10, r0                           @p1 = h

+	 RSB           r11, r2, #62                      @j=62-pos

+	 ADD           r4, r4, #1                        @i++

+

+LOOPj2:

+	 LDRSH         r12, [r10], #2  

+	 LDRSH         r8,  [r9], #2

+	 LDRSH         r14, [r9]

+	 SUBS          r11, r11, #1

+         MLA           r5, r12, r8, r5

+         MLA           r6, r12, r14, r6	 

+	 BGE           LOOPj2

+

+	 LDRSH         r12, [r10], #2                     @*p1++

+	 MOV           r6, r6, LSL #2                     @L_sum2 = (L_sum2 << 2)

+         MLA           r5, r12, r14, r5

+         MOV           r14, #0x8000

+         MOV           r5, r5, LSL #2                     @L_sum1 = (L_sum1 << 2)

+         ADD           r10, r6, r14        

+         ADD           r9, r5, r14

+

+         MOV           r5, r9, ASR #16

+         MOV           r6, r10, ASR #16

+         ADD           r9, r3, r2, LSL #1                 @address of sign[pos]

+         ADD           r8, r7, #32

+         LDRSH         r10, [r9], #2                 	  @sign[pos]

+	 LDRSH         r11, [r9]                          @sign[pos + 1]

+	 MUL           r12, r5, r10

+	 MUL           r14, r6, r11

+	 MOV           r5, r12, ASR #15

+	 MOV           r6, r14, ASR #15

+	 LDR           r9,  [r13, #44]                   

+	 LDR           r12, [r13, #48]

+         LDRSH         r10, [r7], #2                      @*p0++

+	 LDRSH         r11, [r8]                          @*p3++

+         ADD           r9, r9, r4, LSL #1

+	 ADD           r12, r12, r4, LSL #1

+	 ADD           r5, r5, r10

+	 ADD           r6, r6, r11

+	 STRH          r5, [r9]

+	 STRH          r6, [r12]

+	 ADD           r4, r4, #1                         @i+1

+	 ADD           r2, r2, #4                         @pos += STEP

+	 CMP           r4, #16

+	 

+	 BLT           LOOPi

+         

+the_end:

+         LDMFD         r13!, {r4 - r12, r15}

+      

+         @ENDFUNC

+         .END	 

+        

+	

+	  

+

+

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
new file mode 100644
index 0000000..d5dd8f0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s
@@ -0,0 +1,460 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@void Pred_lt4(

+@		  Word16 exc[],                         /* in/out: excitation buffer */

+@		  Word16 T0,                            /* input : integer pitch lag */

+@		  Word16 frac,                          /* input : fraction of lag   */

+@		  Word16 L_subfr                        /* input : subframe size     */

+@	      )

+

+@******************************

+@       ARM Register

+@******************************

+@ r0  ---  exc[]

+@ r1  ---  T0

+@ r2  ---  frac

+@ r3  ---  L_subfr

+

+         .section  .text

+	 .global   pred_lt4_asm

+	 .extern   inter4_2

+

+pred_lt4_asm:

+

+         STMFD     r13!, {r4 - r12, r14} 

+         RSB       r4, r1, #0                         @-T0

+         RSB       r2, r2, #0                         @frac = -frac

+         ADD       r5, r0, r4, LSL #1                 @x = exc - T0

+         CMP       r2, #0

+         ADDLT     r2, r2, #4                         @frac += UP_SAMP

+         SUBLT     r5, r5, #2                         @x--

+         SUB       r5, r5, #30                        @x -= 15

+         RSB       r4, r2, #3                         @k = 3 - frac

+         LDR       r6, Table

+	 MOV       r8, r4, LSL #6                    

+         @MOV       r7, #0                             @j = 0

+         ADD       r8, r6, r8                         @ptr2 = &(inter4_2[k][0])

+

+	 MOV       r1, r5

+	 MOV       r5, #0x8000

+	 MOV       r14, #21

+@ used register

+         @r0 --- exc[]  r1 --- x  r7 --- j  r8 --- ptr2  r5 --- 0x8000

+THREE_LOOP:

+

+         @MOV       r1, r5                             @ptr1 = x

+	 MOV       r2, r8                             @ptr = ptr2

+         LDR       r3, [r2], #4                       @h[0], h[1]

+	 LDRSH     r4, [r1], #2                       @x[0]

+	 LDRSH     r6, [r1], #2                       @x[1]

+	 LDRSH     r9, [r1], #2                       @x[2]

+

+	 SMULBB    r10, r4, r3                        @x[0] * h[0]                  

+	 SMULBB    r11, r6, r3                        @x[1] * h[0]

+	 SMULBB    r12, r9, r3                        @x[2] * h[0]

+

+         LDRSH     r4, [r1], #2                       @x[3]

+	 SMLABT    r10, r6, r3, r10                   @x[1] * h[1]

+         SMLABT    r11, r9, r3, r11                   @x[2] * h[1]

+	 SMLABT    r12, r4, r3, r12                   @x[3] * h[1]

+

+	 LDR       r3, [r2], #4                       @h[2], h[3]

+	 LDRSH     r6, [r1], #2                       @x[4]

+	 SMLABB    r10, r9, r3, r10                   @x[2] * h[2]

+         SMLABB    r11, r4, r3, r11                   @x[3] * h[2]

+         SMLABB    r12, r6, r3, r12                   @x[4] * h[2]

+

+         LDRSH     r9, [r1], #2                       @x[5]

+         SMLABT    r10, r4, r3, r10                   @x[3] * h[3]

+         SMLABT    r11, r6, r3, r11                   @x[4] * h[3]

+         SMLABT    r12, r9, r3, r12                   @x[5] * h[3]

+

+         LDR       r3, [r2], #4                       @h[4], h[5]

+         LDRSH     r4, [r1], #2                       @x[6]

+         SMLABB    r10, r6, r3, r10                   @x[4] * h[4]

+         SMLABB    r11, r9, r3, r11                   @x[5] * h[4]

+         SMLABB    r12, r4, r3, r12                   @x[6] * h[4]

+

+	 LDRSH     r6, [r1], #2                       @x[7]

+	 SMLABT    r10, r9, r3, r10                   @x[5] * h[5]

+	 SMLABT    r11, r4, r3, r11                   @x[6] * h[5]

+	 SMLABT    r12, r6, r3, r12                   @x[7] * h[5]

+

+         LDR       r3, [r2], #4                       @h[6], h[7]

+	 LDRSH     r9, [r1], #2                       @x[8]

+	 SMLABB    r10, r4, r3, r10                   @x[6] * h[6]

+	 SMLABB    r11, r6, r3, r11                   @x[7] * h[6]

+	 SMLABB    r12, r9, r3, r12                   @x[8] * h[6]

+

+	 LDRSH     r4, [r1], #2                       @x[9]

+	 SMLABT    r10, r6, r3, r10                   @x[7] * h[7]

+	 SMLABT    r11, r9, r3, r11                   @x[8] * h[7]

+	 SMLABT    r12, r4, r3, r12                   @x[9] * h[7]

+

+	 LDR       r3, [r2], #4                       @h[8], h[9]

+	 LDRSH     r6, [r1], #2                       @x[10]

+	 SMLABB    r10, r9, r3, r10                   @x[8] * h[8]

+	 SMLABB    r11, r4, r3, r11                   @x[9] * h[8]

+	 SMLABB    r12, r6, r3, r12                   @x[10] * h[8]

+

+	 LDRSH     r9, [r1], #2                       @x[11]

+	 SMLABT    r10, r4, r3, r10                   @x[9] * h[9]

+	 SMLABT    r11, r6, r3, r11                   @x[10] * h[9]

+	 SMLABT    r12, r9, r3, r12                   @x[11] * h[9]

+

+         LDR       r3, [r2], #4                       @h[10], h[11]

+	 LDRSH     r4, [r1], #2                       @x[12]

+         SMLABB    r10, r6, r3, r10                   @x[10] * h[10]

+	 SMLABB    r11, r9, r3, r11                   @x[11] * h[10]

+	 SMLABB    r12, r4, r3, r12                   @x[12] * h[10]

+

+	 LDRSH     r6, [r1], #2                       @x[13]

+	 SMLABT    r10, r9, r3, r10                   @x[11] * h[11]

+	 SMLABT    r11, r4, r3, r11                   @x[12] * h[11]

+	 SMLABT    r12, r6, r3, r12                   @x[13] * h[11]

+

+	 LDR       r3, [r2], #4                       @h[12], h[13]

+	 LDRSH     r9, [r1], #2                       @x[14]

+	 SMLABB    r10, r4, r3, r10                   @x[12] * h[12]

+	 SMLABB    r11, r6, r3, r11                   @x[13] * h[12]

+	 SMLABB    r12, r9, r3, r12                   @x[14] * h[12]

+

+	 LDRSH     r4, [r1], #2                       @x[15]

+	 SMLABT    r10, r6, r3, r10                   @x[13] * h[13]

+	 SMLABT    r11, r9, r3, r11                   @x[14] * h[13]

+	 SMLABT    r12, r4, r3, r12                   @x[15] * h[13]

+

+	 LDR       r3, [r2], #4                       @h[14], h[15]

+	 LDRSH     r6, [r1], #2                       @x[16]

+	 SMLABB    r10, r9, r3, r10                   @x[14] * h[14]

+	 SMLABB    r11, r4, r3, r11                   @x[15] * h[14]

+	 SMLABB    r12, r6, r3, r12                   @x[16] * h[14]

+

+	 LDRSH     r9, [r1], #2                       @x[17]

+         SMLABT    r10, r4, r3, r10                   @x[15] * h[15]

+	 SMLABT    r11, r6, r3, r11                   @x[16] * h[15]

+	 SMLABT    r12, r9, r3, r12                   @x[17] * h[15]

+

+	 LDR       r3, [r2], #4                       @h[16], h[17]

+	 LDRSH     r4, [r1], #2                       @x[18]

+	 SMLABB    r10, r6, r3, r10                   @x[16] * h[16]

+	 SMLABB    r11, r9, r3, r11                   @x[17] * h[16]

+	 SMLABB    r12, r4, r3, r12                   @x[18] * h[16]

+

+         LDRSH     r6, [r1], #2                       @x[19]

+	 SMLABT    r10, r9, r3, r10                   @x[17] * h[17]

+	 SMLABT    r11, r4, r3, r11                   @x[18] * h[17]

+	 SMLABT    r12, r6, r3, r12                   @x[19] * h[17]

+

+	 LDR       r3, [r2], #4                       @h[18], h[19]

+         LDRSH     r9, [r1], #2                       @x[20]

+	 SMLABB    r10, r4, r3, r10                   @x[18] * h[18]

+	 SMLABB    r11, r6, r3, r11                   @x[19] * h[18]

+	 SMLABB    r12, r9, r3, r12                   @x[20] * h[18]

+

+	 LDRSH     r4, [r1], #2                       @x[21]

+	 SMLABT    r10, r6, r3, r10                   @x[19] * h[19]

+	 SMLABT    r11, r9, r3, r11                   @x[20] * h[19]

+	 SMLABT    r12, r4, r3, r12                   @x[21] * h[19]

+

+	 LDR       r3, [r2], #4                       @h[20], h[21]

+	 LDRSH     r6, [r1], #2                       @x[22]

+	 SMLABB    r10, r9, r3, r10                   @x[20] * h[20]

+	 SMLABB    r11, r4, r3, r11                   @x[21] * h[20]

+	 SMLABB    r12, r6, r3, r12                   @x[22] * h[20]

+

+	 LDRSH     r9, [r1], #2                       @x[23]

+	 SMLABT    r10, r4, r3, r10                   @x[21] * h[21]

+	 SMLABT    r11, r6, r3, r11                   @x[22] * h[21]

+	 SMLABT    r12, r9, r3, r12                   @x[23] * h[21]

+

+	 LDR       r3, [r2], #4                       @h[22], h[23]

+	 LDRSH     r4, [r1], #2                       @x[24]

+	 SMLABB    r10, r6, r3, r10                   @x[22] * h[22]

+	 SMLABB    r11, r9, r3, r11                   @x[23] * h[22]

+	 SMLABB    r12, r4, r3, r12                   @x[24] * h[22]

+

+         LDRSH     r6, [r1], #2                       @x[25]

+	 SMLABT    r10, r9, r3, r10                   @x[23] * h[23]

+	 SMLABT    r11, r4, r3, r11                   @x[24] * h[23]

+	 SMLABT    r12, r6, r3, r12                   @x[25] * h[23]

+

+	 LDR       r3, [r2], #4                       @h[24], h[25]

+         LDRSH     r9, [r1], #2                       @x[26]

+	 SMLABB    r10, r4, r3, r10                   @x[24] * h[24]

+	 SMLABB    r11, r6, r3, r11                   @x[25] * h[24]

+	 SMLABB    r12, r9, r3, r12                   @x[26] * h[24]

+

+	 LDRSH     r4, [r1], #2                       @x[27]

+	 SMLABT    r10, r6, r3, r10                   @x[25] * h[25]

+	 SMLABT    r11, r9, r3, r11                   @x[26] * h[25]

+	 SMLABT    r12, r4, r3, r12                   @x[27] * h[25]

+

+	 LDR       r3, [r2], #4                       @h[26], h[27]

+	 LDRSH     r6, [r1], #2                       @x[28]

+	 SMLABB    r10, r9, r3, r10                   @x[26] * h[26]

+	 SMLABB    r11, r4, r3, r11                   @x[27] * h[26]

+	 SMLABB    r12, r6, r3, r12                   @x[28] * h[26]

+

+	 LDRSH     r9, [r1], #2                       @x[29]

+	 SMLABT    r10, r4, r3, r10                   @x[27] * h[27]

+	 SMLABT    r11, r6, r3, r11                   @x[28] * h[27]

+	 SMLABT    r12, r9, r3, r12                   @x[29] * h[27]

+

+	 LDR       r3, [r2], #4                       @h[28], h[29]

+	 LDRSH     r4, [r1], #2                       @x[30]

+	 SMLABB    r10, r6, r3, r10                   @x[28] * h[28]

+	 SMLABB    r11, r9, r3, r11                   @x[29] * h[28]

+	 SMLABB    r12, r4, r3, r12                   @x[30] * h[28]

+

+         LDRSH     r6, [r1], #2                       @x[31]

+	 SMLABT    r10, r9, r3, r10                   @x[29] * h[29]

+	 SMLABT    r11, r4, r3, r11                   @x[30] * h[29]

+	 SMLABT    r12, r6, r3, r12                   @x[31] * h[29]

+

+	 LDR       r3, [r2], #4                       @h[30], h[31]

+         LDRSH     r9, [r1], #2                       @x[32]

+	 SMLABB    r10, r4, r3, r10                   @x[30] * h[30]

+	 SMLABB    r11, r6, r3, r11                   @x[31] * h[30]

+	 SMLABB    r12, r9, r3, r12                   @x[32] * h[30]

+

+	 LDRSH     r4, [r1], #-60                     @x[33]

+	 SMLABT    r10, r6, r3, r10                   @x[31] * h[31]

+	 SMLABT    r11, r9, r3, r11                   @x[32] * h[31]

+	 SMLABT    r12, r4, r3, r12                   @x[33] * h[31]

+

+	 @SSAT      r10, #32, r10, LSL #2

+	 @SSAT      r11, #32, r11, LSL #2

+	 @SSAT      r12, #32, r12, LSL #2

+

+	 MOV       r10, r10, LSL #1

+	 MOV       r11, r11, LSL #1

+	 MOV       r12, r12, LSL #1

+

+	 QADD      r10, r10, r10

+	 QADD      r11, r11, r11

+	 QADD      r12, r12, r12

+

+	 QADD      r10, r10, r5

+	 QADD      r11, r11, r5

+	 QADD      r12, r12, r5

+

+	 SUBS      r14, r14, #1

+

+	 MOV       r10, r10, ASR #16

+	 MOV       r11, r11, ASR #16

+	 MOV       r12, r12, ASR #16

+

+	 STRH      r10, [r0], #2

+	 STRH      r11, [r0], #2

+	 STRH      r12, [r0], #2

+	 BNE       THREE_LOOP

+

+	 MOV       r2, r8                             @ptr = ptr2

+

+Last2LOOP:

+

+         LDR       r3, [r2], #4                       @h[0], h[1]

+	 LDRSH     r4, [r1], #2                       @x[0]

+	 LDRSH     r6, [r1], #2                       @x[1]

+	 LDRSH     r9, [r1], #2                       @x[2]

+

+	 SMULBB    r10, r4, r3                        @x[0] * h[0]

+	 SMULBB    r11, r6, r3                        @x[1] * h[0]

+

+	 SMLABT    r10, r6, r3, r10                   @x[1] * h[1]

+	 SMLABT    r11, r9, r3, r11                   @x[2] * h[1]

+

+	 LDR       r3, [r2], #4                       @h[2], h[3]

+	 LDRSH     r4, [r1], #2                       @x[3]

+         LDRSH     r6, [r1], #2                       @x[4]

+

+	 SMLABB    r10, r9, r3, r10                   @x[2] * h[2]

+         SMLABB    r11, r4, r3, r11                   @x[3] * h[2]

+      

+	 SMLABT    r10, r4, r3, r10                   @x[3] * h[3]

+	 SMLABT    r11, r6, r3, r11                   @x[4] * h[3]

+

+	 LDR       r3, [r2], #4                       @h[4], h[5]

+	 LDRSH     r9, [r1], #2                       @x[5]

+	 LDRSH     r4, [r1], #2                       @x[6]

+

+	 SMLABB    r10, r6, r3, r10                   @x[4] * h[4]

+	 SMLABB    r11, r9, r3, r11                   @x[5] * h[4]

+

+	 SMLABT    r10, r9, r3, r10                   @x[5] * h[5]

+	 SMLABT    r11, r4, r3, r11                   @x[6] * h[5]

+

+	 LDR       r3, [r2], #4                       @h[6], h[7]

+	 LDRSH     r6, [r1], #2                       @x[7]

+	 LDRSH     r9, [r1], #2                       @x[8]

+

+	 SMLABB    r10, r4, r3, r10                   @x[6] * h[6]

+	 SMLABB    r11, r6, r3, r11                   @x[7] * h[6]

+

+	 SMLABT    r10, r6, r3, r10                   @x[7] * h[7]

+	 SMLABT    r11, r9, r3, r11                   @x[8] * h[7]

+

+	 LDR       r3, [r2], #4                       @h[8], h[9]

+	 LDRSH     r4, [r1], #2                       @x[9]

+	 LDRSH     r6, [r1], #2                       @x[10]

+

+	 SMLABB    r10, r9, r3, r10                   @x[8] * h[8]

+	 SMLABB    r11, r4, r3, r11                   @x[9] * h[8]

+

+	 SMLABT    r10, r4, r3, r10                   @x[9] * h[9]

+	 SMLABT    r11, r6, r3, r11                   @x[10] * h[9]

+

+	 LDR       r3, [r2], #4                       @h[10], h[11]

+	 LDRSH     r9, [r1], #2                       @x[11]

+	 LDRSH     r4, [r1], #2                       @x[12]

+

+	 SMLABB    r10, r6, r3, r10                   @x[10] * h[10]

+	 SMLABB    r11, r9, r3, r11                   @x[11] * h[10]

+

+	 SMLABT    r10, r9, r3, r10                   @x[11] * h[11]

+	 SMLABT    r11, r4, r3, r11                   @x[12] * h[11]

+

+	 LDR       r3, [r2], #4                       @h[12], h[13]

+	 LDRSH     r6, [r1], #2                       @x[13]

+	 LDRSH     r9, [r1], #2                       @x[14]

+

+	 SMLABB    r10, r4, r3, r10                   @x[12] * h[12]

+	 SMLABB    r11, r6, r3, r11                   @x[13] * h[12]

+

+	 SMLABT    r10, r6, r3, r10                   @x[13] * h[13]

+	 SMLABT    r11, r9, r3, r11                   @x[14] * h[13]

+

+	 LDR       r3, [r2], #4                       @h[14], h[15]

+	 LDRSH     r4, [r1], #2                       @x[15]

+	 LDRSH     r6, [r1], #2                       @x[16]

+

+	 SMLABB    r10, r9, r3, r10                   @x[14] * h[14]

+	 SMLABB    r11, r4, r3, r11                   @x[15] * h[14]

+

+	 SMLABT    r10, r4, r3, r10                   @x[15] * h[15]

+	 SMLABT    r11, r6, r3, r11                   @x[16] * h[15]

+

+	 LDR       r3, [r2], #4                       @h[16], h[17]

+	 LDRSH     r9, [r1], #2                       @x[17]

+	 LDRSH     r4, [r1], #2                       @x[18]

+

+	 SMLABB    r10, r6, r3, r10                   @x[16] * h[16]

+	 SMLABB    r11, r9, r3, r11                   @x[17] * h[16]

+

+	 SMLABT    r10, r9, r3, r10                   @x[17] * h[17]

+	 SMLABT    r11, r4, r3, r11                   @x[18] * h[17]

+

+	 LDR       r3, [r2], #4                       @h[18], h[19]

+	 LDRSH     r6, [r1], #2                       @x[19]

+	 LDRSH     r9, [r1], #2                       @x[20]

+

+	 SMLABB    r10, r4, r3, r10                   @x[18] * h[18]

+	 SMLABB    r11, r6, r3, r11                   @x[19] * h[18]

+

+	 SMLABT    r10, r6, r3, r10                   @x[19] * h[19]

+	 SMLABT    r11, r9, r3, r11                   @x[20] * h[19]

+

+	 LDR       r3, [r2], #4                       @h[20], h[21]

+	 LDRSH     r4, [r1], #2                       @x[21]

+	 LDRSH     r6, [r1], #2                       @x[22]

+

+	 SMLABB    r10, r9, r3, r10                   @x[20] * h[20]

+	 SMLABB    r11, r4, r3, r11                   @x[21] * h[20]

+

+	 SMLABT    r10, r4, r3, r10                   @x[21] * h[21]

+	 SMLABT    r11, r6, r3, r11                   @x[22] * h[21]

+

+	 LDR       r3, [r2], #4                       @h[22], h[23]

+	 LDRSH     r9, [r1], #2                       @x[23]

+	 LDRSH     r4, [r1], #2                       @x[24]

+

+	 SMLABB    r10, r6, r3, r10                   @x[22] * h[22]

+	 SMLABB    r11, r9, r3, r11                   @x[23] * h[22]

+

+	 SMLABT    r10, r9, r3, r10                   @x[23] * h[23]

+	 SMLABT    r11, r4, r3, r11                   @x[24] * h[23]

+

+	 LDR       r3, [r2], #4                       @h[24], h[25]

+	 LDRSH     r6, [r1], #2                       @x[25]

+	 LDRSH     r9, [r1], #2                       @x[26]

+

+	 SMLABB    r10, r4, r3, r10                   @x[24] * h[24]

+	 SMLABB    r11, r6, r3, r11                   @x[25] * h[24]

+

+	 SMLABT    r10, r6, r3, r10                   @x[25] * h[25]

+	 SMLABT    r11, r9, r3, r11                   @x[26] * h[25]

+

+	 LDR       r3, [r2], #4                       @h[26], h[27]

+	 LDRSH     r4, [r1], #2                       @x[27]

+	 LDRSH     r6, [r1], #2                       @x[28]

+

+	 SMLABB    r10, r9, r3, r10                   @x[26] * h[26]

+	 SMLABB    r11, r4, r3, r11                   @x[27] * h[26]

+

+	 SMLABT    r10, r4, r3, r10                   @x[27] * h[27]

+	 SMLABT    r11, r6, r3, r11                   @x[28] * h[27]

+

+	 LDR       r3, [r2], #4                       @h[28], h[29]

+	 LDRSH     r9, [r1], #2                       @x[29]

+	 LDRSH     r4, [r1], #2                       @x[30]

+

+	 SMLABB    r10, r6, r3, r10                   @x[28] * h[28]

+	 SMLABB    r11, r9, r3, r11                   @x[29] * h[28]

+

+	 SMLABT    r10, r9, r3, r10                   @x[29] * h[29]

+	 SMLABT    r11, r4, r3, r11                   @x[30] * h[29]

+

+	 LDR       r3, [r2], #4                       @h[30], h[31]

+	 LDRSH     r6, [r1], #2                       @x[31]

+	 LDRSH     r9, [r1], #2                       @x[32]

+

+	 SMLABB    r10, r4, r3, r10                   @x[30] * h[30]

+	 SMLABB    r11, r6, r3, r11                   @x[31] * h[30]

+

+	 SMLABT    r10, r6, r3, r10                   @x[31] * h[31]

+	 SMLABT    r11, r9, r3, r11                   @x[32] * h[31]

+

+	 @SSAT      r10, #32, r10, LSL #2

+	 @SSAT      r11, #32, r11, LSL #2

+	 MOV       r10, r10, LSL #1

+	 MOV       r11, r11, LSL #1

+

+	 QADD      r10, r10, r10

+	 QADD      r11, r11, r11 

+

+	 QADD      r10, r10, r5

+	 QADD      r11, r11, r5

+

+	 MOV       r10, r10, ASR #16

+	 MOV       r11, r11, ASR #16

+

+	 STRH      r10, [r0], #2

+	 STRH      r11, [r0], #2

+

+

+pred_lt4_end:

+         LDMFD     r13!, {r4 - r12, r15}

+

+Table:

+         .word       inter4_2

+	 @ENDFUNC

+	 .END

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s
new file mode 100644
index 0000000..060d9c7
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s
@@ -0,0 +1,228 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@void Residu(

+@	    Word16 a[],                           /* (i) Q12 : prediction coefficients */

+@	    Word16 x[],                           /* (i)     : speech (values x[-m..-1] are needed */

+@	    Word16 y[],                           /* (o) x2  : residual signal       */

+@	    Word16 lg                             /* (i)     : size of filtering     */

+@	   )

+@a[] --- r0

+@x[] --- r1

+@y[] --- r2

+@lg  --- r3

+

+        .section  .text

+	.global   Residu_opt

+

+Residu_opt:

+

+        STMFD   r13!, {r4 - r12, r14}

+

+        LDRH    r5, [r0], #2

+        LDRH    r6, [r0], #2

+        ORR     r5, r6, r5, LSL #16                  @r5 --- a0, a1	

+

+        LDRH    r6, [r0], #2

+	LDRH    r7, [r0], #2

+	ORR     r6, r7, r6, LSL #16                  @r6 --- a2, a3

+	

+        LDRH    r7, [r0], #2

+	LDRH    r8, [r0], #2

+	ORR     r7, r8, r7, LSL #16                  @r7 --- a4, a5

+

+	LDRH    r8, [r0], #2

+	LDRH    r9, [r0], #2

+	ORR     r8, r9, r8, LSL #16                  @r8 --- a6, a7

+

+	LDRH    r9, [r0], #2

+	LDRH    r10, [r0], #2

+	ORR     r9, r10, r9, LSL #16                 @r9 --- a8, a9

+

+	LDRH    r10, [r0], #2

+	LDRH    r11, [r0], #2

+	ORR     r10, r11, r10, LSL #16               @r10 --- a10, a11

+

+        LDRH    r11, [r0], #2

+	LDRH    r12, [r0], #2

+	ORR     r11, r12, r11, LSL #16               @r11 --- a12, a13

+	

+	LDRH    r12, [r0], #2

+	LDRH    r4, [r0], #2

+	ORR     r12, r4, r12, LSL #16                @r12 --- a14, a15

+	

+

+	STMFD   r13!, {r8 - r12}                     @store r8-r12 

+	LDRH    r4, [r0], #2                         @load a16

+        MOV     r14, r3, ASR #2                      @one loop get 4 outputs

+	ADD     r1, r1, #4

+	MOV     r0, r2

+	ORR     r14, r4, r14, LSL #16                @r14 --- loopnum, a16

+

+residu_loop:

+

+        LDR     r10, [r1], #-4                       @r10  --- x[3], x[2]

+	LDR     r2,  [r1], #-4                       @r2   --- x[1], x[0]

+

+	SMULTB  r3, r5, r2                           @i1(0)  --- r3 = x[0] * a0

+        SMULTT  r4, r5, r2                           @i2(0)  --- r4 = x[1] * a0	

+	SMULTB  r11, r5, r10                         @i3(0)  --- r11 = x[2] * a0

+	SMULTT  r12, r5, r10                         @i4(0)  --- r12 = x[3] * a0

+

+        SMLABB  r4, r5, r2, r4                       @i2(1)  --- r4 += x[0] * a1

+        SMLABT  r11, r5, r2, r11                     @i3(1)  --- r11 += x[1] * a0

+        SMLABB  r12, r5, r10, r12                    @i4(1)  --- r12 += x[2] * a1

+

+	SMLATB  r11, r6, r2, r11                     @i3(2)  --- r11 += x[0] * a2

+	SMLATT  r12, r6, r2, r12                     @i4(2)  --- r12 += x[1] * a2

+	SMLABB  r12, r6, r2, r12                     @i4(3)  --- r12 += x[0] * a3                 

+	

+	LDR     r2, [r1], #-4                        @r2 ---- x[-1], x[-2]

+

+	SMLABT  r3, r5, r2, r3                       @i1(1) --- r3 += x[-1] * a1

+	SMLATT  r4, r6, r2, r4                       @i2(2) --- r4 += x[-1] * a2

+	SMLABT  r11, r6, r2, r11                     @i3(3) --- r11 += x[-1] * a3

+	SMLATT  r12, r7, r2, r12                     @i4(4) --- r12 += x[-1] * a4

+        SMLATB  r3, r6, r2, r3                       @i1(2) --- r3 += x[-2] * a2	

+

+	SMLABB	r4, r6, r2, r4				@ i2	(3)

+	SMLATB  r11,r7, r2, r11				@ i3	(4)

+	SMLABB	r12,r7, r2, r12				@ i4	(5)

+	

+	LDR	r2,[r1],#-4

+	SMLABT	r3, r6, r2, r3				@ i1	(3)

+	SMLATT	r4, r7, r2, r4				@ i2	(4)

+	SMLABT	r11,r7, r2, r11				@ i3	(5)

+	SMLATT	r12,r8, r2, r12				@ i4	(6)

+	SMLATB	r3, r7, r2, r3				@ i1	(4)

+	SMLABB	r4, r7, r2, r4				@ i2	(5)

+	SMLATB	r11,r8, r2, r11				@ i3	(6)

+	SMLABB	r12,r8, r2, r12				@ i4	(7)

+		

+	LDR	r2,[r1],#-4

+	SMLABT	r3, r7, r2, r3				@ i1	(5)

+	SMLATT	r4, r8, r2, r4				@ i2	(6)

+	SMLABT	r11,r8, r2, r11				@ i3	(7)

+	SMLATT	r12,r9, r2, r12				@ i4	(8)

+	SMLATB	r3, r8, r2, r3				@ i1	(6)

+	SMLABB	r4, r8, r2, r4				@ i2	(7)

+	SMLATB	r11,r9, r2, r11				@ i3	(8)

+	SMLABB	r12,r9, r2, r12				@ i4	(9)

+	LDR	r10, [r13, #8]				@ [ a10 | a11]

+	

+	LDR	r2,[r1],#-4

+	SMLABT	r3, r8, r2, r3				@ i1	(7)

+	SMLATT	r4, r9, r2, r4				@ i2	(8)

+	SMLABT	r11,r9, r2, r11				@ i3	(9)

+	SMLATT	r12,r10, r2, r12			@ i4	(10)

+	SMLATB	r3, r9, r2, r3				@ i1	(8)

+	SMLABB	r4, r9, r2, r4				@ i2	(9)

+	SMLATB	r11,r10, r2, r11			@ i3	(10)

+	SMLABB	r12,r10, r2, r12			@ i4	(11)

+	LDR	r8, [r13, #12]				@ [ a12 | a13 ]

+		

+	LDR	r2,[r1],#-4

+	SMLABT	r3, r9, r2, r3				@ i1	(9)

+	SMLATT	r4, r10, r2, r4				@ i2	(10)

+	SMLABT	r11,r10, r2, r11			@ i3	(11)

+	SMLATT	r12,r8, r2, r12				@ i4	(12)

+	SMLATB	r3, r10, r2, r3				@ i1	(10)

+	SMLABB	r4, r10, r2, r4				@ i2	(11)

+	SMLATB	r11,r8, r2, r11				@ i3	(12)

+	SMLABB	r12,r8, r2, r12				@ i4	(13)

+	LDR	r9, [r13, #16]				@ [ a14 | a15 ]

+	

+	LDR	r2,[r1],#-4

+	SMLABT	r3, r10, r2, r3				@ i1	(11)

+	SMLATT	r4, r8, r2, r4				@ i2	(12)

+	SMLABT	r11,r8, r2, r11				@ i3	(13)

+	SMLATT	r12,r9, r2, r12				@ i4	(14)

+	SMLATB	r3, r8, r2, r3				@ i1	(12)

+	SMLABB	r4, r8, r2, r4				@ i2	(13)

+	SMLATB	r11,r9, r2, r11				@ i3	(14)

+	SMLABB	r12,r9, r2, r12				@ i4	(15)

+	

+

+	LDR	r2,[r1],#-4

+	SMLABT	r3, r8, r2, r3				@ i1	(13)

+	SMLATT	r4, r9, r2, r4				@ i2	(14)

+	SMLABT	r11,r9, r2, r11				@ i3	(15)

+	SMLABT	r12,r14, r2, r12			@ i4	(16)

+	SMLATB	r3, r9, r2, r3				@ i1	(14)

+	SMLABB	r4, r9, r2, r4				@ i2	(15)

+	SMLABB	r11,r14, r2, r11			@ i3	(16)

+	LDR		r8, [r13]					@ [ a6 | a7 ]

+			

+        LDR     r2,[r1],#44         		@ Change

+	SMLABT	r3, r9, r2, r3

+	SMLABB	r3, r14, r2, r3

+	SMLABT	r4, r14, r2, r4

+	LDR		r9, [r13, #4]				@ [ a8 | a9 ]

+	

+

+	QADD	r3,r3,r3					

+	QADD	r4,r4,r4					

+	QADD	r11,r11,r11					

+	QADD	r12,r12,r12					

+		

+	QADD	r3,r3,r3					

+	QADD	r4,r4,r4					

+	QADD	r11,r11,r11					

+	QADD	r12,r12,r12					

+	

+	QADD	r3,r3,r3					

+	QADD	r4,r4,r4					

+	QADD	r11,r11,r11					

+	QADD	r12,r12,r12					

+	

+	QADD	r3,r3,r3					

+	QADD	r4,r4,r4					

+	QADD	r11,r11,r11					

+	QADD	r12,r12,r12					

+	

+	MOV	r2,#32768	

+	

+	QDADD	r3,r2,r3					

+	QDADD	r4,r2,r4					

+	QDADD	r11,r2,r11					

+	QDADD	r12,r2,r12					

+		

+	

+	MOV	r3,r3,asr #16

+	MOV	r4,r4,asr #16

+	MOV	r11,r11,asr #16

+	MOV	r12,r12,asr #16

+	

+	STRH	r3,[r0],#2

+	STRH	r4,[r0],#2

+	STRH	r11,[r0],#2

+	STRH	r12,[r0],#2

+	

+	MOV	r2,r14,asr #16

+	SUB	r14, r14, #0x10000

+	SUBS	r2,r2,#1

+	BNE	residu_loop	

+end:

+	LDMFD	r13!, {r8 -r12}	

+	LDMFD	r13!, {r4 -r12,pc}

+

+        @ENDFUNC

+        .END	 

+        

+	

+	  

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s
new file mode 100644
index 0000000..aa9f464
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s
@@ -0,0 +1,75 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@void Scale_sig(

+@	       Word16 x[],                           /* (i/o) : signal to scale               */

+@	       Word16 lg,                            /* (i)   : size of x[]                   */

+@	       Word16 exp                            /* (i)   : exponent: x = round(x << exp) */

+@	       )

+@

+@r0 --- x[]

+@r1 --- lg

+@r2 --- exp

+

+          .section  .text

+	  .global   Scale_sig_opt

+

+Scale_sig_opt:

+

+         STMFD         r13!, {r4 - r12, r14}

+	 SUB           r3, r1, #1                  @i = lg - 1

+         CMP           r2, #0                      @Compare exp and 0

+	 RSB           r7, r2, #0                  @exp = -exp

+	 ADD           r10, r2, #16                @16 + exp

+         ADD           r4, r0, r3, LSL #1          @x[i] address

+	 MOV           r8, #0x7fffffff

+	 MOV           r9, #0x8000

+	 BLE           LOOP2

+	 

+LOOP1:

+

+         LDRSH          r5, [r4]                    @load x[i]

+         MOV           r12, r5, LSL r10

+	 TEQ           r5, r12, ASR r10

+	 EORNE         r12, r8, r5, ASR #31

+	 SUBS          r3, r3, #1

+	 QADD          r11, r12, r9

+	 MOV           r12, r11, ASR #16

+	 STRH          r12, [r4], #-2

+	 BGE           LOOP1

+         BL            The_end

+

+LOOP2:

+

+         LDRSH          r5, [r4]                   @load x[i]

+	 MOV           r6, r5, LSL #16            @L_tmp = x[i] << 16

+	 MOV           r5, r6, ASR r7             @L_tmp >>= exp

+	 QADD          r11, r5, r9

+	 MOV           r12, r11, ASR #16

+	 SUBS          r3, r3, #1

+	 STRH          r12, [r4], #-2

+	 BGE           LOOP2

+

+The_end:

+         LDMFD         r13!, {r4 - r12, r15}

+     

+         @ENDFUNC

+         .END	 

+        

+	

+	  

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s
new file mode 100644
index 0000000..e05e9e0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s
@@ -0,0 +1,238 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@**********************************************************************/

+@void Syn_filt(

+@     Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients           */

+@     Word16 x[],                           /* (i)     : input signal                             */

+@     Word16 y[],                           /* (o)     : output signal                            */

+@     Word16 mem[],                         /* (i/o)   : memory associated with this filtering.   */

+@)

+@***********************************************************************

+@ a[]    ---   r0

+@ x[]    ---   r1

+@ y[]    ---   r2

+@ mem[]  ---   r3

+@ m ---  16  lg --- 80  update --- 1

+

+          .section  .text

+	  .global   Syn_filt_asm

+          .extern   voAWB_Copy

+

+Syn_filt_asm:

+

+          STMFD   	r13!, {r4 - r12, r14} 

+          SUB           r13, r13, #700                   @ y_buf[L_FRAME16k + M16k]

+   

+          MOV           r4, r3                           @ copy mem[] address

+          MOV           r5, r13                          @ copy yy = y_buf address

+

+          @ for(i = 0@ i < m@ i++)

+          @{

+          @    *yy++ = mem[i]@

+          @} 

+

+          LDRH          r6,  [r4], #2          

+          LDRH          r7,  [r4], #2

+          LDRH          r8,  [r4], #2

+          LDRH          r9,  [r4], #2

+          LDRH          r10, [r4], #2

+          LDRH          r11, [r4], #2

+          LDRH          r12, [r4], #2

+          LDRH          r14, [r4], #2

+

+          STRH          r6,  [r5], #2

+          STRH          r7,  [r5], #2

+          STRH          r8,  [r5], #2

+          STRH          r9,  [r5], #2

+          STRH          r10, [r5], #2

+          STRH          r11, [r5], #2

+          STRH          r12, [r5], #2

+          STRH          r14, [r5], #2

+

+          LDRH          r6,  [r4], #2          

+          LDRH          r7,  [r4], #2

+          LDRH          r8,  [r4], #2

+          LDRH          r9,  [r4], #2

+          LDRH          r10, [r4], #2

+          LDRH          r11, [r4], #2

+          LDRH          r12, [r4], #2

+          LDRH          r14, [r4], #2

+

+          STRH          r6,  [r5], #2

+          STRH          r7,  [r5], #2

+          STRH          r8,  [r5], #2

+          STRH          r9,  [r5], #2

+          STRH          r10, [r5], #2

+          STRH          r11, [r5], #2

+          STRH          r12, [r5], #2

+          STRH          r14, [r5], #2

+

+          LDRSH         r5, [r0]                         @ load a[0]

+          MOV           r8, #0                           @ i = 0

+          MOV           r5, r5, ASR #1                   @ a0 = a[0] >> 1

+          @MOV           r4, r13

+          @ load all a[]

+

+          LDR           r14, =0xffff

+          LDRSH         r6, [r0, #2]                     @ load a[1]

+          LDRSH         r7, [r0, #4]                     @ load a[2]

+          LDRSH         r9, [r0, #6]                     @ load a[3]

+          LDRSH         r11,[r0, #8]                     @ load a[4]

+          AND           r6, r6, r14

+          AND           r9, r9, r14          

+          ORR           r10, r6, r7, LSL #16             @ -a[2] -- -a[1]

+          ORR           r12, r9, r11, LSL #16            @ -a[4] -- -a[3]

+          STR           r10, [r13, #-4]

+          STR           r12, [r13, #-8]

+          

+          LDRSH         r6, [r0, #10]                    @ load a[5]

+          LDRSH         r7, [r0, #12]                    @ load a[6]

+          LDRSH         r9, [r0, #14]                    @ load a[7]

+          LDRSH         r11,[r0, #16]                    @ load a[8]

+          AND           r6, r6, r14

+          AND           r9, r9, r14          

+          ORR           r10, r6, r7, LSL #16             @ -a[6] -- -a[5]

+          ORR           r12, r9, r11, LSL #16            @ -a[8] -- -a[7]

+          STR           r10, [r13, #-12]

+          STR           r12, [r13, #-16]          

+           

+          LDRSH         r6, [r0, #18]                    @ load a[9]

+          LDRSH         r7, [r0, #20]                    @ load a[10]

+          LDRSH         r9, [r0, #22]                    @ load a[11]

+          LDRSH         r11,[r0, #24]                    @ load a[12]

+          AND           r6, r6, r14

+          AND           r9, r9, r14          

+          ORR           r10, r6, r7, LSL #16             @ -a[10] -- -a[9]

+          ORR           r12, r9, r11, LSL #16            @ -a[12] -- -a[11]

+          STR           r10, [r13, #-20]

+          STR           r12, [r13, #-24]    

+

+          LDRSH         r6, [r0, #26]                    @ load a[13]

+          LDRSH         r7, [r0, #28]                    @ load a[14]

+          LDRSH         r9, [r0, #30]                    @ load a[15]

+          LDRSH         r11,[r0, #32]                    @ load a[16]

+          AND           r6, r6, r14

+          AND           r9, r9, r14          

+          ORR           r10, r6, r7, LSL #16             @ -a[14] -- -a[13]

+          ORR           r12, r9, r11, LSL #16            @ -a[16] -- -a[15]

+          STR           r10, [r13, #-28]

+          STR           r12, [r13, #-32]                

+                     

+          ADD           r4, r13, #32

+LOOP:

+          LDRSH         r6,  [r1], #2                    @ load x[i]

+          ADD           r10, r4, r8, LSL #1              @ temp_p = yy + i

+

+          MUL           r0, r5, r6                      @ L_tmp = x[i] * a0

+          @ for(j = 1@ j <= m, j+=8)

+          LDR           r7,  [r13, #-4]                  @ -a[2]  -a[1]

+          LDRSH         r9,  [r10, #-2]                  @ *(temp_p - 1)

+          LDRSH         r12, [r10, #-4]                  @ *(temp_p - 2)

+

+

+          SMULBB        r14, r9, r7                      @ -a[1] * (*(temp_p -1))

+

+          LDRSH         r6,  [r10, #-6]                  @ *(temp_p - 3)

+

+          SMLABT        r14, r12, r7, r14                @ -a[2] * (*(temp_p - 2))

+

+          LDR           r7,  [r13, #-8]                  @ -a[4] -a[3]

+          LDRSH         r11, [r10, #-8]                  @ *(temp_p - 4)

+

+          SMLABB        r14, r6, r7, r14                 @ -a[3] * (*(temp_p -3))

+

+          LDRSH         r9,  [r10, #-10]                 @ *(temp_p - 5)

+   

+          SMLABT        r14, r11, r7, r14                @ -a[4] * (*(temp_p -4))        

+

+          LDR           r7,  [r13, #-12]                 @ -a[6]  -a[5]

+          LDRSH         r12, [r10, #-12]                 @ *(temp_p - 6)

+

+          SMLABB        r14, r9, r7, r14                 @ -a[5] * (*(temp_p -5))

+

+          LDRSH         r6,  [r10, #-14]                 @ *(temp_p - 7)

+

+          SMLABT        r14, r12, r7, r14                @ -a[6] * (*(temp_p - 6))

+

+          LDR           r7,  [r13, #-16]                 @ -a[8] -a[7]

+          LDRSH         r11, [r10, #-16]                 @ *(temp_p - 8)

+         

+          SMLABB        r14, r6, r7, r14                 @ -a[7] * (*(temp_p -7))

+

+          LDRSH         r9,  [r10, #-18]                 @ *(temp_p - 9)

+

+          SMLABT        r14, r11, r7, r14                @ -a[8] * (*(temp_p -8))          

+ 

+          LDR           r7,  [r13, #-20]                 @ -a[10]  -a[9]

+          LDRSH         r12, [r10, #-20]                 @ *(temp_p - 10)

+

+          SMLABB        r14, r9, r7, r14                 @ -a[9] * (*(temp_p -9))

+

+          LDRSH         r6,  [r10, #-22]                 @ *(temp_p - 11)

+

+          SMLABT        r14, r12, r7, r14                @ -a[10] * (*(temp_p - 10))

+

+          LDR           r7,  [r13, #-24]                 @ -a[12] -a[11]

+          LDRSH         r11, [r10, #-24]                 @ *(temp_p - 12)

+

+          SMLABB        r14, r6, r7, r14                 @ -a[11] * (*(temp_p -11))

+

+          LDRSH         r9,  [r10, #-26]                 @ *(temp_p - 13)

+

+          SMLABT        r14, r11, r7, r14                @ -a[12] * (*(temp_p -12))           

+

+          LDR           r7,  [r13, #-28]                 @ -a[14] -a[13]

+          LDRSH         r12, [r10, #-28]                 @ *(temp_p - 14)

+ 

+          SMLABB        r14, r9, r7, r14                 @ -a[13] * (*(temp_p -13))

+

+          LDRSH         r6,  [r10, #-30]                 @ *(temp_p - 15)

+

+          SMLABT        r14, r12, r7, r14                @ -a[14] * (*(temp_p - 14))

+

+          LDR           r7,  [r13, #-32]                 @ -a[16] -a[15]

+          LDRSH         r11, [r10, #-32]                 @ *(temp_p - 16)

+

+          SMLABB        r14, r6, r7, r14                 @ -a[15] * (*(temp_p -15))

+

+          SMLABT        r14, r11, r7, r14                @ -a[16] * (*(temp_p -16))

+

+          RSB           r14, r14, r0

+                                  

+          MOV           r7, r14, LSL #4                  @ L_tmp <<=4

+          ADD           r8, r8, #1

+          ADD           r14, r7, #0x8000                 

+          MOV           r7, r14, ASR #16                 @ (L_tmp + 0x8000) >> 16

+          CMP           r8, #80

+          STRH          r7, [r10]                        @ yy[i]

+          STRH          r7, [r2], #2                     @ y[i]

+          BLT           LOOP

+ 

+          @ update mem[]

+          ADD           r5, r13, #160                    @ yy[64] address

+          MOV           r1, r3

+          MOV           r0, r5

+          MOV           r2, #16

+          BL            voAWB_Copy          

+

+Syn_filt_asm_end:

+ 

+          ADD           r13, r13, #700		     

+          LDMFD   	r13!, {r4 - r12, r15} 

+          @ENDFUNC

+          .END

+ 

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s
new file mode 100644
index 0000000..acb60c3
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s
@@ -0,0 +1,102 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@void Deemph_32(

+@     Word16 x_hi[],                        /* (i)     : input signal (bit31..16) */

+@     Word16 x_lo[],                        /* (i)     : input signal (bit15..4)  */

+@     Word16 y[],                           /* (o)     : output signal (x16)      */

+@     Word16 mu,                            /* (i) Q15 : deemphasis factor        */

+@     Word16 L,                             /* (i)     : vector size              */

+@     Word16 * mem                          /* (i/o)   : memory (y[-1])           */

+@     )

+

+@x_hi     RN      R0

+@x_lo     RN      R1

+@y[]      RN      R2

+@*mem     RN      R3

+

+           .section  .text

+           .global   Deemph_32_asm

+	   

+Deemph_32_asm:

+

+           STMFD   	r13!, {r4 - r12, r14} 

+	   MOV          r4, #2                   @i=0

+	   LDRSH        r6, [r0], #2             @load x_hi[0]

+	   LDRSH        r7, [r1], #2             @load x_lo[0]

+	   LDR          r5, =22282               @r5---mu

+	   MOV          r11, #0x8000

+

+           @y[0]

+	   MOV          r10, r6, LSL #16         @L_tmp = x_hi[0]<<16

+	   MOV          r8,  r5, ASR #1          @fac = mu >> 1

+	   LDR          r5,  [r3]

+	   ADD          r12, r10, r7, LSL #4     @L_tmp += x_lo[0] << 4

+	   MOV          r10, r12, LSL #3         @L_tmp <<= 3

+	   MUL          r9, r5, r8

+	   LDRSH        r6, [r0], #2             @load x_hi[1] 

+	   QDADD        r10, r10, r9

+	   LDRSH        r7, [r1], #2             @load x_lo[1]  

+	   MOV          r12, r10, LSL #1         @L_tmp = L_mac(L_tmp, *mem, fac)

+	   QADD         r10, r12, r11

+	   MOV          r14, r10, ASR #16        @y[0] = round(L_tmp)

+

+

+	   MOV          r10, r6, LSL #16

+	   ADD          r12, r10, r7, LSL #4

+           STRH         r14, [r2], #2            @update y[0]

+	   MOV          r10, r12, LSL #3

+	   MUL          r9, r14, r8

+	   QDADD        r10, r10, r9

+	   MOV          r12, r10, LSL #1

+	   QADD         r10, r12, r11

+	   MOV          r14, r10, ASR #16        @y[1] = round(L_tmp)

+

+LOOP:

+           LDRSH        r6, [r0], #2             @load x_hi[]

+	   LDRSH        r7, [r1], #2

+	   STRH         r14, [r2], #2

+	   MOV          r10, r6, LSL #16

+	   ADD          r12, r10, r7, LSL #4

+	   MUL          r9, r14, r8

+	   MOV          r10, r12, LSL #3

+	   QDADD        r10, r10, r9

+           LDRSH        r6, [r0], #2             @load x_hi[]

+	   MOV          r12, r10, LSL #1

+	   QADD         r10, r12, r11

+	   LDRSH        r7, [r1], #2

+	   MOV          r14, r10, ASR #16

+

+	   MOV          r10, r6, LSL #16

+	   ADD          r12, r10, r7, LSL #4

+	   STRH         r14, [r2], #2

+	   MUL          r9, r14, r8

+	   MOV          r10, r12, LSL #3

+	   QDADD        r10, r10, r9

+           ADD          r4, r4, #2

+	   MOV          r12, r10, LSL #1

+	   QADD         r10, r12, r11

+           CMP          r4, #64

+	   MOV          r14, r10, ASR #16

+

+           BLT          LOOP

+           STR          r14, [r3]

+           STRH         r14, [r2]	   

+

+           LDMFD   	r13!, {r4 - r12, r15} 

+

+	   .END

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s
new file mode 100644
index 0000000..07ca344
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s
@@ -0,0 +1,127 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@**********************************************************************/

+@Word32 Dot_product12(                      /* (o) Q31: normalized result (1 < val <= -1) */

+@       Word16 x[],                           /* (i) 12bits: x vector                       */

+@       Word16 y[],                           /* (i) 12bits: y vector                       */

+@       Word16 lg,                            /* (i)    : vector length                     */

+@       Word16 * exp                          /* (o)    : exponent of result (0..+30)       */

+@)

+@************************************************************************

+@  x[]   ---  r0

+@  y[]   ---  r1

+@  lg    ---  r2

+@  *exp  ---  r3

+

+          .section   .text

+          .global    Dot_product12_asm

+

+Dot_product12_asm:

+

+          STMFD   	    r13!, {r4 - r12, r14}

+	  CMP               r0, r1

+	  BEQ               LOOP_EQ

+

+          VLD1.S16          {Q0, Q1}, [r0]!               @load 16 Word16 x[]

+          VLD1.S16          {Q2, Q3}, [r0]!               @load 16 Word16 x[]

+          VLD1.S16          {Q4, Q5}, [r0]!               @load 16 Word16 x[]

+          VLD1.S16          {Q6, Q7}, [r0]!               @load 16 Word16 x[]

+	  VLD1.S16          {Q8, Q9}, [r1]!               @load 16 Word16 y[]

+	  VLD1.S16          {Q10, Q11}, [r1]!             @load 16 Word16 y[]

+	  VLD1.S16          {Q12, Q13}, [r1]!             @load 16 Word16 y[]

+

+          VMULL.S16         Q15, D16, D0

+          VMLAL.S16         Q15, D17, D1               

+          VMLAL.S16         Q15, D18, D2

+          VMLAL.S16         Q15, D19, D3

+	  VLD1.S16          {Q0, Q1}, [r1]!               @load 16 Word16 y[]   

+          VMLAL.S16         Q15, D20, D4       

+          VMLAL.S16         Q15, D21, D5

+          VMLAL.S16         Q15, D22, D6

+          VMLAL.S16         Q15, D23, D7                                       

+          VMLAL.S16         Q15, D24, D8

+          VMLAL.S16         Q15, D25, D9

+          VMLAL.S16         Q15, D26, D10

+          VMLAL.S16         Q15, D27, D11

+          VMLAL.S16         Q15, D0, D12

+          VMLAL.S16         Q15, D1, D13

+          VMLAL.S16         Q15, D2, D14

+          VMLAL.S16         Q15, D3, D15

+

+          CMP               r2, #64

+          BEQ               Lable1

+          VLD1.S16          {Q0, Q1}, [r0]!               @load 16 Word16 x[]  

+	  VLD1.S16          {Q2, Q3}, [r1]! 

+          VMLAL.S16         Q15, D4, D0             

+          VMLAL.S16         Q15, D5, D1

+          VMLAL.S16         Q15, D6, D2

+          VMLAL.S16         Q15, D7, D3

+	  BL                Lable1

+

+LOOP_EQ:

+          VLD1.S16          {Q0, Q1}, [r0]!

+	  VLD1.S16          {Q2, Q3}, [r0]!

+	  VLD1.S16          {Q4, Q5}, [r0]!

+	  VLD1.S16          {Q6, Q7}, [r0]!

+	  VMULL.S16         Q15, D0, D0

+	  VMLAL.S16         Q15, D1, D1

+	  VMLAL.S16         Q15, D2, D2

+	  VMLAL.S16         Q15, D3, D3

+	  VMLAL.S16         Q15, D4, D4

+	  VMLAL.S16         Q15, D5, D5

+	  VMLAL.S16         Q15, D6, D6

+	  VMLAL.S16         Q15, D7, D7

+	  VMLAL.S16         Q15, D8, D8

+	  VMLAL.S16         Q15, D9, D9

+	  VMLAL.S16         Q15, D10, D10

+	  VMLAL.S16         Q15, D11, D11

+	  VMLAL.S16         Q15, D12, D12

+	  VMLAL.S16         Q15, D13, D13

+	  VMLAL.S16         Q15, D14, D14

+	  VMLAL.S16         Q15, D15, D15

+

+	  CMP               r2, #64

+	  BEQ               Lable1

+	  VLD1.S16          {Q0, Q1}, [r0]!

+	  VMLAL.S16         Q15, D0, D0

+	  VMLAL.S16         Q15, D1, D1

+	  VMLAL.S16         Q15, D2, D2

+	  VMLAL.S16         Q15, D3, D3

+

+Lable1: 

+

+          VQADD.S32         D30, D30, D31

+          VPADD.S32         D30, D30, D30

+          VMOV.S32          r12, D30[0]        

+

+	  ADD               r12, r12, r12

+          ADD               r12, r12, #1                         @ L_sum = (L_sum << 1)  + 1

+	  MOV               r4, r12

+	  CMP               r12, #0

+	  RSBLT             r4, r12, #0

+          CLZ               r10, r4

+          SUB               r10, r10, #1                         @ sft = norm_l(L_sum)

+          MOV               r0, r12, LSL r10                     @ L_sum = L_sum << sft

+          RSB               r11, r10, #30                        @ *exp = 30 - sft

+          STRH              r11, [r3]                     

+

+Dot_product12_end:

+		     

+          LDMFD   	    r13!, {r4 - r12, r15} 

+

+          .END

+

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
new file mode 100644
index 0000000..1880024
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s
@@ -0,0 +1,228 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@                             

+@**********************************************************************/

+@void Filt_6k_7k(

+@     Word16 signal[],                      /* input:  signal                  */

+@     Word16 lg,                            /* input:  length of input         */

+@     Word16 mem[]                          /* in/out: memory (size=30)        */

+@)

+@***********************************************************************

+@ r0    ---  signal[]

+@ r1    ---  lg

+@ r2    ---  mem[] 

+

+          .section  .text

+          .global   Filt_6k_7k_asm

+          .extern   fir_6k_7k

+

+Filt_6k_7k_asm:

+

+          STMFD   		r13!, {r0 - r12, r14} 

+          SUB    		r13, r13, #240              @ x[L_SUBFR16k + (L_FIR - 1)]

+          MOV     		r8, r0                      @ copy signal[] address

+          MOV     		r5, r2                      @ copy mem[] address

+

+          MOV     		r0, r2

+          MOV     		r1, r13

+

+	  VLD1.S16              {D0, D1, D2, D3}, [r0]!

+	  VLD1.S16              {D4, D5, D6, D7}, [r0]!

+

+	  VST1.S16              {D0, D1, D2, D3}, [r1]!

+	  VST1.S16              {D4, D5, D6}, [r1]!

+	  VST1.S16              D7[0], [r1]!

+	  VST1.S16              D7[1], [r1]!

+

+

+

+          LDR     		r10, Lable1                 @ get fir_7k address     

+          MOV                   r3, r8                      @ change myMemCopy to Copy, due to Copy will change r3 content

+          ADD     	    	r6, r13, #60                @ get x[L_FIR - 1] address

+          MOV           	r7, r3                      @ get signal[i]

+          @for (i = lg - 1@ i >= 0@ i--)

+          @{

+          @     x[i + L_FIR - 1] = signal[i] >> 2@

+          @}

+	  VLD1.S16              {Q0, Q1}, [r7]!		    @ signal[0]  ~ signal[15]

+	  VLD1.S16              {Q2, Q3}, [r7]!             @ signal[16] ~ signal[31]

+          VLD1.S16              {Q4, Q5}, [r7]!             @ signal[32] ~ signal[47]

+	  VLD1.S16              {Q6, Q7}, [r7]!             @ signal[48] ~ signal[63]

+	  VLD1.S16              {Q8, Q9}, [r7]!             @ signal[64] ~ signal[79]

+	  VSHR.S16              Q10, Q0, #2

+          VSHR.S16              Q11, Q1, #2

+          VSHR.S16              Q12, Q2, #2

+	  VSHR.S16              Q13, Q3, #2

+	  VST1.S16              {Q10, Q11}, [r6]!

+	  VSHR.S16              Q0,  Q4, #2

+	  VSHR.S16              Q1,  Q5, #2

+	  VSHR.S16              Q10, Q6, #2

+	  VSHR.S16              Q11, Q7, #2

+	  VSHR.S16              Q2,  Q8, #2

+	  VSHR.S16              Q3,  Q9, #2

+	  VST1.S16              {Q12, Q13}, [r6]!

+	  VST1.S16              {Q0, Q1}, [r6]!

+	  VST1.S16              {Q10, Q11}, [r6]!

+	  VST1.S16              {Q2, Q3}, [r6]!

+

+	  MOV                   r12, r5

+          @STR     		r5, [sp, #-4]               @ PUSH  r5 to stack

+          @ not use registers: r4, r10, r12, r14, r5

+          MOV     		r4, r13 

+          MOV     		r5, #0                      @ i = 0    

+         

+          @ r4 --- x[i], r10 ---- fir_6k_7k

+          VLD1.S16              {Q0, Q1}, [r10]!           @fir_6k_7k[0]  ~ fir_6k_7k[15]

+	  VLD1.S16              {Q2, Q3}, [r10]!           @fir_6k_7k[16] ~ fir_6k_7k[31]

+          VMOV.S16              D7[3], r5                        @set fir_6k_7K = 0

+

+	  VLD1.S16              {Q4, Q5}, [r4]!            @x[0]  ~ x[15]

+	  VLD1.S16              {Q6, Q7}, [r4]!            @x[16] ~ X[31]

+	  VLD1.S16              {Q8}, [r4]! 

+          VMOV.S16              Q15, #0	  

+          

+LOOP_6K7K:

+

+          VMULL.S16             Q9,D8,D0[0]                 

+          VMULL.S16             Q10,D9,D1[0] 

+          VMULL.S16             Q11,D9,D0[0]                 

+          VMULL.S16             Q12,D10,D1[0]

+          VEXT.8                Q4,Q4,Q5,#2

+          VMLAL.S16             Q9,D10,D2[0]

+          VMLAL.S16             Q10,D11,D3[0]

+          VMLAL.S16             Q11,D11,D2[0]

+          VMLAL.S16             Q12,D12,D3[0]    

+          VEXT.8                Q5,Q5,Q6,#2

+          VMLAL.S16             Q9,D12,D4[0]

+          VMLAL.S16             Q10,D13,D5[0]

+          VMLAL.S16             Q11,D13,D4[0]

+          VMLAL.S16             Q12,D14,D5[0]

+          VEXT.8                Q6,Q6,Q7,#2

+          VMLAL.S16             Q9,D14,D6[0]

+          VMLAL.S16             Q10,D15,D7[0]

+          VMLAL.S16             Q11,D15,D6[0]

+	  VMLAL.S16             Q12,D16,D7[0]

+	  VEXT.8  		Q7,Q7,Q8,#2 

+

+	  VMLAL.S16 		Q9,D8,D0[1]                

+	  VMLAL.S16     	Q10,D9,D1[1]

+	  VEXT.8 		Q8,Q8,Q15,#2 

+	  VMLAL.S16 		Q11,D9,D0[1]                

+	  VMLAL.S16 		Q12,D10,D1[1]

+	  VEXT.8  		Q4,Q4,Q5,#2

+	  VMLAL.S16 		Q9,D10,D2[1]

+	  VMLAL.S16 		Q10,D11,D3[1]

+	  VMLAL.S16 		Q11,D11,D2[1]

+	  VMLAL.S16 		Q12,D12,D3[1]    

+	  VEXT.8  		Q5,Q5,Q6,#2

+	  VMLAL.S16 		Q9,D12,D4[1]

+	  VMLAL.S16 		Q10,D13,D5[1]

+	  VMLAL.S16 		Q11,D13,D4[1]

+	  VMLAL.S16 		Q12,D14,D5[1]

+	  VEXT.8  		Q6,Q6,Q7,#2

+	  VMLAL.S16 		Q9,D14,D6[1]

+	  VMLAL.S16 		Q10,D15,D7[1]

+	  VMLAL.S16 		Q11,D15,D6[1]

+	  VMLAL.S16 		Q12,D16,D7[1]

+	  VEXT.8  		Q7,Q7,Q8,#2 

+

+	  VMLAL.S16 		Q9,D8,D0[2]           

+	  VMLAL.S16 		Q10,D9,D1[2]

+	  VEXT.8 		Q8,Q8,Q15,#2 

+	  VMLAL.S16 		Q11,D9,D0[2]           

+	  VMLAL.S16 		Q12,D10,D1[2]

+	  VEXT.8  		Q4,Q4,Q5,#2

+	  VMLAL.S16 		Q9,D10,D2[2]

+	  VMLAL.S16 		Q10,D11,D3[2]

+	  VMLAL.S16 		Q11,D11,D2[2]

+	  VMLAL.S16 		Q12,D12,D3[2]    

+	  VEXT.8  		Q5,Q5,Q6,#2

+	  VMLAL.S16 		Q9,D12,D4[2]

+	  VMLAL.S16 		Q10,D13,D5[2]

+	  VMLAL.S16 		Q11,D13,D4[2]

+	  VMLAL.S16 		Q12,D14,D5[2]

+	  VEXT.8  		Q6,Q6,Q7,#2

+	  VMLAL.S16 		Q9,D14,D6[2]

+	  VMLAL.S16 		Q10,D15,D7[2]

+	  VMLAL.S16 		Q11,D15,D6[2]

+	  VMLAL.S16 		Q12,D16,D7[2]

+	  VEXT.8  		Q7,Q7,Q8,#2 

+

+	  VMLAL.S16 		Q9,D8,D0[3]              

+	  VMLAL.S16 		Q10,D9,D1[3]

+	  VEXT.8 		Q8,Q8,Q15,#2 

+	  VMLAL.S16 		Q11,D9,D0[3]              

+	  VMLAL.S16 		Q12,D10,D1[3]

+	  VEXT.8  		Q4,Q4,Q5,#2

+	  VMLAL.S16 		Q9,D10,D2[3]

+	  VMLAL.S16 		Q10,D11,D3[3]

+	  VMLAL.S16 		Q11,D11,D2[3]

+	  VMLAL.S16 		Q12,D12,D3[3]    

+	  VEXT.8  		Q5,Q5,Q6,#2

+	  VMLAL.S16 		Q9,D12,D4[3]

+	  VMLAL.S16 		Q10,D13,D5[3]

+	  VMLAL.S16 		Q11,D13,D4[3]

+	  VMLAL.S16 		Q12,D14,D5[3]

+	  VEXT.8  		Q6,Q6,Q7,#2

+	  VMLAL.S16 		Q9,D14,D6[3]

+	  VMLAL.S16 		Q10,D15,D7[3]

+	  VMLAL.S16 		Q11,D15,D6[3]

+	  VMLAL.S16 		Q12,D16,D7[3]

+	  VEXT.8 		Q7,Q7,Q8,#2     

+

+	  VMOV.S16  		D8,D9

+	  VEXT.8 		Q8,Q8,Q15,#2 

+	  VMOV.S16  		D9,D10

+	  VADD.S32  		Q9,Q9,Q10

+	  VMOV.S16  		D10,D11

+	  VMOV.S16  		D11,D12

+	  VADD.S32  		Q11,Q11,Q12

+	  VMOV.S16  		D12,D13

+	  VQRSHRN.S32 		D28,Q9,#15

+	  VMOV.S16  		D13,D14

+	  VMOV.S16  		D14,D15

+	  VQRSHRN.S32 		D29,Q11,#15

+	  VMOV.S16  		D15,D16

+

+	  VLD1.S16  		{Q8},[r4]!

+	  ADD                   r5, r5, #8

+	  CMP   		r5, #80

+	  VST1.S16  		{D28,D29},[r3]!

+	  BLT     		LOOP_6K7K

+

+          ADD     		r0, r13, #160               @x + lg

+	  MOV                   r1, r12

+	  @LDR     		r1, [sp, #-4]               @mem address

+

+	  VLD1.S16              {D0, D1, D2, D3}, [r0]!

+	  VLD1.S16              {D4, D5, D6, D7}, [r0]!

+

+	  VST1.S16              {D0, D1, D2, D3}, [r1]!

+	  VST1.S16              {D4, D5, D6}, [r1]!

+	  VST1.S16              D7[0], [r1]!

+	  VST1.S16              D7[1], [r1]!

+                    

+Filt_6k_7k_end:

+

+          ADD     		r13, r13, #240  

+          LDMFD   		r13!, {r0 - r12, r15} 

+ 

+Lable1:

+          .word   		fir_6k_7k

+          @ENDFUNC

+          .END

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s
new file mode 100644
index 0000000..60e9ade
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s
@@ -0,0 +1,270 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** 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.
+@ */
+@
+@static void Norm_Corr (Word16 exc[],                    /* (i)     : excitation buffer          */
+@                       Word16 xn[],                     /* (i)     : target vector              */
+@                       Word16 h[],                      /* (i) Q15 : impulse response of synth/wgt filters */
+@                       Word16 L_subfr,                  /* (i)     : sub-frame length */
+@                       Word16 t_min,                    /* (i)     : minimum value of pitch lag.   */
+@                       Word16 t_max,                    /* (i)     : maximum value of pitch lag.   */
+@                       Word16 corr_norm[])              /* (o) Q15 : normalized correlation    */
+@
+
+@ r0 --- exc[]
+@ r1 --- xn[]
+@ r2 --- h[]
+@ r3 --- L_subfr
+@ r4 --- t_min
+@ r5 --- t_max
+@ r6 --- corr_norm[]
+
+
+	.section  .text
+        .global    Norm_corr_asm 
+        .extern    Convolve_asm
+        .extern    Isqrt_n
+@******************************
+@ constant
+@******************************
+.equ    EXC               , 0
+.equ    XN                , 4
+.equ    H                 , 8
+.equ    L_SUBFR           , 12
+.equ    voSTACK           , 172
+.equ    T_MIN             , 212
+.equ    T_MAX             , 216
+.equ    CORR_NORM         , 220
+                  
+Norm_corr_asm:
+
+        STMFD          r13!, {r4 - r12, r14}  
+        SUB            r13, r13, #voSTACK
+  
+        ADD            r8, r13, #20                 @get the excf[L_SUBFR]
+        LDR            r4, [r13, #T_MIN]            @get t_min
+        RSB            r11, r4, #0                  @k = -t_min
+        ADD            r5, r0, r11, LSL #1          @get the &exc[k]   
+        
+        @transfer Convolve function
+        STMFD          sp!, {r0 - r3}
+        MOV            r0, r5
+        MOV            r1, r2
+        MOV            r2, r8                       @r2 --- excf[]
+        BL             Convolve_asm
+        LDMFD          sp!, {r0 - r3}
+
+        @ r8 --- excf[]
+
+	MOV            r14, r1                       @copy xn[] address                      
+        MOV            r7, #1
+	VLD1.S16       {Q0, Q1}, [r14]!
+	VLD1.S16       {Q2, Q3}, [r14]!
+	VLD1.S16       {Q4, Q5}, [r14]!
+	VLD1.S16       {Q6, Q7}, [r14]!
+
+        VMULL.S16      Q10, D0, D0
+        VMLAL.S16      Q10, D1, D1
+        VMLAL.S16      Q10, D2, D2
+        VMLAL.S16      Q10, D3, D3
+        VMLAL.S16      Q10, D4, D4
+        VMLAL.S16      Q10, D5, D5
+        VMLAL.S16      Q10, D6, D6
+        VMLAL.S16      Q10, D7, D7
+        VMLAL.S16      Q10, D8, D8
+        VMLAL.S16      Q10, D9, D9
+	VMLAL.S16      Q10, D10, D10
+	VMLAL.S16      Q10, D11, D11
+	VMLAL.S16      Q10, D12, D12
+	VMLAL.S16      Q10, D13, D13
+	VMLAL.S16      Q10, D14, D14
+	VMLAL.S16      Q10, D15, D15
+
+        VQADD.S32      D20, D20, D21
+        VMOV.S32       r9,  D20[0]
+        VMOV.S32       r10, D20[1]
+        QADD           r6, r9, r10 
+	QADD           r6, r6, r6
+        QADD           r9, r6, r7                   @L_tmp = (L_tmp << 1) + 1;
+	CLZ            r7, r9
+	SUB            r6, r7, #1                   @exp = norm_l(L_tmp)
+        RSB            r7, r6, #32                  @exp = 32 - exp
+	MOV            r6, r7, ASR #1         
+	RSB            r7, r6, #0                   @scale = -(exp >> 1)
+	
+        @loop for every possible period
+	@for(t = t_min@ t <= t_max@ t++)
+	@r7 --- scale r4 --- t_min r8 --- excf[]
+
+LOOPFOR:	
+	ADD            r14, r13, #20                @copy of excf[]
+	MOV            r12, r1                      @copy of xn[]
+	MOV            r8, #0x8000
+
+        VLD1.S16       {Q0, Q1}, [r14]!                 @ load 16 excf[]
+        VLD1.S16       {Q2, Q3}, [r14]!                 @ load 16 excf[]       
+        VLD1.S16       {Q4, Q5}, [r12]!                 @ load 16 x[]
+	VLD1.S16       {Q6, Q7}, [r12]!                 @ load 16 x[]
+        VMULL.S16    Q10, D0, D0                      @L_tmp1 += excf[] * excf[]
+        VMULL.S16    Q11, D0, D8                      @L_tmp  += x[] * excf[]                   
+        VMLAL.S16    Q10, D1, D1
+        VMLAL.S16    Q11, D1, D9
+        VMLAL.S16    Q10, D2, D2
+        VMLAL.S16    Q11, D2, D10        
+        VMLAL.S16    Q10, D3, D3
+        VMLAL.S16    Q11, D3, D11
+        VMLAL.S16    Q10, D4, D4
+        VMLAL.S16    Q11, D4, D12
+        VMLAL.S16    Q10, D5, D5
+        VMLAL.S16    Q11, D5, D13
+        VMLAL.S16    Q10, D6, D6
+        VMLAL.S16    Q11, D6, D14
+        VMLAL.S16    Q10, D7, D7
+        VMLAL.S16    Q11, D7, D15
+
+	VLD1.S16       {Q0, Q1}, [r14]!                 @ load 16 excf[]
+        VLD1.S16       {Q2, Q3}, [r14]!                 @ load 16 excf[]
+        VLD1.S16       {Q4, Q5}, [r12]!                 @ load 16 x[]
+        VLD1.S16       {Q6, Q7}, [r12]!                 @ load 16 x[]
+        VMLAL.S16    Q10, D0, D0
+        VMLAL.S16    Q11, D0, D8
+        VMLAL.S16    Q10, D1, D1
+        VMLAL.S16    Q11, D1, D9
+        VMLAL.S16    Q10, D2, D2
+        VMLAL.S16    Q11, D2, D10        
+        VMLAL.S16    Q10, D3, D3
+        VMLAL.S16    Q11, D3, D11
+        VMLAL.S16    Q10, D4, D4
+        VMLAL.S16    Q11, D4, D12
+        VMLAL.S16    Q10, D5, D5
+        VMLAL.S16    Q11, D5, D13
+        VMLAL.S16    Q10, D6, D6
+        VMLAL.S16    Q11, D6, D14
+        VMLAL.S16    Q10, D7, D7
+        VMLAL.S16    Q11, D7, D15
+
+        VQADD.S32      D20, D20, D21
+        VQADD.S32      D22, D22, D23
+
+	VPADD.S32      D20, D20, D20                   @D20[0] --- L_tmp1 << 1
+	VPADD.S32      D22, D22, D22                   @D22[0] --- L_tmp << 1
+
+	VMOV.S32       r6, D20[0]
+        VMOV.S32       r5, D22[0]	
+
+	@r5 --- L_tmp, r6 --- L_tmp1
+	MOV            r10, #1
+	ADD            r5, r10, r5, LSL #1                     @L_tmp = (L_tmp << 1) + 1
+	ADD            r6, r10, r6, LSL #1                     @L_tmp1 = (L_tmp1 << 1) + 1
+ 
+	CLZ            r10, r5        
+	CMP            r5, #0
+	RSBLT          r11, r5, #0
+	CLZLT          r10, r11
+	SUB            r10, r10, #1                 @exp = norm_l(L_tmp)
+     
+	MOV            r5, r5, LSL r10              @L_tmp = (L_tmp << exp)
+	RSB            r10, r10, #30                @exp_corr = 30 - exp
+	MOV            r11, r5, ASR #16             @corr = extract_h(L_tmp)
+
+	CLZ            r5, r6
+	SUB            r5, r5, #1
+	MOV            r6, r6, LSL r5               @L_tmp = (L_tmp1 << exp)
+	RSB            r5, r5, #30                  @exp_norm = 30 - exp
+
+	@r10 --- exp_corr, r11 --- corr
+	@r6  --- L_tmp, r5 --- exp_norm
+
+	@Isqrt_n(&L_tmp, &exp_norm)
+
+	MOV            r14, r0
+	MOV            r12, r1 
+
+        STMFD          sp!, {r0 - r4, r7 - r12, r14}
+	ADD            r1, sp, #4
+	ADD            r0, sp, #0
+	STR            r6, [sp]
+	STRH           r5, [sp, #4]
+	BL             Isqrt_n
+	LDR            r6, [sp]
+	LDRSH          r5, [sp, #4]
+        LDMFD          sp!, {r0 - r4, r7 - r12, r14}
+	MOV            r0, r14
+	MOV            r1, r12
+
+
+	MOV            r6, r6, ASR #16              @norm = extract_h(L_tmp)
+	MUL            r12, r6, r11
+	ADD            r12, r12, r12                @L_tmp = vo_L_mult(corr, norm)
+  
+	ADD            r6, r10, r5
+	ADD            r6, r6, r7                   @exp_corr + exp_norm + scale
+
+        CMP            r6, #0
+        RSBLT          r6, r6, #0
+	MOVLT          r12, r12, ASR r6
+        MOVGT          r12, r12, LSL r6             @L_tmp = L_shl(L_tmp, exp_corr + exp_norm + scale)
+
+        ADD            r12, r12, r8
+        MOV            r12, r12, ASR #16            @vo_round(L_tmp)
+
+        LDR            r5, [r13, #CORR_NORM]        @ get corr_norm address
+	LDR            r6, [r13, #T_MAX]            @ get t_max
+	ADD            r10, r5, r4, LSL #1          @ get corr_norm[t] address
+	STRH           r12, [r10]                   @ corr_norm[t] = vo_round(L_tmp)
+
+	CMP            r4, r6
+	BEQ            Norm_corr_asm_end
+ 
+	ADD            r4, r4, #1                   @ t_min ++ 
+	RSB            r5, r4, #0                   @ k
+
+	MOV            r6, #63                      @ i = 63
+	MOV            r8, r0                       @ exc[]
+	MOV            r9, r2                       @ h[]
+	ADD            r10, r13, #20                @ excf[]
+
+	ADD            r8, r8, r5, LSL #1           @ exc[k] address
+	ADD            r9, r9, r6, LSL #1           @ h[i] address
+	ADD            r10, r10, r6, LSL #1         @ excf[i] address
+	LDRSH          r11, [r8]                    @ tmp = exc[k]
+
+LOOPK:
+        LDRSH          r8, [r9], #-2                @ load h[i]
+	LDRSH          r12, [r10, #-2]              @ load excf[i - 1]
+	MUL            r14, r11, r8
+	MOV            r8, r14, ASR #15
+	ADD            r14, r8, r12
+	STRH           r14, [r10], #-2
+	SUBS           r6, r6, #1
+	BGT            LOOPK
+
+	LDRSH          r8, [r9]                     @ load h[0]
+	MUL            r14, r11, r8
+        LDR            r6, [r13, #T_MAX]            @ get t_max
+	MOV            r8, r14, ASR #15
+	STRH           r8, [r10]                    
+
+	CMP            r4, r6
+	BLE            LOOPFOR
+
+Norm_corr_asm_end: 
+        
+        ADD            r13, r13, #voSTACK      
+        LDMFD          r13!, {r4 - r12, r15}
+    
+        .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s
new file mode 100644
index 0000000..cb1764f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s
@@ -0,0 +1,133 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@**********************************************************************/

+@void Syn_filt_32(

+@     Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients */

+@     Word16 m,                             /* (i)     : order of LP filter             */

+@     Word16 exc[],                         /* (i) Qnew: excitation (exc[i] >> Qnew)    */

+@     Word16 Qnew,                          /* (i)     : exc scaling = 0(min) to 8(max) */

+@     Word16 sig_hi[],                      /* (o) /16 : synthesis high                 */

+@     Word16 sig_lo[],                      /* (o) /16 : synthesis low                  */

+@     Word16 lg                             /* (i)     : size of filtering              */

+@)

+@***********************************************************************

+@ a[]      --- r0

+@ m        --- r1

+@ exc[]    --- r2

+@ Qnew     --- r3

+@ sig_hi[] --- r4

+@ sig_lo[] --- r5

+@ lg       --- r6

+

+          .section  .text 

+          .global   Syn_filt_32_asm

+

+Syn_filt_32_asm:

+

+          STMFD   	r13!, {r4 - r12, r14} 

+          LDR           r4,  [r13, #40]                  @ get sig_hi[] address

+          LDR           r5,  [r13, #44]                  @ get sig_lo[] address

+

+          LDRSH         r6,  [r0], #2                    @ load Aq[0]

+          ADD           r7,  r3, #4                      @ 4 + Q_new

+          MOV           r3, r6, ASR r7                   @ a0 = Aq[0] >> (4 + Q_new)

+

+	  SUB           r10, r4, #32                     @ sig_hi[-16] address

+	  SUB           r11, r5, #32                     @ sig_lo[-16] address

+

+	  VLD1.S16      {D0, D1, D2, D3}, [r0]!          @a[1] ~ a[16] 

+  

+          MOV           r8, #0                           @ i = 0

+

+	  VLD1.S16      {D4, D5, D6, D7}, [r10]!         @ sig_hi[-16] ~ sig_hi[-1]

+          VREV64.16     D0, D0

+          VREV64.16     D1, D1

+	  VLD1.S16      {D8, D9, D10, D11}, [r11]!       @ sig_lo[-16] ~ sig_lo[-1]

+          VREV64.16     D2, D2

+          VREV64.16     D3, D3	

+          VDUP.S32      Q15, r8

+              

+SYN_LOOP:

+

+          LDRSH         r6, [r2], #2                     @exc[i]

+	  @L_tmp = L_msu(L_tmp, sig_lo[i - j], a[j])@

+	  VMULL.S16     Q10, D8, D3

+	  VEXT.8        D8, D8, D9, #2

+	  VMLAL.S16     Q10, D9, D2

+	  VMLAL.S16     Q10, D10, D1

+	  VMLAL.S16     Q10, D11, D0

+

+	  VEXT.8        D9, D9, D10, #2

+	  VEXT.8        D10, D10, D11, #2

+	  

+	  VPADD.S32     D28, D20, D21

+          MUL           r12, r6, r3                      @exc[i] * a0

+	  VPADD.S32     D29, D28, D28

+	  VDUP.S32      Q10, D29[0]                      @result1

+          

+	  VMULL.S16     Q11, D4, D3

+	  VMLAL.S16     Q11, D5, D2

+          VSUB.S32      Q10, Q15, Q10

+	  @L_tmp = L_msu(L_tmp, sig_hi[i - j], a[j])@

+

+	  VMLAL.S16     Q11, D6, D1

+	  VEXT.8        D4, D4, D5, #2

+	  VMLAL.S16     Q11, D7, D0

+

+

+	  VEXT.8        D5, D5, D6, #2

+	  VEXT.8        D6, D6, D7, #2

+

+	  VPADD.S32     D28, D22, D23

+          VPADD.S32     D29, D28, D28

+          MOV           r14, r12, LSL #1                 @exc[i] * a0 << 1

+          VDUP.S32      Q11, D29[0]                      @result2

+

+

+

+	  VSHR.S32      Q10, Q10, #11                    @result1 >>= 11

+	  VSHL.S32      Q11, Q11, #1                     @result2 <<= 1

+	  VDUP.S32      Q12, r14                         

+	  VADD.S32      Q12, Q12, Q10                    @L_tmp = L_tmp - (result1 >>= 11) - (result2 <<= 1)

+	  VSUB.S32      Q12, Q12, Q11

+

+	  VSHL.S32      Q12, Q12, #3                     @L_tmp <<= 3

+

+

+	  VSHRN.S32     D20, Q12, #16                    @sig_hi[i] = L_tmp >> 16@

+	  VMOV.S16      r10, D20[0]

+	  VSHR.S32      Q12, Q12, #4                     @L_tmp >>= 4

+	  VEXT.8        D7, D7, D20, #2

+	  STRH          r10, [r4], #2                    @store sig_hi[i]

+          VMOV.S32      r11, D24[0]                      @r11 --- L_tmp >>= 4

+	  ADD           r8, r8, #1

+	  SUB           r12, r11, r10, LSL #12

+	  @MOV           r11, r12, ASR #16                @sig_lo[i]

+	  VDUP.S16      D21, r12

+	  VEXT.8        D11, D11, D21, #2

+	  STRH          r12, [r5], #2                    @stroe sig_lo[i]

+

+          CMP           r8, #64

+          BLT           SYN_LOOP                          

+         

+Syn_filt_32_end:

+		     

+          LDMFD   	    r13!, {r4 - r12, r15} 

+          @ENDFUNC

+          .END

+ 

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s
new file mode 100644
index 0000000..189e33b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s
@@ -0,0 +1,178 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** 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.
+@ */
+@
+@*void Convolve (
+@*    Word16 x[],        /* (i)     : input vector                           */
+@*    Word16 h[],        /* (i)     : impulse response                       */
+@*    Word16 y[],        /* (o)     : output vector                          */
+@*    Word16 L           /* (i)     : vector size                            */
+@*)
+@ 
+@ r0 --- x[]
+@ r1 --- h[]
+@ r2 --- y[]
+@ r3 --- L
+
+	.section  .text 
+        .global   Convolve_asm 
+
+Convolve_asm:
+
+        STMFD          r13!, {r4 - r12, r14}  
+        MOV            r3,  #0                        
+	MOV            r11, #0x8000
+        
+LOOP: 
+        @MOV            r8, #0                            @ s = 0
+        ADD            r4, r1, r3, LSL #1                @ tmpH address
+        ADD            r5, r3, #1                        @ i = n + 1
+        MOV            r6, r0
+        LDRSH          r9,  [r6], #2                     @ *tmpX++
+        LDRSH          r10, [r4]                         @ *tmpH--
+        SUB            r5, r5, #1
+        VMOV.S32       Q10, #0 
+        MUL            r8,  r9, r10 
+
+LOOP1:                    
+        CMP            r5, #0
+        BLE            L1
+        SUB            r4, r4, #8
+        MOV            r9, r4
+        VLD1.S16       D0, [r6]!   
+        VLD1.S16       D1, [r9]!
+        VREV64.16      D1, D1
+        SUBS           r5, r5, #4  
+        VMLAL.S16      Q10, D0, D1         
+        B              LOOP1    
+L1:                  
+        VADD.S32       D20, D20, D21
+        VPADD.S32      D20, D20, D20
+        VMOV.S32       r5, D20[0]
+        ADD            r5, r5, r8
+        ADD            r5, r11, r5, LSL #1
+        MOV            r5, r5, LSR #16                   @extract_h(s)
+        ADD            r3, r3, #1
+        STRH           r5, [r2], #2                      @y[n]
+
+
+        @MOV            r8, #0
+        ADD            r4, r1, r3, LSL #1                @tmpH address
+        ADD            r5, r3, #1
+        MOV            r6, r0
+        LDRSH          r9,  [r6], #2                     @ *tmpX++
+        LDRSH          r10, [r4], #-2                     
+        LDRSH          r12, [r6], #2
+        LDRSH          r14, [r4]
+
+        MUL            r8, r9, r10
+        SUB            r5, r5, #2
+        MLA            r8, r12, r14, r8
+        
+        VMOV.S32       Q10, #0
+LOOP2:
+        CMP            r5, #0
+        BLE            L2
+        SUB            r4, r4, #8
+        MOV            r9, r4
+        VLD1.S16       D0, [r6]!   
+        VLD1.S16       D1, [r9]!
+        SUBS           r5, r5, #4
+        VREV64.16      D1, D1
+        VMLAL.S16      Q10, D0, D1 
+        B              LOOP2
+L2:
+        VADD.S32       D20, D20, D21
+        VPADD.S32      D20, D20, D20
+        VMOV.S32       r5, D20[0]
+        ADD            r8, r8, r5
+        ADD            r8, r11, r8, LSL #1
+        MOV            r8, r8, LSR #16                   @extract_h(s)
+        ADD            r3, r3, #1  
+        STRH           r8, [r2], #2                      @y[n]
+
+
+        @MOV            r8, #0
+        ADD            r4, r1, r3, LSL #1
+        ADD            r5, r3, #1
+        MOV            r6, r0
+        LDRSH          r9,  [r6], #2
+        LDRSH          r10, [r4], #-2
+        LDRSH          r12, [r6], #2
+        LDRSH          r14, [r4], #-2
+        MUL            r8, r9, r10
+        LDRSH          r9,  [r6], #2
+        LDRSH          r10, [r4]
+        MLA            r8, r12, r14, r8 
+        SUB            r5, r5, #3
+        MLA            r8, r9, r10, r8
+
+        VMOV.S32       Q10, #0
+LOOP3:
+        CMP            r5, #0
+        BLE            L3
+        SUB            r4, r4, #8
+        MOV            r9, r4
+        VLD1.S16       D0, [r6]!   
+        VLD1.S16       D1, [r9]!
+        VREV64.16      D1, D1
+        SUBS           r5, r5, #4
+        VMLAL.S16      Q10, D0, D1 
+        B              LOOP3   
+
+L3:
+        VADD.S32       D20, D20, D21
+        VPADD.S32      D20, D20, D20
+        VMOV.S32       r5, D20[0]
+        ADD            r8, r8, r5
+        ADD            r8, r11, r8, LSL #1
+        MOV            r8, r8, LSR #16                   @extract_h(s)
+        ADD            r3, r3, #1
+        STRH           r8, [r2], #2                      @y[n]
+
+        ADD            r5, r3, #1                        @ i = n + 1
+        ADD            r4, r1, r5, LSL #1                @ tmpH address
+        MOV            r6, r0
+        VMOV.S32       Q10, #0
+LOOP4:                    
+        CMP            r5, #0
+        BLE            L4
+        SUB            r4, r4, #8
+        MOV            r9, r4
+        VLD1.S16       D0, [r6]!   
+        VLD1.S16       D1, [r9]!
+        VREV64.16      D1, D1
+        SUBS           r5, r5, #4  
+        VMLAL.S16      Q10, D0, D1         
+        B              LOOP4    
+L4:                  
+        VADD.S32       D20, D20, D21
+        VPADD.S32      D20, D20, D20
+        VMOV.S32       r5,  D20[0]
+        ADD            r5, r11, r5, LSL #1
+        MOV            r5, r5, LSR #16                   @extract_h(s)
+        ADD            r3, r3, #1
+        STRH           r5, [r2], #2                      @y[n]
+        
+        CMP            r3, #64
+        BLT            LOOP
+                
+Convolve_asm_end: 
+ 
+        LDMFD      r13!, {r4 - r12, r15}
+    
+        @ENDFUNC
+        .END
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s
new file mode 100644
index 0000000..2e339db
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s
@@ -0,0 +1,151 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@static void cor_h_vec_012(

+@		Word16 h[],                           /* (i) scaled impulse response                 */

+@		Word16 vec[],                         /* (i) scaled vector (/8) to correlate with h[] */

+@		Word16 track,                         /* (i) track to use                            */

+@		Word16 sign[],                        /* (i) sign vector                             */

+@		Word16 rrixix[][NB_POS],              /* (i) correlation of h[x] with h[x]      */

+@		Word16 cor_1[],                       /* (o) result of correlation (NB_POS elements) */

+@		Word16 cor_2[]                        /* (o) result of correlation (NB_POS elements) */

+@)

+@r0 ---- h[]

+@r1 ---- vec[]

+@r2 ---- track

+@r3 ---- sign[]

+@r4 ---- rrixix[][NB_POS]

+@r5 ---- cor_1[]

+@r6 ---- cor_2[]

+

+              .section .text 

+	      .global  cor_h_vec_012_asm

+

+cor_h_vec_012_asm:

+

+             STMFD         r13!, {r4 - r12, r14}

+	     LDR           r4, [r13, #40]                    @load rrixix[][NB_POS]

+	     ADD           r7, r4, r2, LSL #5                @r7 --- p0 = rrixix[track]

+             MOV           r4, #0                            @i=0

+

+	     @r0 --- h[], r1 --- vec[],  r2 --- pos

+	     @r3 --- sign[], r4 --- i, r7 --- p0

+

+LOOPi:

+             MOV           r5, #0                            @L_sum1 = 0

+	     MOV           r6, #0                            @L_sum2 = 0

+	     ADD           r9, r1, r2, LSL #1                @p2 = &vec[pos]

+	     MOV           r10, r0                           @p1 = h

+	     RSB           r11, r2, #62                      @j=62-pos

+

+LOOPj1:

+	     LDRSH         r12, [r10], #2  

+	     LDRSH         r8,  [r9], #2

+	     LDRSH         r14, [r9]

+	     SUBS          r11, r11, #1

+             MLA           r5, r12, r8, r5

+             MLA           r6, r12, r14, r6	 

+	     BGE           LOOPj1

+

+	     LDRSH         r12, [r10], #2                     @*p1++

+	     MOV           r6, r6, LSL #2                     @L_sum2 = (L_sum2 << 2)

+             MLA           r5, r12, r14, r5

+             MOV           r14, #0x8000

+             MOV           r5, r5, LSL #2                     @L_sum1 = (L_sum1 << 2)

+             ADD           r10, r6, r14         

+             ADD           r9, r5, r14

+             MOV           r5, r9, ASR #16

+             MOV           r6, r10, ASR #16

+             ADD           r9, r3, r2, LSL #1                 @address of sign[pos]

+             ADD           r8, r7, #32

+             LDRSH         r10, [r9], #2                 	  @sign[pos]

+	     LDRSH         r11, [r9]                          @sign[pos + 1]

+	     MUL           r12, r5, r10

+	     MUL           r14, r6, r11

+	     MOV           r5, r12, ASR #15

+	     MOV           r6, r14, ASR #15

+	     LDR           r9,  [r13, #44]                   

+	     LDR           r12, [r13, #48]

+             LDRSH         r10, [r7], #2                      @*p0++

+	     LDRSH         r11, [r8]                          @*p3++

+             ADD           r9, r9, r4, LSL #1

+	     ADD           r12, r12, r4, LSL #1

+	     ADD           r5, r5, r10

+	     ADD           r6, r6, r11

+	     STRH          r5, [r9]

+	     STRH          r6, [r12]

+

+             ADD           r2, r2, #4

+ 

+             MOV           r5, #0                            @L_sum1 = 0

+	     MOV           r6, #0                            @L_sum2 = 0

+	     ADD           r9, r1, r2, LSL #1                @p2 = &vec[pos]

+	     MOV           r10, r0                           @p1 = h

+	     RSB           r11, r2, #62                      @j=62-pos

+	     ADD           r4, r4, #1                        @i++

+

+LOOPj2:

+	     LDRSH         r12, [r10], #2  

+	     LDRSH         r8,  [r9], #2

+	     LDRSH         r14, [r9]

+	     SUBS          r11, r11, #1

+             MLA           r5, r12, r8, r5

+             MLA           r6, r12, r14, r6	 

+	     BGE           LOOPj2

+

+	     LDRSH         r12, [r10], #2                     @*p1++

+	     MOV           r6, r6, LSL #2                     @L_sum2 = (L_sum2 << 2)

+             MLA           r5, r12, r14, r5

+             MOV           r14, #0x8000

+             MOV           r5, r5, LSL #2                     @L_sum1 = (L_sum1 << 2)

+             ADD           r10, r6, r14        

+             ADD           r9, r5, r14

+

+             MOV           r5, r9, ASR #16

+             MOV           r6, r10, ASR #16

+             ADD           r9, r3, r2, LSL #1                 @address of sign[pos]

+             ADD           r8, r7, #32

+             LDRSH         r10, [r9], #2                 	  @sign[pos]

+	     LDRSH         r11, [r9]                          @sign[pos + 1]

+	     MUL           r12, r5, r10

+	     MUL           r14, r6, r11

+	     MOV           r5, r12, ASR #15

+	     MOV           r6, r14, ASR #15

+	     LDR           r9,  [r13, #44]                   

+	     LDR           r12, [r13, #48]

+             LDRSH         r10, [r7], #2                      @*p0++

+	     LDRSH         r11, [r8]                          @*p3++

+             ADD           r9, r9, r4, LSL #1

+	     ADD           r12, r12, r4, LSL #1

+	     ADD           r5, r5, r10

+	     ADD           r6, r6, r11

+	     STRH          r5, [r9]

+	     STRH          r6, [r12]

+	     ADD           r4, r4, #1                         @i+1

+	     ADD           r2, r2, #4                         @pos += STEP

+	     CMP           r4, #16

+	     

+	     BLT           LOOPi

+         

+the_end:

+             LDMFD         r13!, {r4 - r12, r15}

+             

+	     .END	 

+        

+	

+	  

+

+

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
new file mode 100644
index 0000000..3b8853f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s
@@ -0,0 +1,100 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@void Pred_lt4(

+@     Word16 exc[],                         /* in/out: excitation buffer */

+@     Word16 T0,                            /* input : integer pitch lag */

+@     Word16 frac,                          /* input : fraction of lag   */

+@     Word16 L_subfr                        /* input : subframe size     */

+@)

+@***********************************************************************

+@ r0    ---  exc[]

+@ r1    ---  T0

+@ r2    ---  frac

+@ r3    ---  L_subfr

+ 

+          .section  .text 

+          .global   pred_lt4_asm

+          .extern   inter4_2

+

+pred_lt4_asm:

+

+          STMFD   	r13!, {r4 - r12, r14} 

+          SUB           r4, r0, r1, LSL #1                        @ x = exc - T0

+          RSB           r2, r2, #0                                @ frac = - frac

+          SUB           r4, r4, #30                               @ x -= L_INTERPOL2 - 1

+          CMP           r2, #0

+          ADDLT         r2, r2, #4                                @ frac += UP_SAMP

+          SUBLT         r4, r4, #2                                @ x--

+

+          LDR           r11, Lable1

+          RSB           r2, r2, #3                                @ k = UP_SAMP - 1 - frac

+          MOV           r8, #0                                    @ j = 0

+	  ADD           r11, r11, r2, LSL #6                      @ get inter4_2[k][]

+

+	  VLD1.S16      {Q0, Q1}, [r11]!

+	  VLD1.S16      {Q2, Q3}, [r11]!

+          

+	  MOV           r6, #0x8000 

+

+          VLD1.S16      {Q4, Q5}, [r4]!                           @load 16 x[]

+          VLD1.S16      {Q6, Q7}, [r4]!                           @load 16 x[]

+

+LOOP:

+          VQDMULL.S16   Q15, D8, D0

+          VQDMLAL.S16   Q15, D9, D1

+          VQDMLAL.S16   Q15, D10, D2

+          VQDMLAL.S16   Q15, D11, D3

+        

+          VQDMLAL.S16   Q15, D12, D4

+          VQDMLAL.S16   Q15, D13, D5

+          VQDMLAL.S16   Q15, D14, D6

+          VQDMLAL.S16   Q15, D15, D7

+

+          LDRSH         r12, [r4], #2                

+          

+          VEXT.S16      D8, D8, D9, #1

+          VEXT.S16      D9, D9, D10, #1

+          VEXT.S16      D10, D10, D11, #1

+          VEXT.S16      D11, D11, D12, #1

+          VDUP.S16      D24, r12

+          VEXT.S16      D12, D12, D13, #1

+          VEXT.S16      D13, D13, D14, #1

+     

+          VQADD.S32     D30, D30, D31

+	  MOV           r11, #0x8000          

+          VPADD.S32     D30, D30, D30

+          ADD           r8, r8, #1

+          VMOV.S32      r12, D30[0]

+          VEXT.S16      D14, D14, D15, #1          

+

+          QADD          r1, r12, r12                              @ L_sum = (L_sum << 2)

+          VEXT.S16      D15, D15, D24, #1

+          QADD          r5, r1, r6                         

+          MOV           r1, r5, ASR #16

+          CMP           r8, r3

+          STRH          r1, [r0], #2                              @ exc[j] = (L_sum + 0x8000) >> 16

+          BLT           LOOP

+                    

+pred_lt4_end:

+		     

+          LDMFD   	r13!, {r4 - r12, r15} 

+ 

+Lable1:

+          .word   	inter4_2

+          @ENDFUNC

+          .END

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s
new file mode 100644
index 0000000..b9e6b23
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s
@@ -0,0 +1,127 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** 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.
+@ */
+@
+@void Residu (
+@    Word16 a[], /* (i)     : prediction coefficients                      */
+@    Word16 x[], /* (i)     : speech signal                                */
+@    Word16 y[], /* (o)     : residual signal                              */
+@    Word16 lg   /* (i)     : size of filtering                            */
+@)
+@a[]        RN     r0
+@x[]        RN     r1
+@y[]        RN     r2
+@lg         RN     r3
+
+	.section   .text
+        .global    Residu_opt 
+
+Residu_opt:
+
+        STMFD          r13!, {r4 - r12, r14} 
+        SUB            r7, r3, #4                       @i = lg - 4
+        
+        VLD1.S16       {D0, D1, D2, D3}, [r0]!              @get all a[]  
+	VLD1.S16       {D4}, [r0]!
+        VMOV.S32       Q8,  #0x8000
+        
+LOOP1:
+        ADD            r9, r1, r7, LSL #1               @copy the address
+        ADD            r10, r2, r7, LSL #1
+        MOV            r8, r9
+        VLD1.S16       D5, [r8]!                       @get x[i], x[i+1], x[i+2], x[i+3]
+        VQDMULL.S16    Q10, D5, D0[0]                  @finish the first L_mult
+
+        SUB            r8, r9, #2                       @get the x[i-1] address
+        VLD1.S16       D5, [r8]! 
+        VQDMLAL.S16    Q10, D5, D0[1]
+
+        SUB            r8, r9, #4                       @load the x[i-2] address
+        VLD1.S16       D5, [r8]!
+        VQDMLAL.S16    Q10, D5, D0[2]
+
+        SUB            r8, r9, #6                       @load the x[i-3] address
+        VLD1.S16       D5, [r8]!     
+        VQDMLAL.S16    Q10, D5, D0[3]                    
+
+        SUB            r8, r9, #8                       @load the x[i-4] address
+        VLD1.S16       D5, [r8]!     
+        VQDMLAL.S16    Q10, D5, D1[0]  
+
+        SUB            r8, r9, #10                      @load the x[i-5] address
+        VLD1.S16       D5, [r8]!     
+        VQDMLAL.S16    Q10, D5, D1[1] 
+
+        SUB            r8, r9, #12                      @load the x[i-6] address
+        VLD1.S16       D5, [r8]!     
+        VQDMLAL.S16    Q10, D5, D1[2]  
+
+        SUB            r8, r9, #14                      @load the x[i-7] address
+        VLD1.S16       D5, [r8]!     
+        VQDMLAL.S16    Q10, D5, D1[3]  
+
+        SUB            r8, r9, #16                      @load the x[i-8] address
+        VLD1.S16       D5, [r8]!     
+        VQDMLAL.S16    Q10, D5, D2[0]  
+
+        SUB            r8, r9, #18                      @load the x[i-9] address
+        VLD1.S16       D5, [r8]!     
+        VQDMLAL.S16    Q10, D5, D2[1]         
+           
+        SUB            r8, r9, #20                      @load the x[i-10] address
+        VLD1.S16       D5, [r8]!     
+        VQDMLAL.S16    Q10, D5, D2[2]  
+
+	SUB            r8, r9, #22                      @load the x[i-11] address
+	VLD1.S16       D5, [r8]!
+	VQDMLAL.S16    Q10, D5, D2[3]
+
+	SUB            r8, r9, #24                      @load the x[i-12] address
+	VLD1.S16       D5, [r8]!
+	VQDMLAL.S16    Q10, D5, D3[0]
+
+	SUB            r8, r9, #26                      @load the x[i-13] address
+	VLD1.S16       D5, [r8]!
+	VQDMLAL.S16    Q10, D5, D3[1]
+
+	SUB            r8, r9, #28                      @load the x[i-14] address
+	VLD1.S16       D5, [r8]!
+	VQDMLAL.S16    Q10, D5, D3[2]
+
+	SUB            r8, r9, #30                      @load the x[i-15] address
+	VLD1.S16       D5, [r8]!
+	VQDMLAL.S16    Q10, D5, D3[3]
+
+	SUB            r8, r9, #32                      @load the x[i-16] address
+	VLD1.S16       D5, [r8]!
+	VQDMLAL.S16    Q10, D5, D4[0]
+
+        SUB            r7, r7, #4                       @i-=4
+        VQSHL.S32      Q10, Q10, #4
+        VQADD.S32      Q10, Q10, Q8
+        VSHRN.S32      D5, Q10, #16
+        VST1.S16       D5, [r10]!
+        CMP            r7,  #0
+
+        BGE            LOOP1
+
+Residu_asm_end: 
+ 
+        LDMFD      r13!, {r4 - r12, r15}
+    
+        @ENDFUNC
+        .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s
new file mode 100644
index 0000000..14957d8
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s
@@ -0,0 +1,138 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@                   

+@**********************************************************************/

+@void Scale_sig(

+@               Word16 x[],                           /* (i/o) : signal to scale               */

+@               Word16 lg,                            /* (i)   : size of x[]                   */

+@               Word16 exp                            /* (i)   : exponent: x = round(x << exp) */

+@)

+@***********************************************************************

+@  x[]   ---  r0

+@  lg    ---  r1

+@  exp   ---  r2

+

+          .section  .text 

+          .global   Scale_sig_opt

+

+Scale_sig_opt:

+

+          STMFD   	r13!, {r4 - r12, r14} 

+          MOV           r4, #4

+          VMOV.S32      Q15, #0x8000       

+          VDUP.S32      Q14, r2  

+          MOV           r5, r0                          @ copy x[] address    

+          CMP           r1, #64

+          MOVEQ         r4, #1

+          BEQ           LOOP

+	  CMP           r1, #128

+	  MOVEQ         r4, #2

+	  BEQ           LOOP

+          CMP           r1, #256

+          BEQ           LOOP

+	  CMP           r1, #80

+	  MOVEQ         r4, #1

+	  BEQ           LOOP1

+

+LOOP1:

+          VLD1.S16      {Q0, Q1}, [r5]!                 @load 16 Word16 x[]     

+          VSHLL.S16     Q10, D0, #16

+          VSHLL.S16     Q11, D1, #16

+          VSHLL.S16     Q12, D2, #16

+          VSHLL.S16     Q13, D3, #16

+          VSHL.S32      Q10, Q10, Q14

+          VSHL.S32      Q11, Q11, Q14

+          VSHL.S32      Q12, Q12, Q14

+          VSHL.S32      Q13, Q13, Q14

+          VADDHN.S32    D16, Q10, Q15

+          VADDHN.S32    D17, Q11, Q15

+          VADDHN.S32    D18, Q12, Q15

+          VADDHN.S32    D19, Q13, Q15

+          VST1.S16      {Q8, Q9}, [r0]!                 @store 16 Word16 x[]

+

+LOOP:                

+          VLD1.S16      {Q0, Q1}, [r5]!                 @load 16 Word16 x[]

+          VLD1.S16      {Q2, Q3}, [r5]!                 @load 16 Word16 x[]

+          VLD1.S16      {Q4, Q5}, [r5]!                 @load 16 Word16 x[]

+          VLD1.S16      {Q6, Q7}, [r5]!                 @load 16 Word16 x[]

+

+          VSHLL.S16     Q8, D0, #16

+          VSHLL.S16     Q9, D1, #16

+          VSHLL.S16     Q10, D2, #16

+          VSHLL.S16     Q11, D3, #16     

+          VSHL.S32      Q8, Q8, Q14

+          VSHL.S32      Q9, Q9, Q14

+          VSHL.S32      Q10, Q10, Q14

+          VSHL.S32      Q11, Q11, Q14

+          VADDHN.S32    D16, Q8, Q15

+          VADDHN.S32    D17, Q9, Q15

+          VADDHN.S32    D18, Q10, Q15

+          VADDHN.S32    D19, Q11, Q15

+          VST1.S16      {Q8, Q9}, [r0]!                 @store 16 Word16 x[]

+

+   

+          VSHLL.S16     Q12, D4, #16

+          VSHLL.S16     Q13, D5, #16

+          VSHLL.S16     Q10, D6, #16

+          VSHLL.S16     Q11, D7, #16

+          VSHL.S32      Q12, Q12, Q14

+          VSHL.S32      Q13, Q13, Q14

+          VSHL.S32      Q10, Q10, Q14

+          VSHL.S32      Q11, Q11, Q14

+          VADDHN.S32    D16, Q12, Q15

+          VADDHN.S32    D17, Q13, Q15

+          VADDHN.S32    D18, Q10, Q15

+          VADDHN.S32    D19, Q11, Q15

+          VST1.S16      {Q8, Q9}, [r0]!                 @store 16 Word16 x[]

+

+          VSHLL.S16     Q10, D8, #16

+          VSHLL.S16     Q11, D9, #16

+          VSHLL.S16     Q12, D10, #16

+          VSHLL.S16     Q13, D11, #16

+          VSHL.S32      Q10, Q10, Q14

+          VSHL.S32      Q11, Q11, Q14

+          VSHL.S32      Q12, Q12, Q14

+          VSHL.S32      Q13, Q13, Q14

+          VADDHN.S32    D16, Q10, Q15

+          VADDHN.S32    D17, Q11, Q15

+          VADDHN.S32    D18, Q12, Q15

+          VADDHN.S32    D19, Q13, Q15

+          VST1.S16      {Q8, Q9}, [r0]!                 @store 16 Word16 x[]

+

+          VSHLL.S16     Q10, D12, #16   

+          VSHLL.S16     Q11, D13, #16

+          VSHLL.S16     Q12, D14, #16

+          VSHLL.S16     Q13, D15, #16

+          VSHL.S32      Q10, Q10, Q14

+          VSHL.S32      Q11, Q11, Q14

+          VSHL.S32      Q12, Q12, Q14

+          VSHL.S32      Q13, Q13, Q14

+          VADDHN.S32    D16, Q10, Q15

+          VADDHN.S32    D17, Q11, Q15

+          VADDHN.S32    D18, Q12, Q15

+          VADDHN.S32    D19, Q13, Q15 

+          VST1.S16      {Q8, Q9}, [r0]!                 @store 16 Word16 x[]  

+          SUBS          r4, r4, #1

+          BGT           LOOP     

+                

+                          

+Scale_sig_asm_end:

+

+          LDMFD   	r13!, {r4 - r12, r15} 

+          @ENDFUNC

+          .END

+ 

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s
new file mode 100644
index 0000000..dc3d4a8
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s
@@ -0,0 +1,106 @@
+@/*

+@ ** Copyright 2003-2010, VisualOn, Inc.

+@ **

+@ ** 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.

+@ */

+@

+@void Syn_filt(

+@     Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients           */

+@     Word16 x[],                           /* (i)     : input signal                             */

+@     Word16 y[],                           /* (o)     : output signal                            */

+@     Word16 mem[],                         /* (i/o)   : memory associated with this filtering.   */

+@)

+@***********************************************************************

+@ a[]    ---   r0

+@ x[]    ---   r1

+@ y[]    ---   r2

+@ mem[]  ---   r3

+@ m ---  16  lg --- 80  update --- 1

+

+          .section  .text 

+          .global   Syn_filt_asm

+

+Syn_filt_asm:

+

+          STMFD   	r13!, {r4 - r12, r14} 

+          SUB           r13, r13, #700                   @ y_buf[L_FRAME16k + M16k]

+   

+          MOV           r4, r3                           @ copy mem[] address

+          MOV           r5, r13                          @ copy yy = y_buf address

+

+          @ for(i = 0@ i < m@ i++)

+          @{

+          @    *yy++ = mem[i]@

+          @} 

+          VLD1.S16      {D0, D1, D2, D3}, [r4]!          @load 16 mems

+	  VST1.S16      {D0, D1, D2, D3}, [r5]!          @store 16 mem[] to *yy

+

+          LDRSH         r5, [r0], #2                     @ load a[0]

+          MOV           r8, #0                           @ i = 0

+          MOV           r5, r5, ASR #1                   @ a0 = a[0] >> 1

+          VMOV.S16      D8[0], r5

+          @ load all a[]

+          VLD1.S16      {D0, D1, D2, D3}, [r0]!          @ load a[1] ~ a[16]

+	  VREV64.16     D0, D0

+	  VREV64.16     D1, D1

+	  VREV64.16     D2, D2

+	  VREV64.16     D3, D3 

+	  MOV           r8, #0                           @ loop times

+	  MOV           r10, r13                         @ temp = y_buf

+	  ADD           r4, r13, #32                     @ yy[i] address

+

+          VLD1.S16      {D4, D5, D6, D7}, [r10]!         @ first 16 temp_p

+

+SYN_LOOP:

+

+          LDRSH         r6, [r1], #2                     @ load x[i]

+	  MUL           r12, r6, r5                      @ L_tmp = x[i] * a0

+	  ADD           r10, r4, r8, LSL #1              @ y[i], yy[i] address

+

+	  VDUP.S32      Q10, r12

+	  VMULL.S16     Q5, D3, D4                    

+          VMLAL.S16     Q5, D2, D5

+          VMLAL.S16     Q5, D1, D6

+          VMLAL.S16     Q5, D0, D7

+          VEXT.8        D4, D4, D5, #2

+          VEXT.8        D5, D5, D6, #2

+          VEXT.8        D6, D6, D7, #2

+          VPADD.S32     D12, D10, D11

+          ADD           r8, r8, #1

+          VPADD.S32     D10, D12, D12

+

+	  VDUP.S32      Q7, D10[0]

+

+	  VSUB.S32      Q9, Q10, Q7

+          VQRSHRN.S32   D20, Q9, #12   

+          VMOV.S16      r9, D20[0]

+          VEXT.8        D7, D7, D20, #2

+          CMP           r8, #80

+          STRH          r9, [r10]                        @ yy[i]

+          STRH          r9, [r2], #2                     @ y[i]          	         

+	  

+          BLT           SYN_LOOP

+ 

+          @ update mem[]

+          ADD           r5, r13, #160                    @ yy[64] address

+	  VLD1.S16      {D0, D1, D2, D3}, [r5]!

+	  VST1.S16      {D0, D1, D2, D3}, [r3]!              

+

+Syn_filt_asm_end:

+ 

+          ADD           r13, r13, #700		     

+          LDMFD   	r13!, {r4 - r12, r15} 

+          @ENDFUNC

+          .END

+ 

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/autocorr.c b/media/libstagefright/codecs/amrwbenc/src/autocorr.c
new file mode 100644
index 0000000..33ed670
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/autocorr.c
@@ -0,0 +1,127 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+

+/***********************************************************************

+*       File: autocorr.c                                               *

+*                                                                      *

+*       Description:Compute autocorrelations of signal with windowing  *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "acelp.h"

+#include "ham_wind.tab"

+

+void Autocorr(

+		Word16 x[],                           /* (i)    : Input signal                      */

+		Word16 m,                             /* (i)    : LPC order                         */

+		Word16 r_h[],                         /* (o) Q15: Autocorrelations  (msb)           */

+		Word16 r_l[]                          /* (o)    : Autocorrelations  (lsb)           */

+	     )

+{

+	Word32 i, norm, shift;

+	Word16 y[L_WINDOW];

+	Word32 L_sum, L_sum1, L_tmp, F_LEN;

+	Word16 *p1,*p2,*p3;

+	const Word16 *p4;

+	/* Windowing of signal */

+	p1 = x;

+	p4 = vo_window;

+	p3 = y;

+

+	for (i = 0; i < L_WINDOW; i+=4)

+	{

+		*p3++ = vo_mult_r((*p1++), (*p4++));

+		*p3++ = vo_mult_r((*p1++), (*p4++));

+		*p3++ = vo_mult_r((*p1++), (*p4++));

+		*p3++ = vo_mult_r((*p1++), (*p4++));

+	}

+

+	/* calculate energy of signal */

+	L_sum = vo_L_deposit_h(16);               /* sqrt(256), avoid overflow after rounding */

+	for (i = 0; i < L_WINDOW; i++)

+	{

+		L_tmp = vo_L_mult(y[i], y[i]);

+		L_tmp = (L_tmp >> 8);

+		L_sum += L_tmp;

+	}

+

+	/* scale signal to avoid overflow in autocorrelation */

+	norm = norm_l(L_sum);

+	shift = 4 - (norm >> 1);

+	if(shift > 0)

+	{

+		p1 = y;

+		for (i = 0; i < L_WINDOW; i+=4)

+		{

+			*p1 = vo_shr_r(*p1, shift); 

+			p1++;

+			*p1 = vo_shr_r(*p1, shift); 

+			p1++;

+			*p1 = vo_shr_r(*p1, shift);

+			p1++;

+			*p1 = vo_shr_r(*p1, shift); 

+			p1++;

+		}

+	}

+

+	/* Compute and normalize r[0] */

+	L_sum = 1; 

+	for (i = 0; i < L_WINDOW; i+=4)

+	{

+		L_sum += vo_L_mult(y[i], y[i]);

+		L_sum += vo_L_mult(y[i+1], y[i+1]);

+		L_sum += vo_L_mult(y[i+2], y[i+2]);

+		L_sum += vo_L_mult(y[i+3], y[i+3]);

+	}

+

+	norm = norm_l(L_sum);

+	L_sum = (L_sum << norm);

+

+	r_h[0] = L_sum >> 16;

+	r_l[0] = (L_sum & 0xffff)>>1;

+

+	/* Compute r[1] to r[m] */

+	for (i = 1; i <= 8; i++)

+	{

+		L_sum1 = 0;

+		L_sum = 0;

+		F_LEN = (Word32)(L_WINDOW - 2*i);

+		p1 = y;

+		p2 = y + (2*i)-1;

+		do{

+			L_sum1 += *p1 * *p2++;

+			L_sum += *p1++ * *p2;

+		}while(--F_LEN!=0);

+

+		L_sum1 += *p1 * *p2++;

+

+		L_sum1 = L_sum1<<norm;

+		L_sum = L_sum<<norm;

+

+		r_h[(2*i)-1] = L_sum1 >> 15;

+		r_l[(2*i)-1] = L_sum1 & 0x00007fff;

+		r_h[(2*i)] = L_sum >> 15;

+		r_l[(2*i)] = L_sum & 0x00007fff;

+	}

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/az_isp.c b/media/libstagefright/codecs/amrwbenc/src/az_isp.c
new file mode 100644
index 0000000..8259f91
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/az_isp.c
@@ -0,0 +1,268 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*  File: az_isp.c

+*

+*  Description:

+*-----------------------------------------------------------------------*

+* Compute the ISPs from  the LPC coefficients  (order=M)                *

+*-----------------------------------------------------------------------*

+*                                                                       *

+* The ISPs are the roots of the two polynomials F1(z) and F2(z)         *

+* defined as                                                            *

+*               F1(z) = A(z) + z^-m A(z^-1)                             *

+*  and          F2(z) = A(z) - z^-m A(z^-1)                             *

+*                                                                       *

+* For a even order m=2n, F1(z) has M/2 conjugate roots on the unit      *

+* circle and F2(z) has M/2-1 conjugate roots on the unit circle in      *

+* addition to two roots at 0 and pi.                                    *

+*                                                                       *

+* For a 16th order LP analysis, F1(z) and F2(z) can be written as       *

+*                                                                       *

+*   F1(z) = (1 + a[M])   PRODUCT  (1 - 2 cos(w_i) z^-1 + z^-2 )         *

+*                        i=0,2,4,6,8,10,12,14                           *

+*                                                                       *

+*   F2(z) = (1 - a[M]) (1 - z^-2) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) *

+*                                 i=1,3,5,7,9,11,13                     *

+*                                                                       *

+* The ISPs are the M-1 frequencies w_i, i=0...M-2 plus the last         *

+* predictor coefficient a[M].                                           *

+*-----------------------------------------------------------------------*

+

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "stdio.h"

+#include "grid100.tab"

+

+#define M   16

+#define NC  (M/2)

+

+/* local function */

+static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n);

+

+void Az_isp(

+		Word16 a[],                           /* (i) Q12 : predictor coefficients                 */

+		Word16 isp[],                         /* (o) Q15 : Immittance spectral pairs              */

+		Word16 old_isp[]                      /* (i)     : old isp[] (in case not found M roots)  */

+	   )

+{

+	Word32 i, j, nf, ip, order;

+	Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint;

+	Word16 x, y, sign, exp;

+	Word16 *coef;

+	Word16 f1[NC + 1], f2[NC];

+	Word32 t0;

+	/*-------------------------------------------------------------*

+	 * find the sum and diff polynomials F1(z) and F2(z)           *

+	 *      F1(z) = [A(z) + z^M A(z^-1)]                           *

+	 *      F2(z) = [A(z) - z^M A(z^-1)]/(1-z^-2)                  *

+	 *                                                             *

+	 * for (i=0; i<NC; i++)                                        *

+	 * {                                                           *

+	 *   f1[i] = a[i] + a[M-i];                                    *

+	 *   f2[i] = a[i] - a[M-i];                                    *

+	 * }                                                           *

+	 * f1[NC] = 2.0*a[NC];                                         *

+	 *                                                             *

+	 * for (i=2; i<NC; i++)            Divide by (1-z^-2)          *

+	 *   f2[i] += f2[i-2];                                         *

+	 *-------------------------------------------------------------*/

+	for (i = 0; i < NC; i++)

+	{

+		t0 = a[i] << 15;

+		f1[i] = vo_round(t0 + (a[M - i] << 15));        /* =(a[i]+a[M-i])/2 */

+		f2[i] = vo_round(t0 - (a[M - i] << 15));        /* =(a[i]-a[M-i])/2 */

+	}

+	f1[NC] = a[NC];                        

+	for (i = 2; i < NC; i++)               /* Divide by (1-z^-2) */

+		f2[i] = add1(f2[i], f2[i - 2]);     

+

+	/*---------------------------------------------------------------------*

+	 * Find the ISPs (roots of F1(z) and F2(z) ) using the                 *

+	 * Chebyshev polynomial evaluation.                                    *

+	 * The roots of F1(z) and F2(z) are alternatively searched.            *

+	 * We start by finding the first root of F1(z) then we switch          *

+	 * to F2(z) then back to F1(z) and so on until all roots are found.    *

+	 *                                                                     *

+	 *  - Evaluate Chebyshev pol. at grid points and check for sign change.*

+	 *  - If sign change track the root by subdividing the interval        *

+	 *    2 times and ckecking sign change.                                *

+	 *---------------------------------------------------------------------*/

+	nf = 0;                                  /* number of found frequencies */

+	ip = 0;                                  /* indicator for f1 or f2      */

+	coef = f1;                             

+	order = NC;                            

+	xlow = vogrid[0];                        

+	ylow = Chebps2(xlow, coef, order);

+	j = 0;

+	while ((nf < M - 1) && (j < GRID_POINTS))

+	{

+		j ++;

+		xhigh = xlow;                     

+		yhigh = ylow;                      

+		xlow = vogrid[j];                    

+		ylow = Chebps2(xlow, coef, order);

+		if ((ylow * yhigh) <= (Word32) 0)

+		{

+			/* divide 2 times the interval */

+			for (i = 0; i < 2; i++)

+			{

+				xmid = (xlow >> 1) + (xhigh >> 1);        /* xmid = (xlow + xhigh)/2 */

+				ymid = Chebps2(xmid, coef, order);

+				if ((ylow * ymid) <= (Word32) 0)

+				{

+					yhigh = ymid;         

+					xhigh = xmid;          

+				} else

+				{

+					ylow = ymid;           

+					xlow = xmid;          

+				}

+			}

+			/*-------------------------------------------------------------*

+			 * Linear interpolation                                        *

+			 *    xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow);            *

+			 *-------------------------------------------------------------*/

+			x = xhigh - xlow;

+			y = yhigh - ylow;

+			if (y == 0)

+			{

+				xint = xlow;               

+			} else

+			{

+				sign = y;                 

+				y = abs_s(y);

+				exp = norm_s(y);

+				y = y << exp;

+				y = div_s((Word16) 16383, y);

+				t0 = x * y;

+				t0 = (t0 >> (19 - exp));

+				y = vo_extract_l(t0);         /* y= (xhigh-xlow)/(yhigh-ylow) in Q11 */

+				if (sign < 0)

+					y = -y;

+				t0 = ylow * y;      /* result in Q26 */

+				t0 = (t0 >> 10);        /* result in Q15 */

+				xint = vo_sub(xlow, vo_extract_l(t0));        /* xint = xlow - ylow*y */

+			}

+			isp[nf] = xint;                

+			xlow = xint;                   

+			nf++;                          

+			if (ip == 0)

+			{

+				ip = 1;                    

+				coef = f2;                

+				order = NC - 1;           

+			} else

+			{

+				ip = 0;                   

+				coef = f1;                 

+				order = NC;              

+			}

+			ylow = Chebps2(xlow, coef, order);

+		}

+	}

+	/* Check if M-1 roots found */

+	if(nf < M - 1)

+	{

+		for (i = 0; i < M; i++)

+		{

+			isp[i] = old_isp[i];          

+		}

+	} else

+	{

+		isp[M - 1] = a[M] << 3;                      /* From Q12 to Q15 with saturation */

+	}

+	return;

+}

+

+/*--------------------------------------------------------------*

+* function  Chebps2:                                           *

+*           ~~~~~~~                                            *

+*    Evaluates the Chebishev polynomial series                 *

+*--------------------------------------------------------------*

+*                                                              *

+*  The polynomial order is                                     *

+*     n = M/2   (M is the prediction order)                    *

+*  The polynomial is given by                                  *

+*    C(x) = f(0)T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2 *

+* Arguments:                                                   *

+*  x:     input value of evaluation; x = cos(frequency) in Q15 *

+*  f[]:   coefficients of the pol.                      in Q11 *

+*  n:     order of the pol.                                    *

+*                                                              *

+* The value of C(x) is returned. (Satured to +-1.99 in Q14)    *

+*                                                              *

+*--------------------------------------------------------------*/

+

+static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n)

+{

+	Word32 i, cheb;

+	Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l;

+	Word32 t0;

+

+	/* Note: All computation are done in Q24. */

+

+	t0 = f[0] << 13;

+	b2_h = t0 >> 16;

+	b2_l = (t0 & 0xffff)>>1;

+

+	t0 = ((b2_h * x)<<1) + (((b2_l * x)>>15)<<1);

+	t0 <<= 1;

+	t0 += (f[1] << 13);						/* + f[1] in Q24        */

+

+	b1_h = t0 >> 16;

+	b1_l = (t0 & 0xffff) >> 1;

+

+	for (i = 2; i < n; i++)

+	{

+		t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1);

+

+		t0 += (b2_h * (-16384))<<1;

+		t0 += (f[i] << 12);

+		t0 <<= 1;

+		t0 -= (b2_l << 1);					/* t0 = 2.0*x*b1 - b2 + f[i]; */

+

+		b0_h = t0 >> 16;

+		b0_l = (t0 & 0xffff) >> 1;

+

+		b2_l = b1_l;                         /* b2 = b1; */

+		b2_h = b1_h;                       

+		b1_l = b0_l;                         /* b1 = b0; */

+		b1_h = b0_h;                       

+	}

+

+	t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1);

+	t0 += (b2_h * (-32768))<<1;				/* t0 = x*b1 - b2          */

+	t0 -= (b2_l << 1);

+	t0 += (f[n] << 12);						/* t0 = x*b1 - b2 + f[i]/2 */

+

+	t0 = L_shl2(t0, 6);                     /* Q24 to Q30 with saturation */

+

+	cheb = extract_h(t0);                  /* Result in Q14              */

+

+	if (cheb == -32768)

+	{

+		cheb = -32767;                     /* to avoid saturation in Az_isp */

+	}

+	return (cheb);

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/bits.c b/media/libstagefright/codecs/amrwbenc/src/bits.c
new file mode 100644
index 0000000..90d1a00
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/bits.c
@@ -0,0 +1,210 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+       File: bits.c

+

+	   Description: Performs bit stream manipulation

+

+************************************************************************/

+

+#include <stdlib.h>

+#include <stdio.h>

+#include "typedef.h"

+#include "basic_op.h"

+#include "cnst.h"

+#include "bits.h"

+#include "acelp.h"

+#include "dtx.h"

+#include "mime_io.tab"

+

+

+int PackBits(Word16 prms[],             /*  i: analysis parameters */

+			 Word16 coding_mode,        /*  i: coding bit-stream ratio mode */

+			 Word16 mode,               /*  i: coding bit-stream ratio mode*/ 

+			 Coder_State *st            /*i/o: coder global parameters struct */           

+			 )

+{

+	Word16 i, frame_type;

+	UWord8 temp;

+	UWord8 *stream_ptr;

+	Word16 bitstreamformat = st->frameType;

+

+	unsigned short* dataOut = st->outputStream;

+

+	if (coding_mode == MRDTX)

+	{	   

+		st->sid_update_counter--;

+

+		if (st->prev_ft == TX_SPEECH)

+		{

+			frame_type = TX_SID_FIRST;

+			st->sid_update_counter = 3;

+		} else

+		{

+			if ((st->sid_handover_debt > 0) && (st->sid_update_counter > 2))

+			{

+				/* ensure extra updates are  properly delayed after a possible SID_FIRST */

+				frame_type = TX_SID_UPDATE;

+				st->sid_handover_debt--;

+			} else

+			{

+				if (st->sid_update_counter == 0)

+				{

+					frame_type = TX_SID_UPDATE;

+					st->sid_update_counter = 8;

+				} else

+				{

+					frame_type = TX_NO_DATA;

+				}

+			}

+		}

+	} else

+	{

+		st->sid_update_counter = 8;

+		frame_type = TX_SPEECH;

+	}

+	st->prev_ft = frame_type;

+

+	if(bitstreamformat == 0)				/* default file format */

+	{

+		*(dataOut) = TX_FRAME_TYPE;

+		*(dataOut + 1) = frame_type;

+		*(dataOut + 2) = mode;

+		for (i = 0; i < nb_of_bits[coding_mode]; i++)

+		{

+			*(dataOut + 3 + i) = prms[i];

+		}

+		return  (3 + nb_of_bits[coding_mode])<<1;

+	} else

+	{

+		if (bitstreamformat == 1)		/* ITU file format */

+		{  						

+			*(dataOut) = 0x6b21;

+			if(frame_type != TX_NO_DATA && frame_type != TX_SID_FIRST)

+			{

+				*(dataOut + 1) = nb_of_bits[coding_mode];

+				for (i = 0; i < nb_of_bits[coding_mode]; i++)

+				{

+					if(prms[i] == BIT_0){

+						*(dataOut + 2 + i) = BIT_0_ITU;	 			

+					}

+					else{

+						*(dataOut + 2 + i) = BIT_1_ITU;

+					}

+				}

+				return (2 + nb_of_bits[coding_mode])<<1;   

+			} else

+			{

+				*(dataOut + 1) = 0;

+				return 2<<1;	   

+			}

+		} else							/* MIME/storage file format */

+		{

+#define MRSID 9

+			/* change mode index in case of SID frame */

+			if (coding_mode == MRDTX)

+			{

+				coding_mode = MRSID;

+				if (frame_type == TX_SID_FIRST)

+				{

+					for (i = 0; i < NBBITS_SID; i++)	prms[i] = BIT_0;

+				}

+			}

+			/* -> force NO_DATA frame */

+			if (coding_mode < 0 || coding_mode > 15 || (coding_mode > MRSID && coding_mode < 14))

+			{

+				coding_mode = 15;

+			}

+			/* mark empty frames between SID updates as NO_DATA frames */

+			if (coding_mode == MRSID && frame_type == TX_NO_DATA)

+			{

+				coding_mode = 15;

+			}

+			/* set pointer for packed frame, note that we handle data as bytes */

+			stream_ptr = (UWord8*)dataOut;

+			/* insert table of contents (ToC) byte at the beginning of the packet */

+			*stream_ptr = toc_byte[coding_mode];

+			stream_ptr++;

+			temp = 0;

+			/* sort and pack AMR-WB speech or SID bits */

+			for (i = 1; i < unpacked_size[coding_mode] + 1; i++)

+			{

+				if (prms[sort_ptr[coding_mode][i-1]] == BIT_1)

+				{

+					temp++;

+				}

+				if (i&0x7)

+				{

+					temp <<= 1;

+				}

+				else

+				{

+					*stream_ptr = temp;

+					stream_ptr++;

+					temp = 0;

+				}

+			}

+			/* insert SID type indication and speech mode in case of SID frame */

+			if (coding_mode == MRSID)

+			{

+				if (frame_type == TX_SID_UPDATE)

+				{

+					temp++;

+				}

+				temp <<= 4;

+				temp += mode & 0x000F;

+			}

+			/* insert unused bits (zeros) at the tail of the last byte */

+			if (unused_size[coding_mode])

+			{

+				temp <<= (unused_size[coding_mode] - 1);

+			}

+			*stream_ptr = temp;

+			/* write packed frame into file (1 byte added to cover ToC entry) */

+			return (1 + packed_size[coding_mode]);

+		}

+	}

+}

+

+/*-----------------------------------------------------*

+* Parm_serial -> convert parameters to serial stream  *

+*-----------------------------------------------------*/

+

+void Parm_serial(

+		Word16 value,                         /* input : parameter value */

+		Word16 no_of_bits,                    /* input : number of bits  */

+		Word16 ** prms

+		)

+{

+	Word16 i, bit;

+	*prms += no_of_bits;                  

+	for (i = 0; i < no_of_bits; i++)

+	{

+		bit = (Word16) (value & 0x0001);    /* get lsb */

+		if (bit == 0)

+			*--(*prms) = BIT_0;

+		else

+			*--(*prms) = BIT_1;

+		value >>= 1;          

+	}

+	*prms += no_of_bits;                  

+	return;

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c
new file mode 100644
index 0000000..39fc4c5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c
@@ -0,0 +1,297 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/************************************************************************

+*      File: c2t64fx.c                                                  *

+*                                                                       *

+*	   Description:Performs algebraic codebook search for 6.60kbits mode*

+*                                                                       *

+*************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+#include "acelp.h"

+#include "cnst.h"

+

+#define NB_TRACK  2

+#define STEP      2

+#define NB_POS    32

+#define MSIZE     1024

+

+/*************************************************************************

+* Function:  ACELP_2t64_fx()                                             *

+*                                                                        *

+* 12 bits algebraic codebook.                                            *

+* 2 tracks x 32 positions per track = 64 samples.                        *

+*                                                                        *

+* 12 bits --> 2 pulses in a frame of 64 samples.                         *

+*                                                                        *

+* All pulses can have two (2) possible amplitudes: +1 or -1.             *

+* Each pulse can have 32 possible positions.                             *

+**************************************************************************/

+

+void ACELP_2t64_fx(

+		Word16 dn[],                          /* (i) <12b : correlation between target x[] and H[]      */

+		Word16 cn[],                          /* (i) <12b : residual after long term prediction         */

+		Word16 H[],                           /* (i) Q12: impulse response of weighted synthesis filter */

+		Word16 code[],                        /* (o) Q9 : algebraic (fixed) codebook excitation         */

+		Word16 y[],                           /* (o) Q9 : filtered fixed codebook excitation            */

+		Word16 * index                        /* (o) : index (12): 5+1+5+1 = 11 bits.                   */

+		)

+{

+	Word32 i, j, k, i0, i1, ix, iy, pos, pos2;

+	Word16 ps, psk, ps1, ps2, alpk, alp1, alp2, sq;

+	Word16 alp, val, exp, k_cn, k_dn;

+	Word16 *p0, *p1, *p2, *psign;

+	Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf;

+

+	Word16 sign[L_SUBFR], vec[L_SUBFR], dn2[L_SUBFR];

+	Word16 h_buf[4 * L_SUBFR] = {0};

+	Word16 rrixix[NB_TRACK][NB_POS];

+	Word16 rrixiy[MSIZE];

+	Word32 s, cor;

+

+	/*----------------------------------------------------------------*

+	 * Find sign for each pulse position.                             *

+	 *----------------------------------------------------------------*/

+	alp = 8192;                              /* alp = 2.0 (Q12) */

+

+	/* calculate energy for normalization of cn[] and dn[] */

+	/* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */

+#ifdef ASM_OPT             /* asm optimization branch */

+	s = Dot_product12_asm(cn, cn, L_SUBFR, &exp);

+#else

+	s = Dot_product12(cn, cn, L_SUBFR, &exp);

+#endif

+

+	Isqrt_n(&s, &exp);

+	s = L_shl(s, add1(exp, 5));             

+	k_cn = vo_round(s);

+

+	/* set k_dn = 32..512 (ener_dn = 2^30..2^22) */

+#ifdef ASM_OPT                  /* asm optimization branch */

+	s = Dot_product12_asm(dn, dn, L_SUBFR, &exp);

+#else

+	s = Dot_product12(dn, dn, L_SUBFR, &exp);

+#endif

+

+	Isqrt_n(&s, &exp);

+	k_dn = vo_round(L_shl(s, (exp + 8)));    /* k_dn = 256..4096 */

+	k_dn = vo_mult_r(alp, k_dn);              /* alp in Q12 */

+

+	/* mix normalized cn[] and dn[] */

+	p0 = cn;

+	p1 = dn;

+	p2 = dn2;

+

+	for (i = 0; i < L_SUBFR/4; i++)

+	{

+		s = (k_cn* (*p0++))+(k_dn * (*p1++));

+		*p2++ = s >> 7;

+		s = (k_cn* (*p0++))+(k_dn * (*p1++));

+		*p2++ = s >> 7;

+		s = (k_cn* (*p0++))+(k_dn * (*p1++));

+		*p2++ = s >> 7;

+		s = (k_cn* (*p0++))+(k_dn * (*p1++));

+		*p2++ = s >> 7; 

+	}

+

+	/* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[]    */

+	for (i = 0; i < L_SUBFR; i ++)

+	{

+		val = dn[i];                   

+		ps = dn2[i];                   

+		if (ps >= 0)

+		{

+			sign[i] = 32767;             /* sign = +1 (Q12) */

+			vec[i] = -32768;           

+		} else

+		{

+			sign[i] = -32768;            /* sign = -1 (Q12) */

+			vec[i] = 32767;            

+			dn[i] = -val;

+		}

+	}

+	/*------------------------------------------------------------*

+	 * Compute h_inv[i].                                          *

+	 *------------------------------------------------------------*/

+	/* impulse response buffer for fast computation */

+	h = h_buf + L_SUBFR;                             

+	h_inv = h + (L_SUBFR<<1);         

+

+	for (i = 0; i < L_SUBFR; i++)

+	{

+		h[i] = H[i];                       

+		h_inv[i] = vo_negate(h[i]);           

+	}

+

+	/*------------------------------------------------------------*

+	 * Compute rrixix[][] needed for the codebook search.         *

+	 * Result is multiplied by 0.5                                *

+	 *------------------------------------------------------------*/

+	/* Init pointers to last position of rrixix[] */

+	p0 = &rrixix[0][NB_POS - 1];           

+	p1 = &rrixix[1][NB_POS - 1];           

+

+	ptr_h1 = h;                            

+	cor = 0x00010000L;                          /* for rounding */

+	for (i = 0; i < NB_POS; i++)

+	{

+		cor += ((*ptr_h1) * (*ptr_h1) << 1);

+		ptr_h1++;

+		*p1-- = (extract_h(cor) >> 1);            

+		cor += ((*ptr_h1) * (*ptr_h1) << 1);

+		ptr_h1++;

+		*p0-- = (extract_h(cor) >> 1);            

+	}

+

+	/*------------------------------------------------------------*

+	 * Compute rrixiy[][] needed for the codebook search.         *

+	 *------------------------------------------------------------*/

+	pos = MSIZE - 1;                       

+	pos2 = MSIZE - 2;                      

+	ptr_hf = h + 1;                        

+

+	for (k = 0; k < NB_POS; k++)

+	{

+		p1 = &rrixiy[pos];                 

+		p0 = &rrixiy[pos2];                

+		cor = 0x00008000L;                        /* for rounding */

+		ptr_h1 = h;                        

+		ptr_h2 = ptr_hf;                   

+

+		for (i = (k + 1); i < NB_POS; i++)

+		{

+			cor += ((*ptr_h1) * (*ptr_h2))<<1;

+			ptr_h1++;

+			ptr_h2++;

+			*p1 = extract_h(cor);          

+			cor += ((*ptr_h1) * (*ptr_h2))<<1;

+			ptr_h1++;

+			ptr_h2++;

+			*p0 = extract_h(cor);         

+

+			p1 -= (NB_POS + 1);

+			p0 -= (NB_POS + 1);

+		}

+		cor += ((*ptr_h1) * (*ptr_h2))<<1;

+		ptr_h1++;

+		ptr_h2++;

+		*p1 = extract_h(cor);              

+

+		pos -= NB_POS;

+		pos2--;

+		ptr_hf += STEP;

+	}

+

+	/*------------------------------------------------------------*

+	 * Modification of rrixiy[][] to take signs into account.     *

+	 *------------------------------------------------------------*/

+	p0 = rrixiy;                          

+	for (i = 0; i < L_SUBFR; i += STEP)

+	{

+		psign = sign;                      

+		if (psign[i] < 0)

+		{

+			psign = vec;                   

+		}

+		for (j = 1; j < L_SUBFR; j += STEP)

+		{

+			*p0 = vo_mult(*p0, psign[j]);     

+			p0++;

+		}

+	}

+	/*-------------------------------------------------------------------*

+	 * search 2 pulses:                                                  *

+	 * ~@~~~~~~~~~~~~~~                                                  *

+	 * 32 pos x 32 pos = 1024 tests (all combinaisons is tested)         *

+	 *-------------------------------------------------------------------*/

+	p0 = rrixix[0];                        

+	p1 = rrixix[1];                        

+	p2 = rrixiy;                          

+

+	psk = -1;                              

+	alpk = 1;                              

+	ix = 0;                                

+	iy = 1;                                

+

+	for (i0 = 0; i0 < L_SUBFR; i0 += STEP)

+	{

+		ps1 = dn[i0];                      

+		alp1 = (*p0++);                    

+		pos = -1;                          

+		for (i1 = 1; i1 < L_SUBFR; i1 += STEP)

+		{

+			ps2 = add1(ps1, dn[i1]);

+			alp2 = add1(alp1, add1(*p1++, *p2++));

+			sq = vo_mult(ps2, ps2);

+			s = vo_L_mult(alpk, sq) - ((psk * alp2)<<1);

+			if (s > 0)

+			{

+				psk = sq;                  

+				alpk = alp2;               

+				pos = i1;                  

+			}

+		}

+		p1 -= NB_POS;

+		if (pos >= 0)

+		{

+			ix = i0;                      

+			iy = pos;                      

+		}

+	}

+	/*-------------------------------------------------------------------*

+	 * Build the codeword, the filtered codeword and index of codevector.*

+	 *-------------------------------------------------------------------*/

+

+	for (i = 0; i < L_SUBFR; i++)

+	{

+		code[i] = 0;                       

+	}

+

+	i0 = (ix >> 1);                       /* pos of pulse 1 (0..31) */

+	i1 = (iy >> 1);                       /* pos of pulse 2 (0..31) */

+	if (sign[ix] > 0)

+	{

+		code[ix] = 512;                     /* codeword in Q9 format */

+		p0 = h - ix;                       

+	} else

+	{

+		code[ix] = -512;                   

+		i0 += NB_POS;                      

+		p0 = h_inv - ix;                   

+	}

+	if (sign[iy] > 0)

+	{

+		code[iy] = 512;                    

+		p1 = h - iy;                       

+	} else

+	{

+		code[iy] = -512;                   

+		i1 += NB_POS;                      

+		p1 = h_inv - iy;                   

+	}

+	*index = add1((i0 << 6), i1);          

+	for (i = 0; i < L_SUBFR; i++)

+	{

+		y[i] = vo_shr_r(add1((*p0++), (*p1++)), 3);

+	}

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
new file mode 100644
index 0000000..27ba95d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
@@ -0,0 +1,1043 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: c4t64fx.c                                                 *

+*                                                                      *

+*	   Description:Performs algebraic codebook search for higher modes *

+*                                                                      *

+************************************************************************/

+

+/************************************************************************

+* Function: ACELP_4t64_fx()                                             *

+*                                                                       *

+* 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook.                   *

+* 4 tracks x 16 positions per track = 64 samples.                       *

+*                                                                       *

+* 20 bits --> 4 pulses in a frame of 64 samples.                        *

+* 36 bits --> 8 pulses in a frame of 64 samples.                        *

+* 44 bits --> 10 pulses in a frame of 64 samples.                       *

+* 52 bits --> 12 pulses in a frame of 64 samples.                       *

+* 64 bits --> 16 pulses in a frame of 64 samples.                       *

+* 72 bits --> 18 pulses in a frame of 64 samples.                       *

+* 88 bits --> 24 pulses in a frame of 64 samples.                       *

+*                                                                       *

+* All pulses can have two (2) possible amplitudes: +1 or -1.            *

+* Each pulse can have sixteen (16) possible positions.                  *

+*************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+#include "acelp.h"

+#include "cnst.h"

+

+#include "q_pulse.h"

+

+static Word16 tipos[36] = {

+	0, 1, 2, 3,                            /* starting point &ipos[0], 1st iter */

+	1, 2, 3, 0,                            /* starting point &ipos[4], 2nd iter */

+	2, 3, 0, 1,                            /* starting point &ipos[8], 3rd iter */

+	3, 0, 1, 2,                            /* starting point &ipos[12], 4th iter */

+	0, 1, 2, 3,

+	1, 2, 3, 0,

+	2, 3, 0, 1,

+	3, 0, 1, 2,

+	0, 1, 2, 3};                           /* end point for 24 pulses &ipos[35], 4th iter */

+

+#define NB_PULSE_MAX  24

+

+#define L_SUBFR   64

+#define NB_TRACK  4

+#define STEP      4

+#define NB_POS    16

+#define MSIZE     256

+#define NB_MAX    8

+#define NPMAXPT   ((NB_PULSE_MAX+NB_TRACK-1)/NB_TRACK)

+

+/* Private functions */

+void cor_h_vec_012(

+		Word16 h[],                           /* (i) scaled impulse response                 */

+		Word16 vec[],                         /* (i) scaled vector (/8) to correlate with h[] */

+		Word16 track,                         /* (i) track to use                            */

+		Word16 sign[],                        /* (i) sign vector                             */

+		Word16 rrixix[][NB_POS],              /* (i) correlation of h[x] with h[x]      */

+		Word16 cor_1[],                       /* (o) result of correlation (NB_POS elements) */

+		Word16 cor_2[]                        /* (o) result of correlation (NB_POS elements) */

+		);

+

+void cor_h_vec_012_asm(

+		Word16 h[],                           /* (i) scaled impulse response                 */

+		Word16 vec[],                         /* (i) scaled vector (/8) to correlate with h[] */

+		Word16 track,                         /* (i) track to use                            */

+		Word16 sign[],                        /* (i) sign vector                             */

+		Word16 rrixix[][NB_POS],              /* (i) correlation of h[x] with h[x]      */

+		Word16 cor_1[],                       /* (o) result of correlation (NB_POS elements) */

+		Word16 cor_2[]                        /* (o) result of correlation (NB_POS elements) */

+		);

+

+void cor_h_vec_30(

+		Word16 h[],                           /* (i) scaled impulse response                 */

+		Word16 vec[],                         /* (i) scaled vector (/8) to correlate with h[] */

+		Word16 track,                         /* (i) track to use                            */

+		Word16 sign[],                        /* (i) sign vector                             */

+		Word16 rrixix[][NB_POS],              /* (i) correlation of h[x] with h[x]      */

+		Word16 cor_1[],                       /* (o) result of correlation (NB_POS elements) */

+		Word16 cor_2[]                        /* (o) result of correlation (NB_POS elements) */

+		);

+

+void search_ixiy(

+		Word16 nb_pos_ix,                     /* (i) nb of pos for pulse 1 (1..8)       */

+		Word16 track_x,                       /* (i) track of pulse 1                   */

+		Word16 track_y,                       /* (i) track of pulse 2                   */

+		Word16 * ps,                          /* (i/o) correlation of all fixed pulses  */

+		Word16 * alp,                         /* (i/o) energy of all fixed pulses       */

+		Word16 * ix,                          /* (o) position of pulse 1                */

+		Word16 * iy,                          /* (o) position of pulse 2                */

+		Word16 dn[],                          /* (i) corr. between target and h[]       */

+		Word16 dn2[],                         /* (i) vector of selected positions       */

+		Word16 cor_x[],                       /* (i) corr. of pulse 1 with fixed pulses */

+		Word16 cor_y[],                       /* (i) corr. of pulse 2 with fixed pulses */

+		Word16 rrixiy[][MSIZE]                /* (i) corr. of pulse 1 with pulse 2   */

+		);

+

+

+void ACELP_4t64_fx(

+		Word16 dn[],                          /* (i) <12b : correlation between target x[] and H[]      */

+		Word16 cn[],                          /* (i) <12b : residual after long term prediction         */

+		Word16 H[],                           /* (i) Q12: impulse response of weighted synthesis filter */

+		Word16 code[],                        /* (o) Q9 : algebraic (fixed) codebook excitation         */

+		Word16 y[],                           /* (o) Q9 : filtered fixed codebook excitation            */

+		Word16 nbbits,                        /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits                */

+		Word16 ser_size,                      /* (i) : bit rate                                         */

+		Word16 _index[]                       /* (o) : index (20): 5+5+5+5 = 20 bits.                   */

+		/* (o) : index (36): 9+9+9+9 = 36 bits.                   */

+		/* (o) : index (44): 13+9+13+9 = 44 bits.                 */

+		/* (o) : index (52): 13+13+13+13 = 52 bits.               */

+		/* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits.       */

+		/* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits.     */

+		/* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits.   */

+		)

+{

+	Word32 i, j, k;

+	Word16 st, ix, iy, pos, index, track, nb_pulse, nbiter, j_temp;

+	Word16 psk, ps, alpk, alp, val, k_cn, k_dn, exp;

+	Word16 *p0, *p1, *p2, *p3, *psign;

+	Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf, h_shift;

+	Word32 s, cor, L_tmp, L_index;

+	Word16 dn2[L_SUBFR], sign[L_SUBFR], vec[L_SUBFR];

+	Word16 ind[NPMAXPT * NB_TRACK];

+	Word16 codvec[NB_PULSE_MAX], nbpos[10];

+	Word16 cor_x[NB_POS], cor_y[NB_POS], pos_max[NB_TRACK];

+	Word16 h_buf[4 * L_SUBFR];

+	Word16 rrixix[NB_TRACK][NB_POS], rrixiy[NB_TRACK][MSIZE];

+	Word16 ipos[NB_PULSE_MAX];

+

+	switch (nbbits)

+	{

+		case 20:                               /* 20 bits, 4 pulses, 4 tracks */

+			nbiter = 4;                          /* 4x16x16=1024 loop */

+			alp = 8192;                          /* alp = 2.0 (Q12) */

+			nb_pulse = 4;                      

+			nbpos[0] = 4;                      

+			nbpos[1] = 8;                      

+			break;

+		case 36:                               /* 36 bits, 8 pulses, 4 tracks */

+			nbiter = 4;                          /* 4x20x16=1280 loop */

+			alp = 4096;                          /* alp = 1.0 (Q12) */

+			nb_pulse = 8;                      

+			nbpos[0] = 4;                      

+			nbpos[1] = 8;                      

+			nbpos[2] = 8;                      

+			break;

+		case 44:                               /* 44 bits, 10 pulses, 4 tracks */

+			nbiter = 4;                          /* 4x26x16=1664 loop */

+			alp = 4096;                          /* alp = 1.0 (Q12) */

+			nb_pulse = 10;                     

+			nbpos[0] = 4;                      

+			nbpos[1] = 6;                      

+			nbpos[2] = 8;                      

+			nbpos[3] = 8;                      

+			break;

+		case 52:                               /* 52 bits, 12 pulses, 4 tracks */

+			nbiter = 4;                          /* 4x26x16=1664 loop */

+			alp = 4096;                          /* alp = 1.0 (Q12) */

+			nb_pulse = 12;                     

+			nbpos[0] = 4;                      

+			nbpos[1] = 6;                      

+			nbpos[2] = 8;                      

+			nbpos[3] = 8;                      

+			break;

+		case 64:                               /* 64 bits, 16 pulses, 4 tracks */

+			nbiter = 3;                          /* 3x36x16=1728 loop */

+			alp = 3277;                          /* alp = 0.8 (Q12) */

+			nb_pulse = 16;                     

+			nbpos[0] = 4;                      

+			nbpos[1] = 4;                      

+			nbpos[2] = 6;                      

+			nbpos[3] = 6;                      

+			nbpos[4] = 8;                      

+			nbpos[5] = 8;                      

+			break;

+		case 72:                               /* 72 bits, 18 pulses, 4 tracks */

+			nbiter = 3;                          /* 3x35x16=1680 loop */

+			alp = 3072;                          /* alp = 0.75 (Q12) */

+			nb_pulse = 18;                     

+			nbpos[0] = 2;                      

+			nbpos[1] = 3;                      

+			nbpos[2] = 4;                      

+			nbpos[3] = 5;                      

+			nbpos[4] = 6;                      

+			nbpos[5] = 7;                      

+			nbpos[6] = 8;                      

+			break;

+		case 88:                               /* 88 bits, 24 pulses, 4 tracks */

+			if(ser_size > 462)

+				nbiter = 1;

+			else

+				nbiter = 2;                    /* 2x53x16=1696 loop */

+

+			alp = 2048;                          /* alp = 0.5 (Q12) */

+			nb_pulse = 24;                     

+			nbpos[0] = 2;                      

+			nbpos[1] = 2;                      

+			nbpos[2] = 3;                      

+			nbpos[3] = 4;                      

+			nbpos[4] = 5;                      

+			nbpos[5] = 6;                      

+			nbpos[6] = 7;                      

+			nbpos[7] = 8;                      

+			nbpos[8] = 8;                      

+			nbpos[9] = 8;                      

+			break;

+		default:

+			nbiter = 0;

+			alp = 0;

+			nb_pulse = 0;

+	}

+

+	for (i = 0; i < nb_pulse; i++)

+	{

+		codvec[i] = i;                     

+	}

+

+	/*----------------------------------------------------------------*

+	 * Find sign for each pulse position.                             *

+	 *----------------------------------------------------------------*/

+	/* calculate energy for normalization of cn[] and dn[] */

+	/* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */

+#ifdef ASM_OPT                  /* asm optimization branch */

+	s = Dot_product12_asm(cn, cn, L_SUBFR, &exp);

+#else

+	s = Dot_product12(cn, cn, L_SUBFR, &exp);

+#endif

+

+	Isqrt_n(&s, &exp);

+	s = L_shl(s, (exp + 5)); 

+	k_cn = extract_h(L_add(s, 0x8000));

+

+	/* set k_dn = 32..512 (ener_dn = 2^30..2^22) */

+#ifdef ASM_OPT                      /* asm optimization branch */

+	s = Dot_product12_asm(dn, dn, L_SUBFR, &exp);

+#else

+	s = Dot_product12(dn, dn, L_SUBFR, &exp);

+#endif

+

+	Isqrt_n(&s, &exp);

+	k_dn = (L_shl(s, (exp + 5 + 3)) + 0x8000) >> 16;    /* k_dn = 256..4096 */

+	k_dn = vo_mult_r(alp, k_dn);              /* alp in Q12 */

+

+	/* mix normalized cn[] and dn[] */

+	p0 = cn;

+	p1 = dn;

+	p2 = dn2;

+

+	for (i = 0; i < L_SUBFR/4; i++)

+	{

+		s = (k_cn* (*p0++))+(k_dn * (*p1++));

+		*p2++ = s >> 7;

+		s = (k_cn* (*p0++))+(k_dn * (*p1++));

+		*p2++ = s >> 7;

+		s = (k_cn* (*p0++))+(k_dn * (*p1++));

+		*p2++ = s >> 7;

+		s = (k_cn* (*p0++))+(k_dn * (*p1++));

+		*p2++ = s >> 7; 

+	}

+

+	/* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[]    */

+	for(i = 0; i < L_SUBFR; i++)

+	{

+		val = dn[i];                   

+		ps = dn2[i];                   

+		if (ps >= 0)

+		{

+			sign[i] = 32767;             /* sign = +1 (Q12) */

+			vec[i] = -32768;           

+		} else

+		{

+			sign[i] = -32768;            /* sign = -1 (Q12) */

+			vec[i] = 32767;            

+			dn[i] = -val;

+			dn2[i] = -ps;

+		}

+	}

+	/*----------------------------------------------------------------*

+	 * Select NB_MAX position per track according to max of dn2[].    *

+	 *----------------------------------------------------------------*/

+	pos = 0;

+	for (i = 0; i < NB_TRACK; i++)

+	{

+		for (k = 0; k < NB_MAX; k++)

+		{

+			ps = -1;                       

+			for (j = i; j < L_SUBFR; j += STEP)

+			{

+				if(dn2[j] > ps)

+				{

+					ps = dn2[j];          

+					pos = j;               

+				}

+			}

+			dn2[pos] = (k - NB_MAX);     /* dn2 < 0 when position is selected */

+			if (k == 0)

+			{

+				pos_max[i] = pos;          

+			}

+		}

+	}

+

+	/*--------------------------------------------------------------*

+	 * Scale h[] to avoid overflow and to get maximum of precision  *

+	 * on correlation.                                              *

+	 *                                                              *

+	 * Maximum of h[] (h[0]) is fixed to 2048 (MAX16 / 16).         *

+	 *  ==> This allow addition of 16 pulses without saturation.    *

+	 *                                                              *

+	 * Energy worst case (on resonant impulse response),            *

+	 * - energy of h[] is approximately MAX/16.                     *

+	 * - During search, the energy is divided by 8 to avoid         *

+	 *   overflow on "alp". (energy of h[] = MAX/128).              *

+	 *  ==> "alp" worst case detected is 22854 on sinusoidal wave.  *

+	 *--------------------------------------------------------------*/

+

+	/* impulse response buffer for fast computation */

+

+	h = h_buf;                             

+	h_inv = h_buf + (2 * L_SUBFR);   

+	L_tmp = 0;

+	for (i = 0; i < L_SUBFR; i++)

+	{

+		*h++ = 0;                          

+		*h_inv++ = 0;   

+		L_tmp += (H[i] * H[i]) << 1;

+	}

+	/* scale h[] down (/2) when energy of h[] is high with many pulses used */

+	val = extract_h(L_tmp);

+	h_shift = 0;                           

+

+	if ((nb_pulse >= 12) && (val > 1024))

+	{

+		h_shift = 1;                       

+	}

+	p0 = H;

+	p1 = h;

+	p2 = h_inv;

+

+	for (i = 0; i < L_SUBFR/4; i++)

+	{

+		*p1 = *p0++ >> h_shift;         

+		*p2++ = -(*p1++);  

+		*p1 = *p0++ >> h_shift;         

+		*p2++ = -(*p1++); 

+		*p1 = *p0++ >> h_shift;         

+		*p2++ = -(*p1++); 

+		*p1 = *p0++ >> h_shift;         

+		*p2++ = -(*p1++); 

+	}

+

+	/*------------------------------------------------------------*

+	 * Compute rrixix[][] needed for the codebook search.         *

+	 * This algorithm compute impulse response energy of all      *

+	 * positions (16) in each track (4).       Total = 4x16 = 64. *

+	 *------------------------------------------------------------*/

+

+	/* storage order --> i3i3, i2i2, i1i1, i0i0 */

+

+	/* Init pointers to last position of rrixix[] */

+	p0 = &rrixix[0][NB_POS - 1];           

+	p1 = &rrixix[1][NB_POS - 1];           

+	p2 = &rrixix[2][NB_POS - 1];           

+	p3 = &rrixix[3][NB_POS - 1];           

+

+	ptr_h1 = h;                            

+	cor = 0x00008000L;                             /* for rounding */

+	for (i = 0; i < NB_POS; i++)

+	{

+		cor += vo_L_mult((*ptr_h1), (*ptr_h1));

+		ptr_h1++;

+		*p3-- = extract_h(cor);            

+		cor += vo_L_mult((*ptr_h1), (*ptr_h1));

+		ptr_h1++;

+		*p2-- = extract_h(cor);            

+		cor += vo_L_mult((*ptr_h1), (*ptr_h1));

+		ptr_h1++;

+		*p1-- = extract_h(cor);            

+		cor += vo_L_mult((*ptr_h1), (*ptr_h1));

+		ptr_h1++;

+		*p0-- = extract_h(cor);            

+	}

+

+	/*------------------------------------------------------------*

+	 * Compute rrixiy[][] needed for the codebook search.         *

+	 * This algorithm compute correlation between 2 pulses        *

+	 * (2 impulses responses) in 4 possible adjacents tracks.     *

+	 * (track 0-1, 1-2, 2-3 and 3-0).     Total = 4x16x16 = 1024. *

+	 *------------------------------------------------------------*/

+

+	/* storage order --> i2i3, i1i2, i0i1, i3i0 */

+

+	pos = MSIZE - 1;                       

+	ptr_hf = h + 1;                        

+

+	for (k = 0; k < NB_POS; k++)

+	{

+		p3 = &rrixiy[2][pos];              

+		p2 = &rrixiy[1][pos];              

+		p1 = &rrixiy[0][pos];              

+		p0 = &rrixiy[3][pos - NB_POS];     

+

+		cor = 0x00008000L;                   /* for rounding */

+		ptr_h1 = h;                        

+		ptr_h2 = ptr_hf;                   

+

+		for (i = k + 1; i < NB_POS; i++)

+		{

+			cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+			ptr_h1++;

+			ptr_h2++;

+			*p3 = extract_h(cor);          

+			cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+			ptr_h1++;

+			ptr_h2++;

+			*p2 = extract_h(cor);          

+			cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+			ptr_h1++;

+			ptr_h2++;

+			*p1 = extract_h(cor);          

+			cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+			ptr_h1++;

+			ptr_h2++;

+			*p0 = extract_h(cor);         

+

+			p3 -= (NB_POS + 1);

+			p2 -= (NB_POS + 1);

+			p1 -= (NB_POS + 1);

+			p0 -= (NB_POS + 1);

+		}

+		cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+		ptr_h1++;

+		ptr_h2++;

+		*p3 = extract_h(cor);              

+		cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+		ptr_h1++;

+		ptr_h2++;

+		*p2 = extract_h(cor);              

+		cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+		ptr_h1++;

+		ptr_h2++;

+		*p1 = extract_h(cor);              

+

+		pos -= NB_POS;

+		ptr_hf += STEP;

+	}

+

+	/* storage order --> i3i0, i2i3, i1i2, i0i1 */

+

+	pos = MSIZE - 1;                       

+	ptr_hf = h + 3;                        

+

+	for (k = 0; k < NB_POS; k++)

+	{

+		p3 = &rrixiy[3][pos];              

+		p2 = &rrixiy[2][pos - 1];          

+		p1 = &rrixiy[1][pos - 1];          

+		p0 = &rrixiy[0][pos - 1];          

+

+		cor = 0x00008000L;								/* for rounding */

+		ptr_h1 = h;                        

+		ptr_h2 = ptr_hf;                   

+

+		for (i = k + 1; i < NB_POS; i++)

+		{

+			cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+			ptr_h1++;

+			ptr_h2++;

+			*p3 = extract_h(cor);          

+			cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+			ptr_h1++;

+			ptr_h2++;

+			*p2 = extract_h(cor);          

+			cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+			ptr_h1++;

+			ptr_h2++;

+			*p1 = extract_h(cor);          

+			cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+			ptr_h1++;

+			ptr_h2++;

+			*p0 = extract_h(cor);          

+

+			p3 -= (NB_POS + 1);

+			p2 -= (NB_POS + 1);

+			p1 -= (NB_POS + 1);

+			p0 -= (NB_POS + 1);

+		}

+		cor += vo_L_mult((*ptr_h1), (*ptr_h2));

+		ptr_h1++;

+		ptr_h2++;

+		*p3 = extract_h(cor);              

+

+		pos--;

+		ptr_hf += STEP;

+	}

+

+	/*------------------------------------------------------------*

+	 * Modification of rrixiy[][] to take signs into account.     *

+	 *------------------------------------------------------------*/

+

+	p0 = &rrixiy[0][0];                    

+

+	for (k = 0; k < NB_TRACK; k++)

+	{

+		j_temp = (k + 1)&0x03;

+		for (i = k; i < L_SUBFR; i += STEP)

+		{

+			psign = sign;                  

+			if (psign[i] < 0)

+			{

+				psign = vec;               

+			}

+			j = j_temp;

+			for (; j < L_SUBFR; j += STEP)

+			{

+				*p0 = vo_mult(*p0, psign[j]);    

+				p0++;

+			}

+		}

+	}

+

+	/*-------------------------------------------------------------------*

+	 *                       Deep first search                           *

+	 *-------------------------------------------------------------------*/

+

+	psk = -1;                              

+	alpk = 1;                              

+

+	for (k = 0; k < nbiter; k++)

+	{

+		j_temp = k<<2;

+		for (i = 0; i < nb_pulse; i++)

+			ipos[i] = tipos[j_temp + i];

+

+		if(nbbits == 20)

+		{

+			pos = 0;                       

+			ps = 0;                        

+			alp = 0;                       

+			for (i = 0; i < L_SUBFR; i++)

+			{

+				vec[i] = 0;                

+			}

+		} else if ((nbbits == 36) || (nbbits == 44))

+		{

+			/* first stage: fix 2 pulses */

+			pos = 2;

+

+			ix = ind[0] = pos_max[ipos[0]];

+			iy = ind[1] = pos_max[ipos[1]];

+			ps = dn[ix] + dn[iy];

+			i = ix >> 2;                /* ix / STEP */

+			j = iy >> 2;                /* iy / STEP */

+			s = rrixix[ipos[0]][i] << 13;

+			s += rrixix[ipos[1]][j] << 13;

+			i = (i << 4) + j;         /* (ix/STEP)*NB_POS + (iy/STEP) */

+			s += rrixiy[ipos[0]][i] << 14;

+			alp = (s + 0x8000) >> 16;

+			if (sign[ix] < 0)

+				p0 = h_inv - ix;

+			else

+				p0 = h - ix;

+			if (sign[iy] < 0)

+				p1 = h_inv - iy;

+			else

+				p1 = h - iy;

+

+			for (i = 0; i < L_SUBFR; i++)

+			{

+				vec[i] = (*p0++) + (*p1++);

+			}

+

+			if(nbbits == 44)

+			{

+				ipos[8] = 0;               

+				ipos[9] = 1;               

+			}

+		} else

+		{

+			/* first stage: fix 4 pulses */

+			pos = 4;

+

+			ix = ind[0] = pos_max[ipos[0]];  

+			iy = ind[1] = pos_max[ipos[1]];  

+			i = ind[2] = pos_max[ipos[2]];   

+			j = ind[3] = pos_max[ipos[3]];   

+			ps = add1(add1(add1(dn[ix], dn[iy]), dn[i]), dn[j]);

+

+			if (sign[ix] < 0)

+				p0 = h_inv - ix;

+			else

+				p0 = h - ix;

+

+			if (sign[iy] < 0)

+				p1 = h_inv - iy;

+			else

+				p1 = h - iy;

+

+			if (sign[i] < 0)

+				p2 = h_inv - i;

+			else

+				p2 = h - i;

+

+			if (sign[j] < 0)

+				p3 = h_inv - j;

+			else

+				p3 = h - j;

+

+			L_tmp = 0L;

+			for(i = 0; i < L_SUBFR; i++)

+			{

+				vec[i]  = add1(add1(add1(*p0++, *p1++), *p2++), *p3++);

+				L_tmp  += (vec[i] * vec[i]) << 1;

+			}

+

+			alp = ((L_tmp >> 3) + 0x8000) >> 16;

+

+			if(nbbits == 72)

+			{

+				ipos[16] = 0;              

+				ipos[17] = 1;              

+			}

+		}

+

+		/* other stages of 2 pulses */

+

+		for (j = pos, st = 0; j < nb_pulse; j += 2, st++)

+		{

+			/*--------------------------------------------------*

+			 * Calculate correlation of all possible positions  *

+			 * of the next 2 pulses with previous fixed pulses. *

+			 * Each pulse can have 16 possible positions.       *

+			 *--------------------------------------------------*/

+			if(ipos[j] == 3)

+			{

+				cor_h_vec_30(h, vec, ipos[j], sign, rrixix, cor_x, cor_y);

+			}

+			else

+			{

+#ifdef ASM_OPT                 /* asm optimization branch */

+				cor_h_vec_012_asm(h, vec, ipos[j], sign, rrixix, cor_x, cor_y);

+#else

+				cor_h_vec_012(h, vec, ipos[j], sign, rrixix, cor_x, cor_y);

+#endif

+			}

+			/*--------------------------------------------------*

+			 * Find best positions of 2 pulses.                 *

+			 *--------------------------------------------------*/

+			search_ixiy(nbpos[st], ipos[j], ipos[j + 1], &ps, &alp,

+					&ix, &iy, dn, dn2, cor_x, cor_y, rrixiy);

+

+			ind[j] = ix;                   

+			ind[j + 1] = iy;               

+

+			if (sign[ix] < 0)

+				p0 = h_inv - ix;

+			else

+				p0 = h - ix;

+			if (sign[iy] < 0)

+				p1 = h_inv - iy;

+			else

+				p1 = h - iy;

+

+			for (i = 0; i < L_SUBFR; i+=4)

+			{

+				vec[i]   += add1((*p0++), (*p1++));       

+				vec[i+1] += add1((*p0++), (*p1++));        

+				vec[i+2] += add1((*p0++), (*p1++));        

+				vec[i+3] += add1((*p0++), (*p1++));      

+			}

+		}

+		/* memorise the best codevector */

+		ps = vo_mult(ps, ps);

+		s = vo_L_msu(vo_L_mult(alpk, ps), psk, alp);

+		if (s > 0)

+		{

+			psk = ps;                      

+			alpk = alp;                    

+			for (i = 0; i < nb_pulse; i++)

+			{

+				codvec[i] = ind[i];        

+			}

+			for (i = 0; i < L_SUBFR; i++)

+			{

+				y[i] = vec[i];             

+			}

+		}

+	}

+	/*-------------------------------------------------------------------*

+	 * Build the codeword, the filtered codeword and index of codevector.*

+	 *-------------------------------------------------------------------*/

+	for (i = 0; i < NPMAXPT * NB_TRACK; i++)

+	{

+		ind[i] = -1;                       

+	}

+	for (i = 0; i < L_SUBFR; i++)

+	{

+		code[i] = 0;                       

+		y[i] = vo_shr_r(y[i], 3);               /* Q12 to Q9 */

+	}

+	val = (512 >> h_shift);               /* codeword in Q9 format */

+	for (k = 0; k < nb_pulse; k++)

+	{

+		i = codvec[k];                       /* read pulse position */

+		j = sign[i];                         /* read sign           */

+		index = i >> 2;                 /* index = pos of pulse (0..15) */

+		track = (Word16) (i & 0x03);         /* track = i % NB_TRACK (0..3)  */

+

+		if (j > 0)

+		{

+			code[i] += val;   

+			codvec[k] += 128;  

+		} else

+		{

+			code[i] -= val;   

+			index += NB_POS;    

+		}

+

+		i = (Word16)((vo_L_mult(track, NPMAXPT) >> 1));

+

+		while (ind[i] >= 0)

+		{

+			i += 1;

+		}

+		ind[i] = index;                    

+	}

+

+	k = 0;                                 

+	/* Build index of codevector */

+	if(nbbits == 20)

+	{

+		for (track = 0; track < NB_TRACK; track++)

+		{

+			_index[track] = (Word16)(quant_1p_N1(ind[k], 4));

+			k += NPMAXPT;

+		}

+	} else if(nbbits == 36)

+	{

+		for (track = 0; track < NB_TRACK; track++)

+		{

+			_index[track] = (Word16)(quant_2p_2N1(ind[k], ind[k + 1], 4));

+			k += NPMAXPT;

+		}

+	} else if(nbbits == 44)

+	{

+		for (track = 0; track < NB_TRACK - 2; track++)

+		{

+			_index[track] = (Word16)(quant_3p_3N1(ind[k], ind[k + 1], ind[k + 2], 4));

+			k += NPMAXPT;

+		}

+		for (track = 2; track < NB_TRACK; track++)

+		{

+			_index[track] = (Word16)(quant_2p_2N1(ind[k], ind[k + 1], 4));

+			k += NPMAXPT;

+		}

+	} else if(nbbits == 52)

+	{

+		for (track = 0; track < NB_TRACK; track++)

+		{

+			_index[track] = (Word16)(quant_3p_3N1(ind[k], ind[k + 1], ind[k + 2], 4));

+			k += NPMAXPT;

+		}

+	} else if(nbbits == 64)

+	{

+		for (track = 0; track < NB_TRACK; track++)

+		{

+			L_index = quant_4p_4N(&ind[k], 4);

+			_index[track] = (Word16)((L_index >> 14) & 3);

+			_index[track + NB_TRACK] = (Word16)(L_index & 0x3FFF);

+			k += NPMAXPT;

+		}

+	} else if(nbbits == 72)

+	{

+		for (track = 0; track < NB_TRACK - 2; track++)

+		{

+			L_index = quant_5p_5N(&ind[k], 4);

+			_index[track] = (Word16)((L_index >> 10) & 0x03FF);

+			_index[track + NB_TRACK] = (Word16)(L_index & 0x03FF);

+			k += NPMAXPT;

+		}

+		for (track = 2; track < NB_TRACK; track++)

+		{

+			L_index = quant_4p_4N(&ind[k], 4);

+			_index[track] = (Word16)((L_index >> 14) & 3);

+			_index[track + NB_TRACK] = (Word16)(L_index & 0x3FFF);

+			k += NPMAXPT;

+		}

+	} else if(nbbits == 88)

+	{

+		for (track = 0; track < NB_TRACK; track++)

+		{

+			L_index = quant_6p_6N_2(&ind[k], 4);

+			_index[track] = (Word16)((L_index >> 11) & 0x07FF);

+			_index[track + NB_TRACK] = (Word16)(L_index & 0x07FF);

+			k += NPMAXPT;

+		}

+	}

+	return;

+}

+

+

+/*-------------------------------------------------------------------*

+ * Function  cor_h_vec()                                             *

+ * ~~~~~~~~~~~~~~~~~~~~~                                             *

+ * Compute correlations of h[] with vec[] for the specified track.   *

+ *-------------------------------------------------------------------*/

+void cor_h_vec_30(

+		Word16 h[],                           /* (i) scaled impulse response                 */

+		Word16 vec[],                         /* (i) scaled vector (/8) to correlate with h[] */

+		Word16 track,                         /* (i) track to use                            */

+		Word16 sign[],                        /* (i) sign vector                             */

+		Word16 rrixix[][NB_POS],              /* (i) correlation of h[x] with h[x]      */

+		Word16 cor_1[],                       /* (o) result of correlation (NB_POS elements) */

+		Word16 cor_2[]                        /* (o) result of correlation (NB_POS elements) */

+		)

+{

+	Word32 i, j, pos, corr;

+	Word16 *p0, *p1, *p2,*p3,*cor_x,*cor_y;

+	Word32 L_sum1,L_sum2;

+	cor_x = cor_1;

+	cor_y = cor_2;

+	p0 = rrixix[track];

+	p3 = rrixix[0];

+	pos = track;

+

+	for (i = 0; i < NB_POS; i+=2)

+	{

+		L_sum1 = L_sum2 = 0L;

+		p1 = h;

+		p2 = &vec[pos];

+		for (j=pos;j < L_SUBFR; j++)

+		{

+			L_sum1 += *p1 * *p2;		

+			p2-=3;

+			L_sum2 += *p1++ * *p2;		

+			p2+=4;

+		}

+		p2-=3;

+		L_sum2 += *p1++ * *p2++;	

+		L_sum2 += *p1++ * *p2++;	

+		L_sum2 += *p1++ * *p2++;	

+

+		L_sum1 = (L_sum1 << 2);

+		L_sum2 = (L_sum2 << 2);

+

+		corr = vo_round(L_sum1);	

+		*cor_x++ = vo_mult(corr, sign[pos]) + (*p0++);

+		corr = vo_round(L_sum2);

+		*cor_y++ = vo_mult(corr, sign[pos-3]) + (*p3++);

+		pos += STEP;

+

+		L_sum1 = L_sum2 = 0L;

+		p1 = h;

+		p2 = &vec[pos];

+		for (j=pos;j < L_SUBFR; j++)

+		{

+			L_sum1 += *p1 * *p2;		

+			p2-=3;

+			L_sum2 += *p1++ * *p2;		

+			p2+=4;

+		}

+		p2-=3;

+		L_sum2 += *p1++ * *p2++;	

+		L_sum2 += *p1++ * *p2++;	

+		L_sum2 += *p1++ * *p2++;	

+

+		L_sum1 = (L_sum1 << 2);

+		L_sum2 = (L_sum2 << 2);

+

+		corr = vo_round(L_sum1);	

+		*cor_x++ = vo_mult(corr, sign[pos]) + (*p0++);

+		corr = vo_round(L_sum2);

+		*cor_y++ = vo_mult(corr, sign[pos-3]) + (*p3++);

+		pos += STEP;

+	}

+	return;

+}

+

+void cor_h_vec_012(

+		Word16 h[],                           /* (i) scaled impulse response                 */

+		Word16 vec[],                         /* (i) scaled vector (/8) to correlate with h[] */

+		Word16 track,                         /* (i) track to use                            */

+		Word16 sign[],                        /* (i) sign vector                             */

+		Word16 rrixix[][NB_POS],              /* (i) correlation of h[x] with h[x]      */

+		Word16 cor_1[],                       /* (o) result of correlation (NB_POS elements) */

+		Word16 cor_2[]                        /* (o) result of correlation (NB_POS elements) */

+		)

+{

+	Word32 i, j, pos, corr;

+	Word16 *p0, *p1, *p2,*p3,*cor_x,*cor_y;

+	Word32 L_sum1,L_sum2;

+	cor_x = cor_1;

+	cor_y = cor_2;

+	p0 = rrixix[track];

+	p3 = rrixix[track+1];

+	pos = track;

+

+	for (i = 0; i < NB_POS; i+=2)

+	{

+		L_sum1 = L_sum2 = 0L;

+		p1 = h;

+		p2 = &vec[pos];

+		for (j=62-pos ;j >= 0; j--)

+		{

+			L_sum1 += *p1 * *p2++;

+			L_sum2 += *p1++ * *p2;

+		}

+		L_sum1 += *p1 * *p2;

+		L_sum1 = (L_sum1 << 2);

+		L_sum2 = (L_sum2 << 2);

+

+		corr = (L_sum1 + 0x8000) >> 16;

+		cor_x[i] = vo_mult(corr, sign[pos]) + (*p0++);

+		corr = (L_sum2 + 0x8000) >> 16;

+		cor_y[i] = vo_mult(corr, sign[pos + 1]) + (*p3++);

+		pos += STEP;

+

+		L_sum1 = L_sum2 = 0L;

+		p1 = h;

+		p2 = &vec[pos];

+		for (j= 62-pos;j >= 0; j--)

+		{

+			L_sum1 += *p1 * *p2++;

+			L_sum2 += *p1++ * *p2;

+		}

+		L_sum1 += *p1 * *p2;

+		L_sum1 = (L_sum1 << 2);

+		L_sum2 = (L_sum2 << 2);

+

+		corr = (L_sum1 + 0x8000) >> 16;

+		cor_x[i+1] = vo_mult(corr, sign[pos]) + (*p0++);

+		corr = (L_sum2 + 0x8000) >> 16;

+		cor_y[i+1] = vo_mult(corr, sign[pos + 1]) + (*p3++);

+		pos += STEP;

+	}

+	return;

+}

+

+/*-------------------------------------------------------------------*

+ * Function  search_ixiy()                                           *

+ * ~~~~~~~~~~~~~~~~~~~~~~~                                           *

+ * Find the best positions of 2 pulses in a subframe.                *

+ *-------------------------------------------------------------------*/

+

+void search_ixiy(

+		Word16 nb_pos_ix,                     /* (i) nb of pos for pulse 1 (1..8)       */

+		Word16 track_x,                       /* (i) track of pulse 1                   */

+		Word16 track_y,                       /* (i) track of pulse 2                   */

+		Word16 * ps,                          /* (i/o) correlation of all fixed pulses  */

+		Word16 * alp,                         /* (i/o) energy of all fixed pulses       */

+		Word16 * ix,                          /* (o) position of pulse 1                */

+		Word16 * iy,                          /* (o) position of pulse 2                */

+		Word16 dn[],                          /* (i) corr. between target and h[]       */

+		Word16 dn2[],                         /* (i) vector of selected positions       */

+		Word16 cor_x[],                       /* (i) corr. of pulse 1 with fixed pulses */

+		Word16 cor_y[],                       /* (i) corr. of pulse 2 with fixed pulses */

+		Word16 rrixiy[][MSIZE]                /* (i) corr. of pulse 1 with pulse 2   */

+		)

+{

+	Word32 x, y, pos, thres_ix;

+	Word16 ps1, ps2, sq, sqk;

+	Word16 alp_16, alpk;

+	Word16 *p0, *p1, *p2;

+	Word32 s, alp0, alp1, alp2;

+

+	p0 = cor_x;                            

+	p1 = cor_y;                            

+	p2 = rrixiy[track_x];                  

+

+	thres_ix = nb_pos_ix - NB_MAX;

+

+	alp0 = L_deposit_h(*alp);

+	alp0 = (alp0 + 0x00008000L);       /* for rounding */

+

+	sqk = -1;                              

+	alpk = 1;                              

+

+	for (x = track_x; x < L_SUBFR; x += STEP)

+	{

+		ps1 = *ps + dn[x];

+		alp1 = alp0 + ((*p0++)<<13);

+

+		if (dn2[x] < thres_ix)

+		{

+			pos = -1;

+			for (y = track_y; y < L_SUBFR; y += STEP)

+			{

+				ps2 = add1(ps1, dn[y]);

+

+				alp2 = alp1 + ((*p1++)<<13);

+				alp2 = alp2 + ((*p2++)<<14);

+				alp_16 = extract_h(alp2);

+				sq = vo_mult(ps2, ps2);

+				s = vo_L_mult(alpk, sq) - ((sqk * alp_16)<<1);

+

+				if (s > 0)

+				{

+					sqk = sq;              

+					alpk = alp_16;         

+					pos = y;               

+				}

+			}

+			p1 -= NB_POS;

+

+			if (pos >= 0)

+			{

+				*ix = x;                   

+				*iy = pos;                 

+			}

+		} else

+		{

+			p2 += NB_POS;

+		}

+	}

+

+	*ps = add1(*ps, add1(dn[*ix], dn[*iy])); 

+	*alp = alpk;                           

+

+	return;

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c b/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c
new file mode 100644
index 0000000..c17264c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c
@@ -0,0 +1,73 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		cmnMemory.c

+

+	Content:	sample code for memory operator implementation

+

+*******************************************************************************/

+#include "cmnMemory.h"

+

+#include <malloc.h>

+#if defined LINUX

+#include <string.h>

+#endif

+

+//VO_MEM_OPERATOR		g_memOP;

+

+VO_U32 cmnMemAlloc (VO_S32 uID,  VO_MEM_INFO * pMemInfo)

+{

+	if (!pMemInfo)

+		return VO_ERR_INVALID_ARG;

+

+	pMemInfo->VBuffer = malloc (pMemInfo->Size);

+	return 0;

+}

+

+VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem)

+{

+	free (pMem);

+	return 0;

+}

+

+VO_U32	cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize)

+{

+	memset (pBuff, uValue, uSize);

+	return 0;

+}

+

+VO_U32	cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)

+{

+	memcpy (pDest, pSource, uSize);

+	return 0;

+}

+

+VO_U32	cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize)

+{

+	return 0;

+}

+

+VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize)

+{

+	return memcmp(pBuffer1, pBuffer2, uSize);

+}

+

+VO_U32	cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)

+{

+	memmove (pDest, pSource, uSize);

+	return 0;

+}

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/convolve.c b/media/libstagefright/codecs/amrwbenc/src/convolve.c
new file mode 100644
index 0000000..66c74d6
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/convolve.c
@@ -0,0 +1,109 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+       File: convolve.c

+

+	   Description:Perform the convolution between two vectors x[] and h[]

+	               and write the result in the vector y[]

+

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+void Convolve (

+		Word16 x[],        /* (i)     : input vector                           */

+		Word16 h[],        /* (i)     : impulse response                       */

+		Word16 y[],        /* (o)     : output vector                          */

+		Word16 L           /* (i)     : vector size                            */

+	      )

+{

+	Word32  i, n;

+	Word16 *tmpH,*tmpX;

+	Word32 s;

+	for (n = 0; n < 64;)

+	{

+		tmpH = h+n;

+		tmpX = x;

+		i=n+1;

+		s = vo_mult32((*tmpX++), (*tmpH--));i--;

+		while(i>0)

+		{

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			i -= 4;

+		}

+		y[n] = ((s<<1) + 0x8000)>>16;   

+		n++;

+

+		tmpH = h+n;

+		tmpX = x;

+		i=n+1;

+		s =  vo_mult32((*tmpX++), (*tmpH--));i--;

+		s += vo_mult32((*tmpX++), (*tmpH--));i--;

+

+		while(i>0)

+		{

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			i -= 4;

+		}

+		y[n] = ((s<<1) + 0x8000)>>16;    

+		n++;

+

+		tmpH = h+n;

+		tmpX = x;

+		i=n+1;

+		s =  vo_mult32((*tmpX++), (*tmpH--));i--;

+		s += vo_mult32((*tmpX++), (*tmpH--));i--;

+		s += vo_mult32((*tmpX++), (*tmpH--));i--;

+

+		while(i>0)

+		{

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			i -= 4;

+		}

+		y[n] = ((s<<1) + 0x8000)>>16;   

+		n++;

+

+		s = 0;

+		tmpH = h+n;

+		tmpX = x;

+		i=n+1;

+		while(i>0)

+		{

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			s += vo_mult32((*tmpX++), (*tmpH--));

+			i -= 4;

+		}

+		y[n] = ((s<<1) + 0x8000)>>16;   

+		n++;        

+	}

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c b/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c
new file mode 100644
index 0000000..3c2e9d5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c
@@ -0,0 +1,127 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: cor_h_x.c                                                *

+*                                                                      *

+*	   Description:Compute correlation between target "x[]" and "h[]"  *

+*	               Designed for codebook search (24 pulses, 4 tracks,  * 

+*				   4 pulses per track, 16 positions in each track) to  *

+*				   avoid saturation.                                   *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+

+#define L_SUBFR   64

+#define NB_TRACK  4

+#define STEP      4

+

+void cor_h_x(

+		Word16 h[],                           /* (i) Q12 : impulse response of weighted synthesis filter */

+		Word16 x[],                           /* (i) Q0  : target vector                                 */

+		Word16 dn[]                           /* (o) <12bit : correlation between target and h[]         */

+	    )

+{

+	Word32 i, j;

+	Word32 L_tmp, y32[L_SUBFR], L_tot;

+	Word16 *p1, *p2;

+	Word32 *p3;

+	Word32 L_max, L_max1, L_max2, L_max3;

+	/* first keep the result on 32 bits and find absolute maximum */

+	L_tot  = 1;                            

+	L_max  = 0; 

+	L_max1 = 0;

+	L_max2 = 0;

+	L_max3 = 0;

+	for (i = 0; i < L_SUBFR; i += STEP)

+	{

+		L_tmp = 1;                                    /* 1 -> to avoid null dn[] */

+		p1 = &x[i];

+		p2 = &h[0];

+		for (j = i; j < L_SUBFR; j++)

+			L_tmp += vo_L_mult(*p1++, *p2++);

+

+		y32[i] = L_tmp;               

+		L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;

+		if(L_tmp > L_max)

+		{

+			L_max = L_tmp;             

+		}

+

+		L_tmp = 1L;

+		p1 = &x[i+1];

+		p2 = &h[0];

+		for (j = i+1; j < L_SUBFR; j++)

+			L_tmp += vo_L_mult(*p1++, *p2++);

+

+		y32[i+1] = L_tmp;               

+		L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;

+		if(L_tmp > L_max1)

+		{

+			L_max1 = L_tmp;             

+		}

+

+		L_tmp = 1;

+		p1 = &x[i+2];

+		p2 = &h[0];

+		for (j = i+2; j < L_SUBFR; j++)

+			L_tmp += vo_L_mult(*p1++, *p2++);

+

+		y32[i+2] = L_tmp;               

+		L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;

+		if(L_tmp > L_max2)

+		{

+			L_max2 = L_tmp;             

+		}

+

+		L_tmp = 1;

+		p1 = &x[i+3];

+		p2 = &h[0];

+		for (j = i+3; j < L_SUBFR; j++)

+			L_tmp += vo_L_mult(*p1++, *p2++);

+

+		y32[i+3] = L_tmp;               

+		L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;

+		if(L_tmp > L_max3)

+		{

+			L_max3 = L_tmp;             

+		}

+	}

+	/* tot += 3*max / 8 */

+	L_max = ((L_max + L_max1 + L_max2 + L_max3) >> 2);

+	L_tot = vo_L_add(L_tot, L_max);       /* +max/4 */

+	L_tot = vo_L_add(L_tot, (L_max >> 1));  /* +max/8 */

+

+	/* Find the number of right shifts to do on y32[] so that    */

+	/* 6.0 x sumation of max of dn[] in each track not saturate. */

+	j = norm_l(L_tot) - 4;             /* 4 -> 16 x tot */

+	p1 = dn;

+	p3 = y32;

+	for (i = 0; i < L_SUBFR; i+=4)

+	{

+		*p1++ = vo_round(L_shl(*p3++, j));

+		*p1++ = vo_round(L_shl(*p3++, j));

+		*p1++ = vo_round(L_shl(*p3++, j));

+		*p1++ = vo_round(L_shl(*p3++, j));

+	}

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/decim54.c b/media/libstagefright/codecs/amrwbenc/src/decim54.c
new file mode 100644
index 0000000..429a7d6
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/decim54.c
@@ -0,0 +1,146 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: decim54.c                                                 *

+*                                                                      *

+*	   Description:Decimation of 16kHz signal to 12.8kHz           *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "acelp.h"

+#include "cnst.h"

+

+#define FAC5   5

+#define DOWN_FAC  26215                    /* 4/5 in Q15 */

+

+#define NB_COEF_DOWN  15

+

+/* Local functions */

+static void Down_samp(

+		Word16 * sig,                         /* input:  signal to downsampling  */

+		Word16 * sig_d,                       /* output: downsampled signal      */

+		Word16 L_frame_d                      /* input:  length of output        */

+		);

+

+/* 1/5 resolution interpolation filter  (in Q14)  */

+/* -1.5dB @ 6kHz, -6dB @ 6.4kHz, -10dB @ 6.6kHz, -20dB @ 6.9kHz, -25dB @ 7kHz, -55dB @ 8kHz */

+

+static Word16 fir_down1[4][30] =

+{

+	{-5, 24, -50, 54, 0, -128, 294, -408, 344, 0, -647, 1505, -2379, 3034, 13107, 3034, -2379, 1505, -647, 0, 344, -408,

+	294, -128, 0, 54, -50, 24, -5, 0},

+

+	{-6, 19, -26, 0, 77, -188, 270, -233, 0, 434, -964, 1366, -1293, 0, 12254, 6575, -2746, 1030, 0, -507, 601, -441,

+	198, 0, -95, 99, -58, 18, 0, -1},

+

+	{-3, 9, 0, -41, 111, -170, 153, 0, -295, 649, -888, 770, 0, -1997, 9894, 9894, -1997, 0, 770, -888, 649, -295, 0,

+	153, -170, 111, -41, 0, 9, -3},

+

+	{-1, 0, 18, -58, 99, -95, 0, 198, -441, 601, -507, 0, 1030, -2746, 6575, 12254, 0, -1293, 1366, -964, 434, 0,

+	-233, 270, -188, 77, 0, -26, 19, -6}

+};

+

+void Init_Decim_12k8(

+		Word16 mem[]                          /* output: memory (2*NB_COEF_DOWN) set to zeros */

+		)

+{

+	Set_zero(mem, 2 * NB_COEF_DOWN);

+	return;

+}

+

+void Decim_12k8(

+		Word16 sig16k[],                      /* input:  signal to downsampling  */

+		Word16 lg,                            /* input:  length of input         */

+		Word16 sig12k8[],                     /* output: decimated signal        */

+		Word16 mem[]                          /* in/out: memory (2*NB_COEF_DOWN) */

+	       )

+{

+	Word16 lg_down;

+	Word16 signal[L_FRAME16k + (2 * NB_COEF_DOWN)];

+

+	Copy(mem, signal, 2 * NB_COEF_DOWN);

+

+	Copy(sig16k, signal + (2 * NB_COEF_DOWN), lg);

+

+	lg_down = (lg * DOWN_FAC)>>15;

+

+	Down_samp(signal + NB_COEF_DOWN, sig12k8, lg_down);

+

+	Copy(signal + lg, mem, 2 * NB_COEF_DOWN);

+

+	return;

+}

+

+static void Down_samp(

+		Word16 * sig,                         /* input:  signal to downsampling  */

+		Word16 * sig_d,                       /* output: downsampled signal      */

+		Word16 L_frame_d                      /* input:  length of output        */

+		)

+{

+	Word32 i, j, frac, pos;

+	Word16 *x, *y;

+	Word32 L_sum;

+

+	pos = 0;                                 /* position is in Q2 -> 1/4 resolution  */

+	for (j = 0; j < L_frame_d; j++)

+	{

+		i = (pos >> 2);                   /* integer part     */

+		frac = pos & 3;                   /* fractional part */

+		x = sig + i - NB_COEF_DOWN + 1;

+		y = (Word16 *)(fir_down1 + frac);

+

+		L_sum = vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x++),(*y++));

+		L_sum += vo_mult32((*x),(*y));

+

+		L_sum = L_shl2(L_sum, 2);              

+		sig_d[j] = extract_h(L_add(L_sum, 0x8000)); 

+		pos += FAC5;              /* pos + 5/4 */

+	}

+	return;

+}

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/deemph.c b/media/libstagefright/codecs/amrwbenc/src/deemph.c
new file mode 100644
index 0000000..6ad528d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/deemph.c
@@ -0,0 +1,117 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: deemph.c                                                 *

+*                                                                      *

+*	   Description:filtering through 1/(1-mu z^ -1)                    *

+*	               Deemph2 --> signal is divided by 2                  *

+*				   Deemph_32 --> for 32 bits signal.                   *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+

+void Deemph(

+		Word16 x[],                           /* (i/o)   : input signal overwritten by the output */

+		Word16 mu,                            /* (i) Q15 : deemphasis factor                      */

+		Word16 L,                             /* (i)     : vector size                            */

+		Word16 * mem                          /* (i/o)   : memory (y[-1])                         */

+	   )

+{

+	Word32 i;

+	Word32 L_tmp;

+

+	L_tmp = L_deposit_h(x[0]);

+	L_tmp = L_mac(L_tmp, *mem, mu);

+	x[0] = vo_round(L_tmp);                   

+

+	for (i = 1; i < L; i++)

+	{

+		L_tmp = L_deposit_h(x[i]);

+		L_tmp = L_mac(L_tmp, x[i - 1], mu);

+		x[i] = voround(L_tmp);               

+	}

+

+	*mem = x[L - 1];                       

+

+	return;

+}

+

+

+void Deemph2(

+		Word16 x[],                           /* (i/o)   : input signal overwritten by the output */

+		Word16 mu,                            /* (i) Q15 : deemphasis factor                      */

+		Word16 L,                             /* (i)     : vector size                            */

+		Word16 * mem                          /* (i/o)   : memory (y[-1])                         */

+	    )

+{

+	Word32 i;

+	Word32 L_tmp;

+	L_tmp = x[0] << 15;

+	L_tmp += ((*mem) * mu)<<1;

+	x[0] = (L_tmp + 0x8000)>>16;                   

+	for (i = 1; i < L; i++)

+	{

+		L_tmp = x[i] << 15;

+		L_tmp += (x[i - 1] * mu)<<1;

+		x[i] = (L_tmp + 0x8000)>>16;               

+	}

+	*mem = x[L - 1];                       

+	return;

+}

+

+

+void Deemph_32(

+		Word16 x_hi[],                        /* (i)     : input signal (bit31..16) */

+		Word16 x_lo[],                        /* (i)     : input signal (bit15..4)  */

+		Word16 y[],                           /* (o)     : output signal (x16)      */

+		Word16 mu,                            /* (i) Q15 : deemphasis factor        */

+		Word16 L,                             /* (i)     : vector size              */

+		Word16 * mem                          /* (i/o)   : memory (y[-1])           */

+	      )

+{

+	Word16 fac;

+	Word32 i, L_tmp;

+

+	fac = mu >> 1;                                /* Q15 --> Q14 */

+

+	L_tmp = L_deposit_h(x_hi[0]);

+	L_tmp += (x_lo[0] * 8)<<1;

+	L_tmp = (L_tmp << 3);

+	L_tmp += ((*mem) * fac)<<1;

+	L_tmp = (L_tmp << 1);               

+	y[0] = (L_tmp + 0x8000)>>16;                  

+

+	for (i = 1; i < L; i++)

+	{

+		L_tmp = L_deposit_h(x_hi[i]);

+		L_tmp += (x_lo[i] * 8)<<1;

+		L_tmp = (L_tmp << 3);

+		L_tmp += (y[i - 1] * fac)<<1;

+		L_tmp = (L_tmp << 1);           

+		y[i] = (L_tmp + 0x8000)>>16;               

+	}

+

+	*mem = y[L - 1];                       

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/dtx.c b/media/libstagefright/codecs/amrwbenc/src/dtx.c
new file mode 100644
index 0000000..02921eb
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/dtx.c
@@ -0,0 +1,605 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: dtx.c                                                    *

+*                                                                      *

+*	    Description:DTX functions                                  *

+*                                                                      *

+************************************************************************/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "math_op.h"

+#include "cnst.h"

+#include "acelp.h"                         /* prototype of functions    */

+#include "bits.h"

+#include "dtx.h"

+#include "log2.h"

+#include "mem_align.h"

+

+static void aver_isf_history(

+		Word16 isf_old[],

+		Word16 indices[],

+		Word32 isf_aver[]

+		);

+

+static void find_frame_indices(

+		Word16 isf_old_tx[],

+		Word16 indices[],

+		dtx_encState * st

+		);

+

+static Word16 dithering_control(

+		dtx_encState * st

+		);

+

+/* excitation energy adjustment depending on speech coder mode used, Q7 */

+static Word16 en_adjust[9] =

+{

+	230,                                   /* mode0 = 7k  :  -5.4dB  */

+	179,                                   /* mode1 = 9k  :  -4.2dB  */

+	141,                                   /* mode2 = 12k :  -3.3dB  */

+	128,                                   /* mode3 = 14k :  -3.0dB  */

+	122,                                   /* mode4 = 16k :  -2.85dB */

+	115,                                   /* mode5 = 18k :  -2.7dB  */

+	115,                                   /* mode6 = 20k :  -2.7dB  */

+	115,                                   /* mode7 = 23k :  -2.7dB  */

+	115                                    /* mode8 = 24k :  -2.7dB  */

+};

+

+/**************************************************************************

+*

+* Function    : dtx_enc_init

+*

+**************************************************************************/

+Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[], VO_MEM_OPERATOR *pMemOP)

+{

+	dtx_encState *s;

+

+	if (st == (dtx_encState **) NULL)

+	{

+		fprintf(stderr, "dtx_enc_init: invalid parameter\n");

+		return -1;

+	}

+	*st = NULL;

+

+	/* allocate memory */

+	if ((s = (dtx_encState *)mem_malloc(pMemOP, sizeof(dtx_encState), 32, VO_INDEX_ENC_AMRWB)) == NULL)

+	{

+		fprintf(stderr, "dtx_enc_init: can not malloc state structure\n");

+		return -1;

+	}

+	dtx_enc_reset(s, isf_init);

+	*st = s;

+	return 0;

+}

+

+/**************************************************************************

+*

+* Function    : dtx_enc_reset

+*

+**************************************************************************/

+Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[])

+{

+	Word32 i;

+

+	if (st == (dtx_encState *) NULL)

+	{

+		fprintf(stderr, "dtx_enc_reset: invalid parameter\n");

+		return -1;

+	}

+	st->hist_ptr = 0;                      

+	st->log_en_index = 0;                  

+

+	/* Init isf_hist[] */

+	for (i = 0; i < DTX_HIST_SIZE; i++)

+	{

+		Copy(isf_init, &st->isf_hist[i * M], M);

+	}

+	st->cng_seed = RANDOM_INITSEED;       

+

+	/* Reset energy history */

+	Set_zero(st->log_en_hist, DTX_HIST_SIZE);

+

+	st->dtxHangoverCount = DTX_HANG_CONST; 

+	st->decAnaElapsedCount = 32767;        

+

+	for (i = 0; i < 28; i++)

+	{

+		st->D[i] = 0;                      

+	}

+

+	for (i = 0; i < DTX_HIST_SIZE - 1; i++)

+	{

+		st->sumD[i] = 0;                   

+	}

+

+	return 1;

+}

+

+/**************************************************************************

+*

+* Function    : dtx_enc_exit

+*

+**************************************************************************/

+void dtx_enc_exit(dtx_encState ** st, VO_MEM_OPERATOR *pMemOP)

+{

+	if (st == NULL || *st == NULL)

+		return;

+	/* deallocate memory */

+	mem_free(pMemOP, *st, VO_INDEX_ENC_AMRWB);

+	*st = NULL;

+	return;

+}

+

+

+/**************************************************************************

+*

+* Function    : dtx_enc

+*

+**************************************************************************/

+Word16 dtx_enc(

+		dtx_encState * st,                    /* i/o : State struct                                         */

+		Word16 isf[M],                        /* o   : CN ISF vector                                        */

+		Word16 * exc2,                        /* o   : CN excitation                                        */

+		Word16 ** prms

+	      )

+{

+	Word32 i, j;

+	Word16 indice[7];

+	Word16 log_en, gain, level, exp, exp0, tmp;

+	Word16 log_en_int_e, log_en_int_m;

+	Word32 L_isf[M], ener32, level32;

+	Word16 isf_order[3];

+	Word16 CN_dith;

+

+	/* VOX mode computation of SID parameters */

+	log_en = 0;

+	for (i = 0; i < M; i++)

+	{

+		L_isf[i] = 0;

+	}

+	/* average energy and isf */

+	for (i = 0; i < DTX_HIST_SIZE; i++)

+	{

+		/* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer. log_en is in Q10 */

+		log_en = add(log_en, st->log_en_hist[i]);

+

+	}

+	find_frame_indices(st->isf_hist, isf_order, st);

+	aver_isf_history(st->isf_hist, isf_order, L_isf);

+

+	for (j = 0; j < M; j++)

+	{

+		isf[j] = (Word16)(L_isf[j] >> 3);  /* divide by 8 */

+	}

+

+	/* quantize logarithmic energy to 6 bits (-6 : 66 dB) which corresponds to -2:22 in log2(E).  */

+	/* st->log_en_index = (short)( (log_en + 2.0) * 2.625 ); */

+

+	/* increase dynamics to 7 bits (Q8) */

+	log_en = (log_en >> 2);

+

+	/* Add 2 in Q8 = 512 to get log2(E) between 0:24 */

+	log_en = add(log_en, 512);

+

+	/* Multiply by 2.625 to get full 6 bit range. 2.625 = 21504 in Q13. The result is in Q6 */

+	log_en = mult(log_en, 21504);

+

+	/* Quantize Energy */

+	st->log_en_index = shr(log_en, 6);

+

+	if(st->log_en_index > 63)

+	{

+		st->log_en_index = 63;

+	}

+	if (st->log_en_index < 0)

+	{

+		st->log_en_index = 0;

+	}

+	/* Quantize ISFs */

+	Qisf_ns(isf, isf, indice);

+

+

+	Parm_serial(indice[0], 6, prms);

+	Parm_serial(indice[1], 6, prms);

+	Parm_serial(indice[2], 6, prms);

+	Parm_serial(indice[3], 5, prms);

+	Parm_serial(indice[4], 5, prms);

+

+	Parm_serial((st->log_en_index), 6, prms);

+

+	CN_dith = dithering_control(st);

+	Parm_serial(CN_dith, 1, prms);

+

+	/* level = (float)( pow( 2.0f, (float)st->log_en_index / 2.625 - 2.0 ) );    */

+	/* log2(E) in Q9 (log2(E) lies in between -2:22) */

+	log_en = shl(st->log_en_index, 15 - 6);

+

+	/* Divide by 2.625; log_en will be between 0:24  */

+	log_en = mult(log_en, 12483);

+	/* the result corresponds to log2(gain) in Q10 */

+

+	/* Find integer part  */

+	log_en_int_e = (log_en >> 10);

+

+	/* Find fractional part */

+	log_en_int_m = (Word16) (log_en & 0x3ff);

+	log_en_int_m = shl(log_en_int_m, 5);

+

+	/* Subtract 2 from log_en in Q9, i.e divide the gain by 2 (energy by 4) */

+	/* Add 16 in order to have the result of pow2 in Q16 */

+	log_en_int_e = add(log_en_int_e, 16 - 1);

+

+	level32 = Pow2(log_en_int_e, log_en_int_m); /* Q16 */

+	exp0 = norm_l(level32);

+	level32 = (level32 << exp0);        /* level in Q31 */

+	exp0 = (15 - exp0);

+	level = extract_h(level32);            /* level in Q15 */

+

+	/* generate white noise vector */

+	for (i = 0; i < L_FRAME; i++)

+	{

+		exc2[i] = (Random(&(st->cng_seed)) >> 4);

+	}

+

+	/* gain = level / sqrt(ener) * sqrt(L_FRAME) */

+

+	/* energy of generated excitation */

+	ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);

+

+	Isqrt_n(&ener32, &exp);

+

+	gain = extract_h(ener32);

+

+	gain = mult(level, gain);              /* gain in Q15 */

+

+	exp = add(exp0, exp);

+

+	/* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */

+	exp += 4;

+

+	for (i = 0; i < L_FRAME; i++)

+	{

+		tmp = mult(exc2[i], gain);         /* Q0 * Q15 */

+		exc2[i] = shl(tmp, exp); 

+	}

+

+	return 0;

+}

+

+/**************************************************************************

+*

+* Function    : dtx_buffer Purpose     : handles the DTX buffer

+*

+**************************************************************************/

+Word16 dtx_buffer(

+		dtx_encState * st,                    /* i/o : State struct                    */

+		Word16 isf_new[],                     /* i   : isf vector                      */

+		Word32 enr,                           /* i   : residual energy (in L_FRAME)    */

+		Word16 codec_mode

+		)

+{

+	Word16 log_en;

+

+	Word16 log_en_e;

+	Word16 log_en_m;

+	st->hist_ptr = add(st->hist_ptr, 1); 

+	if(st->hist_ptr == DTX_HIST_SIZE)

+	{

+		st->hist_ptr = 0;

+	}

+	/* copy lsp vector into buffer */

+	Copy(isf_new, &st->isf_hist[st->hist_ptr * M], M);

+

+	/* log_en = (float)log10(enr*0.0059322)/(float)log10(2.0f);  */

+	Log2(enr, &log_en_e, &log_en_m);

+

+	/* convert exponent and mantissa to Word16 Q7. Q7 is used to simplify averaging in dtx_enc */

+	log_en = shl(log_en_e, 7);             /* Q7 */

+	log_en = add(log_en, shr(log_en_m, 15 - 7));

+

+	/* Find energy per sample by multiplying with 0.0059322, i.e subtract log2(1/0.0059322) = 7.39722 The

+	 * constant 0.0059322 takes into account windowings and analysis length from autocorrelation

+	 * computations; 7.39722 in Q7 = 947  */

+	/* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */

+	/* log_en = sub( log_en, 947 + en_adjust[codec_mode] ); */

+

+	/* Find energy per sample (divide by L_FRAME=256), i.e subtract log2(256) = 8.0  (1024 in Q7) */

+	/* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */

+

+	log_en = sub(log_en, add(1024, en_adjust[codec_mode]));

+

+	/* Insert into the buffer */

+	st->log_en_hist[st->hist_ptr] = log_en;

+	return 0;

+}

+

+/**************************************************************************

+*

+* Function    : tx_dtx_handler Purpose     : adds extra speech hangover

+*                                            to analyze speech on

+*                                            the decoding side.

+**************************************************************************/

+void tx_dtx_handler(dtx_encState * st,     /* i/o : State struct           */

+		Word16 vad_flag,                      /* i   : vad decision           */

+		Word16 * usedMode                     /* i/o : mode changed or not    */

+		)

+{

+

+	/* this state machine is in synch with the GSMEFR txDtx machine      */

+	st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1); 

+

+	if (vad_flag != 0)

+	{

+		st->dtxHangoverCount = DTX_HANG_CONST;

+	} else

+	{                                      /* non-speech */

+		if (st->dtxHangoverCount == 0)

+		{                                  /* out of decoder analysis hangover  */

+			st->decAnaElapsedCount = 0;    

+			*usedMode = MRDTX;            

+		} else

+		{                                  /* in possible analysis hangover */

+			st->dtxHangoverCount = sub(st->dtxHangoverCount, 1);

+

+			/* decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH */

+			if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount),

+						DTX_ELAPSED_FRAMES_THRESH) < 0)

+			{

+				*usedMode = MRDTX;

+				/* if short time since decoder update, do not add extra HO */

+			}

+			/* else override VAD and stay in speech mode *usedMode and add extra hangover */

+		}

+	}

+

+	return;

+}

+

+

+

+static void aver_isf_history(

+		Word16 isf_old[],

+		Word16 indices[],

+		Word32 isf_aver[]

+		)

+{

+	Word32 i, j, k;

+	Word16 isf_tmp[2 * M];

+	Word32 L_tmp;

+

+	/* Memorize in isf_tmp[][] the ISF vectors to be replaced by */

+	/* the median ISF vector prior to the averaging               */

+	for (k = 0; k < 2; k++)

+	{

+		if ((indices[k] + 1) != 0)

+		{

+			for (i = 0; i < M; i++)

+			{

+				isf_tmp[k * M + i] = isf_old[indices[k] * M + i];      

+				isf_old[indices[k] * M + i] = isf_old[indices[2] * M + i];    

+			}

+		}

+	}

+

+	/* Perform the ISF averaging */

+	for (j = 0; j < M; j++)

+	{

+		L_tmp = 0;                      

+

+		for (i = 0; i < DTX_HIST_SIZE; i++)

+		{

+			L_tmp = L_add(L_tmp, L_deposit_l(isf_old[i * M + j]));

+		}

+		isf_aver[j] = L_tmp;              

+	}

+

+	/* Retrieve from isf_tmp[][] the ISF vectors saved prior to averaging */

+	for (k = 0; k < 2; k++)

+	{

+		if ((indices[k] + 1) != 0)

+		{

+			for (i = 0; i < M; i++)

+			{

+				isf_old[indices[k] * M + i] = isf_tmp[k * M + i];

+			}

+		}

+	}

+

+	return;

+}

+

+static void find_frame_indices(

+		Word16 isf_old_tx[],

+		Word16 indices[],

+		dtx_encState * st

+		)

+{

+	Word32 L_tmp, summin, summax, summax2nd;

+	Word16 i, j, tmp;

+	Word16 ptr;

+

+	/* Remove the effect of the oldest frame from the column */

+	/* sum sumD[0..DTX_HIST_SIZE-1]. sumD[DTX_HIST_SIZE] is    */

+	/* not updated since it will be removed later.           */

+

+	tmp = DTX_HIST_SIZE_MIN_ONE;           

+	j = -1;                                

+	for (i = 0; i < DTX_HIST_SIZE_MIN_ONE; i++)

+	{

+		j = add(j, tmp);

+		st->sumD[i] = L_sub(st->sumD[i], st->D[j]);     

+		tmp = sub(tmp, 1);

+	}

+

+	/* Shift the column sum sumD. The element sumD[DTX_HIST_SIZE-1]    */

+	/* corresponding to the oldest frame is removed. The sum of     */

+	/* the distances between the latest isf and other isfs, */

+	/* i.e. the element sumD[0], will be computed during this call. */

+	/* Hence this element is initialized to zero.                   */

+

+	for (i = DTX_HIST_SIZE_MIN_ONE; i > 0; i--)

+	{

+		st->sumD[i] = st->sumD[i - 1];     

+	}

+	st->sumD[0] = 0;                       

+

+	/* Remove the oldest frame from the distance matrix.           */

+	/* Note that the distance matrix is replaced by a one-         */

+	/* dimensional array to save static memory.                    */

+

+	tmp = 0;                               

+	for (i = 27; i >= 12; i = (Word16) (i - tmp))

+	{

+		tmp = add(tmp, 1);

+		for (j = tmp; j > 0; j--)

+		{

+			st->D[i - j + 1] = st->D[i - j - tmp];   

+		}

+	}

+

+	/* Compute the first column of the distance matrix D            */

+	/* (squared Euclidean distances from isf1[] to isf_old_tx[][]). */

+

+	ptr = st->hist_ptr;                 

+	for (i = 1; i < DTX_HIST_SIZE; i++)

+	{

+		/* Compute the distance between the latest isf and the other isfs. */

+		ptr = sub(ptr, 1);

+		if (ptr < 0)

+		{

+			ptr = DTX_HIST_SIZE_MIN_ONE;   

+		}

+		L_tmp = 0;                         

+		for (j = 0; j < M; j++)

+		{

+			tmp = sub(isf_old_tx[st->hist_ptr * M + j], isf_old_tx[ptr * M + j]);

+			L_tmp = L_mac(L_tmp, tmp, tmp);

+		}

+		st->D[i - 1] = L_tmp;           

+

+		/* Update also the column sums. */

+		st->sumD[0] = L_add(st->sumD[0], st->D[i - 1]); 

+		st->sumD[i] = L_add(st->sumD[i], st->D[i - 1]); 

+	}

+

+	/* Find the minimum and maximum distances */

+	summax = st->sumD[0];                  

+	summin = st->sumD[0];                  

+	indices[0] = 0;                        

+	indices[2] = 0;                        

+	for (i = 1; i < DTX_HIST_SIZE; i++)

+	{

+		if (L_sub(st->sumD[i], summax) > 0)

+		{

+			indices[0] = i;                

+			summax = st->sumD[i];          

+		}

+		if (L_sub(st->sumD[i], summin) < 0)

+		{

+			indices[2] = i;                

+			summin = st->sumD[i];          

+		}

+	}

+

+	/* Find the second largest distance */

+	summax2nd = -2147483647L;              

+	indices[1] = -1;                       

+	for (i = 0; i < DTX_HIST_SIZE; i++)

+	{

+		if ((L_sub(st->sumD[i], summax2nd) > 0) && (sub(i, indices[0]) != 0))

+		{

+			indices[1] = i;                

+			summax2nd = st->sumD[i];       

+		}

+	}

+

+	for (i = 0; i < 3; i++)

+	{

+		indices[i] = sub(st->hist_ptr, indices[i]);     

+		if (indices[i] < 0)

+		{

+			indices[i] = add(indices[i], DTX_HIST_SIZE);       

+		}

+	}

+

+	/* If maximum distance/MED_THRESH is smaller than minimum distance */

+	/* then the median ISF vector replacement is not performed         */

+	tmp = norm_l(summax);

+	summax = (summax << tmp);

+	summin = (summin << tmp);

+	L_tmp = L_mult(voround(summax), INV_MED_THRESH);

+	if(L_tmp <= summin)

+	{

+		indices[0] = -1; 

+	}

+	/* If second largest distance/MED_THRESH is smaller than     */

+	/* minimum distance then the median ISF vector replacement is    */

+	/* not performed                                                 */

+	summax2nd = L_shl(summax2nd, tmp);

+	L_tmp = L_mult(voround(summax2nd), INV_MED_THRESH);

+	if(L_tmp <= summin)

+	{

+		indices[1] = -1;                 

+	}

+	return;

+}

+

+static Word16 dithering_control(

+		dtx_encState * st

+		)

+{

+	Word16 tmp, mean, CN_dith, gain_diff;

+	Word32 i, ISF_diff;

+

+	/* determine how stationary the spectrum of background noise is */

+	ISF_diff = 0;

+	for (i = 0; i < 8; i++)

+	{

+		ISF_diff = L_add(ISF_diff, st->sumD[i]);

+	}

+	if ((ISF_diff >> 26) > 0)

+	{

+		CN_dith = 1;

+	} else

+	{

+		CN_dith = 0;

+	}

+

+	/* determine how stationary the energy of background noise is */

+	mean = 0;

+	for (i = 0; i < DTX_HIST_SIZE; i++)

+	{

+		mean = add(mean, st->log_en_hist[i]);

+	}

+	mean = (mean >> 3);

+	gain_diff = 0;

+	for (i = 0; i < DTX_HIST_SIZE; i++)

+	{

+		tmp = abs_s(sub(st->log_en_hist[i], mean));

+		gain_diff = add(gain_diff, tmp);

+	}

+	if (gain_diff > GAIN_THR)

+	{

+		CN_dith = 1;

+	}

+	return CN_dith;

+}

diff --git a/media/libstagefright/codecs/amrwbenc/src/g_pitch.c b/media/libstagefright/codecs/amrwbenc/src/g_pitch.c
new file mode 100644
index 0000000..570138e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/g_pitch.c
@@ -0,0 +1,79 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: g_pitch.c                                                 *

+*                                                                      *

+*	   Description:Compute the gain of pitch. Result in Q12        *

+*	               if(gain < 0) gain = 0                           *

+*				   if(gain > 1.2) gain = 1.2           *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+

+Word16 G_pitch(                            /* (o) Q14 : Gain of pitch lag saturated to 1.2   */

+		Word16 xn[],                          /* (i)     : Pitch target.                        */

+		Word16 y1[],                          /* (i)     : filtered adaptive codebook.          */

+		Word16 g_coeff[],                     /* : Correlations need for gain quantization.     */

+		Word16 L_subfr                        /* : Length of subframe.                          */

+	      )

+{

+	Word32 i;

+	Word16 xy, yy, exp_xy, exp_yy, gain;

+	/* Compute scalar product <y1[],y1[]> */

+#ifdef ASM_OPT                  /* asm optimization branch */

+	/* Compute scalar product <xn[],y1[]> */

+	xy = extract_h(Dot_product12_asm(xn, y1, L_subfr, &exp_xy));

+	yy = extract_h(Dot_product12_asm(y1, y1, L_subfr, &exp_yy));

+

+#else

+	/* Compute scalar product <xn[],y1[]> */

+	xy = extract_h(Dot_product12(xn, y1, L_subfr, &exp_xy));

+	yy = extract_h(Dot_product12(y1, y1, L_subfr, &exp_yy));

+

+#endif

+

+	g_coeff[0] = yy;                       

+	g_coeff[1] = exp_yy;                   

+	g_coeff[2] = xy;                       

+	g_coeff[3] = exp_xy;                   

+

+	/* If (xy < 0) gain = 0 */

+	if (xy < 0)

+		return ((Word16) 0);

+

+	/* compute gain = xy/yy */

+

+	xy >>= 1;                       /* Be sure xy < yy */

+	gain = div_s(xy, yy);

+

+	i = exp_xy;

+	i -= exp_yy;

+

+	gain = shl(gain, i);                   

+

+	/* if (gain > 1.2) gain = 1.2  in Q14 */

+	if(gain > 19661)

+	{

+		gain = 19661;                      

+	}

+	return (gain);

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/gpclip.c b/media/libstagefright/codecs/amrwbenc/src/gpclip.c
new file mode 100644
index 0000000..e23f2f4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/gpclip.c
@@ -0,0 +1,110 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/**************************************************************************

+*      File: gpclip.c                                                     *

+*                                                                         *

+*      Description:To avoid unstable synthesis on frame erasure, the gain *

+*      need to be limited(gain pitch < 1.0) when the following            *

+*      case occurs                                                        *

+*      a resonance on LPC filter(lp_disp < 60Hz)                          *

+*      a good pitch prediction (lp_gp > 0.95)                             *

+*                                                                         *   

+***************************************************************************/

+#include "typedef.h"

+#include "basic_op.h"

+

+#define DIST_ISF_MAX    307                /* 120 Hz (6400Hz=16384) */

+#define DIST_ISF_THRES  154                /* 60     (6400Hz=16384) */

+#define GAIN_PIT_THRES  14746              /* 0.9 in Q14 */

+#define GAIN_PIT_MIN    9830               /* 0.6 in Q14 */

+#define M               16

+

+

+void Init_gp_clip(

+		Word16 mem[]                          /* (o) : memory of gain of pitch clipping algorithm */

+		)

+{

+	mem[0] = DIST_ISF_MAX;                 

+	mem[1] = GAIN_PIT_MIN;                 

+}

+

+

+Word16 Gp_clip(

+		Word16 mem[]                          /* (i/o) : memory of gain of pitch clipping algorithm */

+	      )

+{

+	Word16 clip = 0;

+	if ((mem[0] < DIST_ISF_THRES) && (mem[1] > GAIN_PIT_THRES))

+		clip = 1;                          

+

+	return (clip);

+}

+

+

+void Gp_clip_test_isf(

+		Word16 isf[],                         /* (i)   : isf values (in frequency domain)           */

+		Word16 mem[]                          /* (i/o) : memory of gain of pitch clipping algorithm */

+		)

+{

+	Word16 dist, dist_min;

+	Word32 i;

+

+	dist_min = vo_sub(isf[1], isf[0]);

+

+	for (i = 2; i < M - 1; i++)

+	{

+		dist = vo_sub(isf[i], isf[i - 1]);

+		if(dist < dist_min)

+		{

+			dist_min = dist;               

+		}

+	}

+

+	dist = extract_h(L_mac(vo_L_mult(26214, mem[0]), 6554, dist_min));

+

+	if (dist > DIST_ISF_MAX)

+	{

+		dist = DIST_ISF_MAX;               

+	}

+	mem[0] = dist;                        

+

+	return;

+}

+

+

+void Gp_clip_test_gain_pit(

+		Word16 gain_pit,                      /* (i) Q14 : gain of quantized pitch                    */

+		Word16 mem[]                          /* (i/o)   : memory of gain of pitch clipping algorithm */

+		)

+{

+	Word16 gain;

+	Word32 L_tmp;

+	L_tmp = (29491 * mem[1])<<1;

+	L_tmp += (3277 * gain_pit)<<1;

+

+	gain = extract_h(L_tmp);

+

+	if(gain < GAIN_PIT_MIN)

+	{

+		gain = GAIN_PIT_MIN;              

+	}

+	mem[1] = gain;                         

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/homing.c b/media/libstagefright/codecs/amrwbenc/src/homing.c
new file mode 100644
index 0000000..015633f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/homing.c
@@ -0,0 +1,46 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: homing.c                                                 *

+*                                                                      *

+*       Description:Performs the homing routines                       *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "cnst.h"

+#include "basic_op.h"

+#include "bits.h"

+#include "homing.tab"

+

+Word16 encoder_homing_frame_test(Word16 input_frame[])

+{

+	Word32 i;

+	Word16 j = 0;

+

+	/* check 320 input samples for matching EHF_MASK: defined in e_homing.h */

+	for (i = 0; i < L_FRAME16k; i++)

+	{

+		j = (Word16) (input_frame[i] ^ EHF_MASK);

+

+		if (j)

+			break;

+	}

+

+	return (Word16) (!j);

+}

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/hp400.c b/media/libstagefright/codecs/amrwbenc/src/hp400.c
new file mode 100644
index 0000000..463a53a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/hp400.c
@@ -0,0 +1,106 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: hp400.c                                                    *

+*                                                                       *

+*      Description:                                                     *

+* 2nd order high pass filter with cut off frequency at 400 Hz.          *

+* Designed with cheby2 function in MATLAB.                              *

+* Optimized for fixed-point to get the following frequency response:    *

+*                                                                       *

+*  frequency:     0Hz   100Hz  200Hz  300Hz  400Hz  630Hz  1.5kHz  3kHz *

+*  dB loss:     -infdB  -30dB  -20dB  -10dB  -3dB   +6dB    +1dB    0dB *

+*                                                                       *

+* Algorithm:                                                            *

+*                                                                       *

+*  y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]                         *

+*                   + a[1]*y[i-1] + a[2]*y[i-2];                        *

+*                                                                       *

+*  Word16 b[3] = {3660, -7320,  3660};       in Q12                     *

+*  Word16 a[3] = {4096,  7320, -3540};       in Q12                     *

+*                                                                       *

+*  float -->   b[3] = {0.893554687, -1.787109375,  0.893554687};        *

+*              a[3] = {1.000000000,  1.787109375, -0.864257812};        *

+*                                                                       *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "acelp.h"

+

+/* filter coefficients  */

+static Word16 b[3] = {915, -1830, 915};         /* Q12 (/4) */

+static Word16 a[3] = {16384, 29280, -14160};    /* Q12 (x4) */

+/* Initialization of static values */

+

+void Init_HP400_12k8(Word16 mem[])

+{

+	Set_zero(mem, 6);

+}

+

+

+void HP400_12k8(

+		Word16 signal[],                      /* input signal / output is divided by 16 */

+		Word16 lg,                            /* lenght of signal    */

+		Word16 mem[]                          /* filter memory [6]   */

+	       )

+{

+	Word16  x2;

+	Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;

+	Word32 L_tmp;

+	Word32 num;

+	y2_hi = *mem++;

+	y2_lo = *mem++;

+	y1_hi = *mem++;

+	y1_lo = *mem++;

+	x0 = *mem++;   

+	x1 = *mem;   

+	num = (Word32)lg;

+	do

+	{

+		x2 = x1;

+		x1 = x0;

+		x0 = *signal;

+		/* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2]  */

+		/* + a[1]*y[i-1] + a[2] * y[i-2];  */

+		L_tmp = 8192L;                    /* rounding to maximise precision */

+		L_tmp += y1_lo * a[1];

+		L_tmp += y2_lo * a[2];

+		L_tmp = L_tmp >> 14;

+		L_tmp += (y1_hi * a[1] + y2_hi * a[2] + (x0 + x2)* b[0] + x1 * b[1]) << 1;

+		L_tmp <<= 1;           /* coeff Q12 --> Q13 */

+		y2_hi = y1_hi;

+		y2_lo = y1_lo;

+		y1_hi = (Word16)(L_tmp>>16);

+		y1_lo = (Word16)((L_tmp & 0xffff)>>1);

+

+		/* signal is divided by 16 to avoid overflow in energy computation */

+		*signal++ = (L_tmp + 0x8000) >> 16;

+	}while(--num !=0);

+

+	*mem-- = x1;

+	*mem-- = x0;

+	*mem-- = y1_lo;

+	*mem-- = y1_hi;

+	*mem-- = y2_lo;

+	*mem   = y2_hi;  

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/hp50.c b/media/libstagefright/codecs/amrwbenc/src/hp50.c
new file mode 100644
index 0000000..53e3d7b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/hp50.c
@@ -0,0 +1,106 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: hp50.c                                                     *

+*                                                                       *

+*	   Description:                                                 *

+* 2nd order high pass filter with cut off frequency at 31 Hz.           *

+* Designed with cheby2 function in MATLAB.                              *

+* Optimized for fixed-point to get the following frequency response:    *

+*                                                                       *

+*  frequency:     0Hz    14Hz  24Hz   31Hz   37Hz   41Hz   47Hz         *

+*  dB loss:     -infdB  -15dB  -6dB   -3dB  -1.5dB  -1dB  -0.5dB        *

+*                                                                       *

+* Algorithm:                                                            *

+*                                                                       *

+*  y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2]                         *

+*                   + a[1]*y[i-1] + a[2]*y[i-2];                        *

+*                                                                       *

+*  Word16 b[3] = {4053, -8106, 4053};       in Q12                      *

+*  Word16 a[3] = {8192, 16211, -8021};       in Q12                     *

+*                                                                       *

+*  float -->   b[3] = {0.989501953, -1.979003906,  0.989501953};        *

+*              a[3] = {1.000000000,  1.978881836, -0.979125977};        *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "cnst.h"

+#include "acelp.h"

+

+/* filter coefficients  */

+static Word16 b[3] = {4053, -8106, 4053};  /* Q12 */

+static Word16 a[3] = {8192, 16211, -8021}; /* Q12 (x2) */

+

+/* Initialization of static values */

+

+void Init_HP50_12k8(Word16 mem[])

+{

+	Set_zero(mem, 6);

+}

+

+

+void HP50_12k8(

+		Word16 signal[],                      /* input/output signal */

+		Word16 lg,                            /* lenght of signal    */

+		Word16 mem[]                          /* filter memory [6]   */

+	      )

+{

+	Word16 x2;

+	Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;

+	Word32 L_tmp;

+	Word32 num;

+

+	y2_hi = *mem++;

+	y2_lo = *mem++;

+	y1_hi = *mem++;

+	y1_lo = *mem++;

+	x0 = *mem++;   

+	x1 = *mem;

+	num = (Word32)lg;

+	do

+	{

+		x2 = x1;

+		x1 = x0;

+		x0 = *signal;

+		/* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2]  */

+		/* + a[1]*y[i-1] + a[2] * y[i-2];  */

+		L_tmp = 8192 ;                    /* rounding to maximise precision */

+		L_tmp += y1_lo * a[1];

+		L_tmp += y2_lo * a[2];

+		L_tmp = L_tmp >> 14;

+		L_tmp += (y1_hi * a[1] + y2_hi * a[2] + (x0 + x2) * b[0] + x1 * b[1]) << 1;

+		L_tmp <<= 2;           /* coeff Q12 --> Q13 */

+		y2_hi = y1_hi;

+		y2_lo = y1_lo;

+		y1_hi = (Word16)(L_tmp>>16);

+		y1_lo = (Word16)((L_tmp & 0xffff)>>1);

+		*signal++ = extract_h((L_add((L_tmp<<1), 0x8000)));

+	}while(--num !=0);

+

+	*mem-- = x1;

+	*mem-- = x0;

+	*mem-- = y1_lo;

+	*mem-- = y1_hi;

+	*mem-- = y2_lo;

+	*mem-- = y2_hi;  

+

+	return;

+}

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/hp6k.c b/media/libstagefright/codecs/amrwbenc/src/hp6k.c
new file mode 100644
index 0000000..5ee5b20
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/hp6k.c
@@ -0,0 +1,93 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: hp6k.c                                                    *

+*                                                                       *

+*	Description:15th order band pass 6kHz to 7kHz FIR filter        *

+*       frequency: 4kHz   5kHz  5.5kHz  6kHz  6.5kHz  7kHz 7.5kHz 8kHz  *

+*	dB loss:  -60dB  -45dB  -13dB   -3dB   0dB    -3dB -13dB  -45dB *

+*	                                                                *                                                                 

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "acelp.h"

+#include "cnst.h"

+

+#define L_FIR 31

+

+/* filter coefficients (gain=4.0) */

+

+Word16 fir_6k_7k[L_FIR] =

+{

+	-32, 47, 32, -27, -369,

+	1122, -1421, 0, 3798, -8880,

+	12349, -10984, 3548, 7766, -18001,

+	22118, -18001, 7766, 3548, -10984,

+	12349, -8880, 3798, 0, -1421,

+	1122, -369, -27, 32, 47,

+	-32

+};

+

+

+void Init_Filt_6k_7k(Word16 mem[])         /* mem[30] */

+{

+	Set_zero(mem, L_FIR - 1);

+	return;

+}

+

+void Filt_6k_7k(

+		Word16 signal[],                      /* input:  signal                  */

+		Word16 lg,                            /* input:  length of input         */

+		Word16 mem[]                          /* in/out: memory (size=30)        */

+	       )

+{

+	Word16 x[L_SUBFR16k + (L_FIR - 1)];

+	Word32 i, L_tmp;

+

+	Copy(mem, x, L_FIR - 1);

+	for (i = lg - 1; i >= 0; i--)

+	{

+		x[i + L_FIR - 1] = signal[i] >> 2;                         /* gain of filter = 4 */

+	}	

+	for (i = 0; i < lg; i++)

+	{

+		L_tmp =  (x[i] + x[i+ 30]) * fir_6k_7k[0];

+		L_tmp += (x[i+1] + x[i + 29]) * fir_6k_7k[1];

+		L_tmp += (x[i+2] + x[i + 28]) * fir_6k_7k[2];

+		L_tmp += (x[i+3] + x[i + 27]) * fir_6k_7k[3];

+		L_tmp += (x[i+4] + x[i + 26]) * fir_6k_7k[4];

+		L_tmp += (x[i+5] + x[i + 25]) * fir_6k_7k[5];

+		L_tmp += (x[i+6] + x[i + 24]) * fir_6k_7k[6];

+		L_tmp += (x[i+7] + x[i + 23]) * fir_6k_7k[7];

+		L_tmp += (x[i+8] + x[i + 22]) * fir_6k_7k[8];

+		L_tmp += (x[i+9] + x[i + 21]) * fir_6k_7k[9];

+		L_tmp += (x[i+10] + x[i + 20]) * fir_6k_7k[10];

+		L_tmp += (x[i+11] + x[i + 19]) * fir_6k_7k[11];

+		L_tmp += (x[i+12] + x[i + 18]) * fir_6k_7k[12];

+		L_tmp += (x[i+13] + x[i + 17]) * fir_6k_7k[13];

+		L_tmp += (x[i+14] + x[i + 16]) * fir_6k_7k[14];

+		L_tmp += (x[i+15]) * fir_6k_7k[15];

+		signal[i] = (L_tmp + 0x4000) >> 15;

+	}

+

+	Copy(x + lg, mem, L_FIR - 1);

+

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c b/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c
new file mode 100644
index 0000000..7fb62a4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c
@@ -0,0 +1,148 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: hp_wsp.c                                                  *

+*       Description:                                                    *

+*       3nd order high pass filter with cut off frequency at 180Hz      *

+* Algorithm:                                                            *

+*                                                                       *

+*  y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] + b[3]*x[i-3]           *

+*                   + a[1]*y[i-1] + a[2]*y[i-2] + a[3]*y[i-3];          *

+*                                                                       *

+* float a_coef[HP_ORDER]= {                                             *

+*    -2.64436711600664f,                                                *

+*    2.35087386625360f,                                                 *

+*   -0.70001156927424f};                                                *

+*                                                                       *

+* float b_coef[HP_ORDER+1]= {                                           *

+*     -0.83787057505665f,                                               *

+*    2.50975570071058f,                                                 *

+*   -2.50975570071058f,                                                 *

+*    0.83787057505665f};                                                *

+*                                                                       *

+*************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "acelp.h"

+

+/* filter coefficients in Q12 */

+static Word16 a[4] = {8192, 21663, -19258, 5734};

+static Word16 b[4] = {-3432, +10280, -10280, +3432};

+

+/* Initialization of static values */

+void Init_Hp_wsp(Word16 mem[])

+{

+	Set_zero(mem, 9);

+

+	return;

+}

+

+void scale_mem_Hp_wsp(Word16 mem[], Word16 exp)

+{

+	Word32 i;

+	Word32 L_tmp;

+

+	for (i = 0; i < 6; i += 2)

+	{

+		L_tmp = ((mem[i] << 16) + (mem[i + 1]<<1));

+		L_tmp = L_shl(L_tmp, exp);

+		mem[i] = L_tmp >> 16;

+		mem[i + 1] = (L_tmp & 0xffff)>>1;

+	}

+

+	for (i = 6; i < 9; i++)

+	{

+		L_tmp = L_deposit_h(mem[i]);       /* x[i] */

+		L_tmp = L_shl(L_tmp, exp);

+		mem[i] = vo_round(L_tmp);

+	}

+

+	return;

+}

+

+

+void Hp_wsp(

+		Word16 wsp[],                         /* i   : wsp[]  signal       */

+		Word16 hp_wsp[],                      /* o   : hypass wsp[]        */

+		Word16 lg,                            /* i   : lenght of signal    */

+		Word16 mem[]                          /* i/o : filter memory [9]   */

+	   )

+{

+	Word16 x0, x1, x2, x3;

+	Word16 y3_hi, y3_lo, y2_hi, y2_lo, y1_hi, y1_lo;

+	Word32 i, L_tmp;

+

+	y3_hi = mem[0];                        

+	y3_lo = mem[1];                        

+	y2_hi = mem[2];                        

+	y2_lo = mem[3];                        

+	y1_hi = mem[4];                        

+	y1_lo = mem[5];                        

+	x0 = mem[6];                           

+	x1 = mem[7];                           

+	x2 = mem[8];                           

+

+	for (i = 0; i < lg; i++)

+	{

+		x3 = x2;                           

+		x2 = x1;                           

+		x1 = x0;                           

+		x0 = wsp[i];                       

+		/* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] + b[3]*x[i-3]  */

+		/* + a[1]*y[i-1] + a[2] * y[i-2]  + a[3]*y[i-3]  */

+

+		L_tmp = 16384L;                    /* rounding to maximise precision */

+		L_tmp += (y1_lo * a[1])<<1;

+		L_tmp += (y2_lo * a[2])<<1;

+		L_tmp += (y3_lo * a[3])<<1;

+		L_tmp = L_tmp >> 15;

+		L_tmp += (y1_hi * a[1])<<1;

+		L_tmp += (y2_hi * a[2])<<1;

+		L_tmp += (y3_hi * a[3])<<1;

+		L_tmp += (x0 * b[0])<<1;

+		L_tmp += (x1 * b[1])<<1;

+		L_tmp += (x2 * b[2])<<1;

+		L_tmp += (x3 * b[3])<<1;

+

+		L_tmp = L_tmp << 2;

+

+		y3_hi = y2_hi;                     

+		y3_lo = y2_lo;                     

+		y2_hi = y1_hi;                     

+		y2_lo = y1_lo; 

+		y1_hi = L_tmp >> 16;

+		y1_lo = (L_tmp & 0xffff) >>1;

+

+		hp_wsp[i] = (L_tmp + 0x4000)>>15;          

+	}

+

+	mem[0] = y3_hi;                        

+	mem[1] = y3_lo;                        

+	mem[2] = y2_hi;                        

+	mem[3] = y2_lo;                        

+	mem[4] = y1_hi;                        

+	mem[5] = y1_lo;                        

+	mem[6] = x0;                           

+	mem[7] = x1;                           

+	mem[8] = x2;                           

+

+	return;

+}

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/int_lpc.c b/media/libstagefright/codecs/amrwbenc/src/int_lpc.c
new file mode 100644
index 0000000..be1fd0b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/int_lpc.c
@@ -0,0 +1,66 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: int_lpc.c                                                 *

+*                                                                      *

+*      Description:Interpolation of the LP parameters in 4 subframes.  *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "cnst.h"

+#include "acelp.h"

+

+#define MP1 (M+1)

+

+

+void Int_isp(

+		Word16 isp_old[],                     /* input : isps from past frame              */

+		Word16 isp_new[],                     /* input : isps from present frame           */

+		Word16 frac[],                        /* input : fraction for 3 first subfr (Q15)  */

+		Word16 Az[]                           /* output: LP coefficients in 4 subframes    */

+	    )

+{

+	Word32 i, k; 

+	Word16 fac_old, fac_new;

+	Word16 isp[M];

+	Word32 L_tmp;

+

+	for (k = 0; k < 3; k++)

+	{

+		fac_new = frac[k];                

+		fac_old = (32767 - fac_new) + 1;  /* 1.0 - fac_new */

+

+		for (i = 0; i < M; i++)

+		{

+			L_tmp = (isp_old[i] * fac_old)<<1;

+			L_tmp += (isp_new[i] * fac_new)<<1;

+			isp[i] = (L_tmp + 0x8000)>>16;        

+		}

+		Isp_Az(isp, Az, M, 0);

+		Az += MP1;

+	}

+

+	/* 4th subframe: isp_new (frac=1.0) */

+	Isp_Az(isp_new, Az, M, 0);

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/isp_az.c b/media/libstagefright/codecs/amrwbenc/src/isp_az.c
new file mode 100644
index 0000000..7b44d12
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/isp_az.c
@@ -0,0 +1,247 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: isp_az.c                                                  *

+*                                                                      *

+*      Description:Compute the LPC coefficients from isp (order=M)     *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "cnst.h"

+

+#define NC (M/2)

+#define NC16k (M16k/2)

+

+/* local function */

+

+static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n);

+static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n);

+

+void Isp_Az(

+		Word16 isp[],                         /* (i) Q15 : Immittance spectral pairs            */

+		Word16 a[],                           /* (o) Q12 : predictor coefficients (order = M)   */

+		Word16 m,

+		Word16 adaptive_scaling               /* (i) 0   : adaptive scaling disabled */

+		                                      /*     1   : adaptive scaling enabled  */

+	   )

+{

+	Word32 i, j; 

+	Word16 hi, lo;

+	Word32 f1[NC16k + 1], f2[NC16k];

+	Word16 nc;

+	Word32 t0;

+	Word16 q, q_sug;

+	Word32 tmax;

+

+	nc = (m >> 1);

+	if(nc > 8)

+	{

+		Get_isp_pol_16kHz(&isp[0], f1, nc);

+		for (i = 0; i <= nc; i++)

+		{

+			f1[i] = f1[i] << 2;

+		}

+	} else

+		Get_isp_pol(&isp[0], f1, nc);

+

+	if (nc > 8)

+	{

+		Get_isp_pol_16kHz(&isp[1], f2, (nc - 1));

+		for (i = 0; i <= nc - 1; i++)

+		{

+			f2[i] = f2[i] << 2;

+		}

+	} else

+		Get_isp_pol(&isp[1], f2, (nc - 1));

+

+	/*-----------------------------------------------------*

+	 *  Multiply F2(z) by (1 - z^-2)                       *

+	 *-----------------------------------------------------*/

+

+	for (i = (nc - 1); i > 1; i--)

+	{

+		f2[i] = vo_L_sub(f2[i], f2[i - 2]);          /* f2[i] -= f2[i-2]; */

+	}

+

+	/*----------------------------------------------------------*

+	 *  Scale F1(z) by (1+isp[m-1])  and  F2(z) by (1-isp[m-1]) *

+	 *----------------------------------------------------------*/

+

+	for (i = 0; i < nc; i++)

+	{

+		/* f1[i] *= (1.0 + isp[M-1]); */

+

+		hi = f1[i] >> 16;

+		lo = (f1[i] & 0xffff)>>1;

+

+		t0 = Mpy_32_16(hi, lo, isp[m - 1]);

+		f1[i] = vo_L_add(f1[i], t0); 

+

+		/* f2[i] *= (1.0 - isp[M-1]); */

+

+		hi = f2[i] >> 16;

+		lo = (f2[i] & 0xffff)>>1;

+		t0 = Mpy_32_16(hi, lo, isp[m - 1]);

+		f2[i] = vo_L_sub(f2[i], t0); 

+	}

+

+	/*-----------------------------------------------------*

+	 *  A(z) = (F1(z)+F2(z))/2                             *

+	 *  F1(z) is symmetric and F2(z) is antisymmetric      *

+	 *-----------------------------------------------------*/

+

+	/* a[0] = 1.0; */

+	a[0] = 4096;  

+	tmax = 1;                            

+	for (i = 1, j = m - 1; i < nc; i++, j--)

+	{

+		/* a[i] = 0.5*(f1[i] + f2[i]); */

+

+		t0 = vo_L_add(f1[i], f2[i]);          /* f1[i] + f2[i]             */

+		tmax |= L_abs(t0);                 

+		a[i] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */

+

+		/* a[j] = 0.5*(f1[i] - f2[i]); */

+

+		t0 = vo_L_sub(f1[i], f2[i]);          /* f1[i] - f2[i]             */

+		tmax |= L_abs(t0);                

+		a[j] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */

+	}

+

+	/* rescale data if overflow has occured and reprocess the loop */

+	if(adaptive_scaling == 1)

+		q = 4 - norm_l(tmax);        /* adaptive scaling enabled */

+	else

+		q = 0;                           /* adaptive scaling disabled */

+

+	if (q > 0)

+	{

+		q_sug = (12 + q);

+		for (i = 1, j = m - 1; i < nc; i++, j--)

+		{

+			/* a[i] = 0.5*(f1[i] + f2[i]); */

+			t0 = vo_L_add(f1[i], f2[i]);          /* f1[i] + f2[i]             */

+			a[i] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */

+

+			/* a[j] = 0.5*(f1[i] - f2[i]); */

+			t0 = vo_L_sub(f1[i], f2[i]);          /* f1[i] - f2[i]             */

+			a[j] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */

+		}

+		a[0] = shr(a[0], q); 

+	}

+	else

+	{

+		q_sug = 12; 

+		q     = 0; 

+	}

+	/* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */

+	hi = f1[nc] >> 16;

+	lo = (f1[nc] & 0xffff)>>1;

+	t0 = Mpy_32_16(hi, lo, isp[m - 1]);

+	t0 = vo_L_add(f1[nc], t0);

+	a[nc] = (Word16)(L_shr_r(t0, q_sug));    /* from Q23 to Q12 and * 0.5 */

+	/* a[m] = isp[m-1]; */

+

+	a[m] = vo_shr_r(isp[m - 1], (3 + q));           /* from Q15 to Q12          */

+	return;

+}

+

+/*-----------------------------------------------------------*

+* procedure Get_isp_pol:                                    *

+*           ~~~~~~~~~~~                                     *

+*   Find the polynomial F1(z) or F2(z) from the ISPs.       *

+* This is performed by expanding the product polynomials:   *

+*                                                           *

+* F1(z) =   product   ( 1 - 2 isp_i z^-1 + z^-2 )           *

+*         i=0,2,4,6,8                                       *

+* F2(z) =   product   ( 1 - 2 isp_i z^-1 + z^-2 )           *

+*         i=1,3,5,7                                         *

+*                                                           *

+* where isp_i are the ISPs in the cosine domain.            *

+*-----------------------------------------------------------*

+*                                                           *

+* Parameters:                                               *

+*  isp[]   : isp vector (cosine domaine)         in Q15     *

+*  f[]     : the coefficients of F1 or F2        in Q23     *

+*  n       : == NC for F1(z); == NC-1 for F2(z)             *

+*-----------------------------------------------------------*/

+

+static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n)

+{

+	Word16 hi, lo;

+	Word32 i, j, t0;

+	/* All computation in Q23 */

+

+	f[0] = vo_L_mult(4096, 1024);               /* f[0] = 1.0;        in Q23  */

+	f[1] = vo_L_mult(isp[0], -256);             /* f[1] = -2.0*isp[0] in Q23  */

+

+	f += 2;                                  /* Advance f pointer          */

+	isp += 2;                                /* Advance isp pointer        */

+	for (i = 2; i <= n; i++)

+	{

+		*f = f[-2];                        

+		for (j = 1; j < i; j++, f--)

+		{

+			hi = f[-1]>>16;

+			lo = (f[-1] & 0xffff)>>1;

+

+			t0 = Mpy_32_16(hi, lo, *isp);  /* t0 = f[-1] * isp    */

+			t0 = t0 << 1;

+			*f = vo_L_sub(*f, t0);              /* *f -= t0            */

+			*f = vo_L_add(*f, f[-2]);           /* *f += f[-2]         */

+		}

+		*f -= (*isp << 9);           /* *f -= isp<<8        */

+		f += i;                            /* Advance f pointer   */

+		isp += 2;                          /* Advance isp pointer */

+	}

+	return;

+}

+

+static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n)

+{

+	Word16 hi, lo;

+	Word32 i, j, t0;

+

+	/* All computation in Q23 */

+	f[0] = L_mult(4096, 256);                /* f[0] = 1.0;        in Q23  */

+	f[1] = L_mult(isp[0], -64);              /* f[1] = -2.0*isp[0] in Q23  */

+

+	f += 2;                                  /* Advance f pointer          */

+	isp += 2;                                /* Advance isp pointer        */

+

+	for (i = 2; i <= n; i++)

+	{

+		*f = f[-2];                        

+		for (j = 1; j < i; j++, f--)

+		{

+			VO_L_Extract(f[-1], &hi, &lo);

+			t0 = Mpy_32_16(hi, lo, *isp);  /* t0 = f[-1] * isp    */

+			t0 = L_shl2(t0, 1);

+			*f = L_sub(*f, t0);              /* *f -= t0            */

+			*f = L_add(*f, f[-2]);           /* *f += f[-2]         */

+		}

+		*f = L_msu(*f, *isp, 64);            /* *f -= isp<<8        */

+		f += i;                            /* Advance f pointer   */

+		isp += 2;                          /* Advance isp pointer */

+	}

+	return;

+}

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/isp_isf.c b/media/libstagefright/codecs/amrwbenc/src/isp_isf.c
new file mode 100644
index 0000000..6c6e389
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/isp_isf.c
@@ -0,0 +1,91 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: isp_isf.c                                                *

+*                                                                      *

+*       Description:                                                   *

+*	Isp_isf   Transformation isp to isf                            *

+*	Isf_isp   Transformation isf to isp                            *

+*                                                                      *

+*	The transformation from isp[i] to isf[i] and isf[i] to isp[i]  *

+*	are approximated by a look-up table and interpolation          *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "isp_isf.tab"                     /* Look-up table for transformations */

+

+void Isp_isf(

+		Word16 isp[],                         /* (i) Q15 : isp[m] (range: -1<=val<1)                */

+		Word16 isf[],                         /* (o) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */

+		Word16 m                              /* (i)     : LPC order                                */

+	    )

+{

+	Word32 i, ind;

+	Word32 L_tmp;

+	ind = 127;                               /* beging at end of table -1 */

+	for (i = (m - 1); i >= 0; i--)

+	{

+		if (i >= (m - 2))

+		{                                  /* m-2 is a constant */

+			ind = 127;                       /* beging at end of table -1 */

+		}

+		/* find value in table that is just greater than isp[i] */

+		while (table[ind] < isp[i])

+			ind--;

+		/* acos(isp[i])= ind*128 + ( ( isp[i]-table[ind] ) * slope[ind] )/2048 */

+		L_tmp = vo_L_mult(vo_sub(isp[i], table[ind]), slope[ind]);

+		isf[i] = vo_round((L_tmp << 4));   /* (isp[i]-table[ind])*slope[ind])>>11 */

+		isf[i] = add1(isf[i], (ind << 7)); 

+	}

+	isf[m - 1] = (isf[m - 1] >> 1);      

+	return;

+}

+

+

+void Isf_isp(

+		Word16 isf[],                         /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */

+		Word16 isp[],                         /* (o) Q15 : isp[m] (range: -1<=val<1)                */

+		Word16 m                              /* (i)     : LPC order                                */

+	    )

+{

+	Word16 offset;

+	Word32 i, ind, L_tmp;

+

+	for (i = 0; i < m - 1; i++)

+	{

+		isp[i] = isf[i];                  

+	}

+	isp[m - 1] = (isf[m - 1] << 1);

+

+	for (i = 0; i < m; i++)

+	{

+		ind = (isp[i] >> 7);                      /* ind    = b7-b15 of isf[i] */

+		offset = (Word16) (isp[i] & 0x007f);      /* offset = b0-b6  of isf[i] */

+

+		/* isp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 128 */

+		L_tmp = vo_L_mult(vo_sub(table[ind + 1], table[ind]), offset);

+		isp[i] = add1(table[ind], (Word16)((L_tmp >> 8)));   

+	}

+

+	return;

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/lag_wind.c b/media/libstagefright/codecs/amrwbenc/src/lag_wind.c
new file mode 100644
index 0000000..0397704
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/lag_wind.c
@@ -0,0 +1,49 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: lag_wind.c                                                *

+*                                                                      *

+*	   Description: Lag_windows on autocorrelations                *

+*	                r[i] *= lag_wind[i]                            *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "lag_wind.tab"

+

+

+void Lag_window(

+		Word16 r_h[],                         /* (i/o)   : Autocorrelations  (msb)          */

+		Word16 r_l[]                          /* (i/o)   : Autocorrelations  (lsb)          */

+	       )

+{

+	Word32 i;

+	Word32 x;

+

+	for (i = 1; i <= M; i++)

+	{

+		x = Mpy_32(r_h[i], r_l[i], volag_h[i - 1], volag_l[i - 1]);

+		r_h[i] = x >> 16;

+		r_l[i] = (x & 0xffff)>>1;

+	}

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/levinson.c b/media/libstagefright/codecs/amrwbenc/src/levinson.c
new file mode 100644
index 0000000..8bc6f62
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/levinson.c
@@ -0,0 +1,250 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: levinson.c                                                *

+*                                                                      *

+*      Description:LEVINSON-DURBIN algorithm in double precision       *

+*                                                                      *

+************************************************************************/

+/*---------------------------------------------------------------------------*

+ *                         LEVINSON.C					     *

+ *---------------------------------------------------------------------------*

+ *                                                                           *

+ *      LEVINSON-DURBIN algorithm in double precision                        *

+ *                                                                           *

+ *                                                                           *

+ * Algorithm                                                                 *

+ *                                                                           *

+ *       R[i]    autocorrelations.                                           *

+ *       A[i]    filter coefficients.                                        *

+ *       K       reflection coefficients.                                    *

+ *       Alpha   prediction gain.                                            *

+ *                                                                           *

+ *       Initialization:                                                     *

+ *               A[0] = 1                                                    *

+ *               K    = -R[1]/R[0]                                           *

+ *               A[1] = K                                                    *

+ *               Alpha = R[0] * (1-K**2]                                     *

+ *                                                                           *

+ *       Do for  i = 2 to M                                                  *

+ *                                                                           *

+ *            S =  SUM ( R[j]*A[i-j] ,j=1,i-1 ) +  R[i]                      *

+ *                                                                           *

+ *            K = -S / Alpha                                                 *

+ *                                                                           *

+ *            An[j] = A[j] + K*A[i-j]   for j=1 to i-1                       *

+ *                                      where   An[i] = new A[i]             *

+ *            An[i]=K                                                        *

+ *                                                                           *

+ *            Alpha=Alpha * (1-K**2)                                         *

+ *                                                                           *

+ *       END                                                                 *

+ *                                                                           *

+ * Remarks on the dynamics of the calculations.                              *

+ *                                                                           *

+ *       The numbers used are in double precision in the following format :  *

+ *       A = AH <<16 + AL<<1.  AH and AL are 16 bit signed integers.         *

+ *       Since the LSB's also contain a sign bit, this format does not       *

+ *       correspond to standard 32 bit integers.  We use this format since   *

+ *       it allows fast execution of multiplications and divisions.          *

+ *                                                                           *

+ *       "DPF" will refer to this special format in the following text.      *

+ *       See oper_32b.c                                                      *

+ *                                                                           *

+ *       The R[i] were normalized in routine AUTO (hence, R[i] < 1.0).       *

+ *       The K[i] and Alpha are theoretically < 1.0.                         *

+ *       The A[i], for a sampling frequency of 8 kHz, are in practice        *

+ *       always inferior to 16.0.                                            *

+ *                                                                           *

+ *       These characteristics allow straigthforward fixed-point             *

+ *       implementation.  We choose to represent the parameters as           *

+ *       follows :                                                           *

+ *                                                                           *

+ *               R[i]    Q31   +- .99..                                      *

+ *               K[i]    Q31   +- .99..                                      *

+ *               Alpha   Normalized -> mantissa in Q31 plus exponent         *

+ *               A[i]    Q27   +- 15.999..                                   *

+ *                                                                           *

+ *       The additions are performed in 32 bit.  For the summation used      *

+ *       to calculate the K[i], we multiply numbers in Q31 by numbers        *

+ *       in Q27, with the result of the multiplications in Q27,              *

+ *       resulting in a dynamic of +- 16.  This is sufficient to avoid       *

+ *       overflow, since the final result of the summation is                *

+ *       necessarily < 1.0 as both the K[i] and Alpha are                    *

+ *       theoretically < 1.0.                                                *

+ *___________________________________________________________________________*/

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "acelp.h"

+

+#define M   16

+#define NC  (M/2)

+

+void Init_Levinson(

+		Word16 * mem                          /* output  :static memory (18 words) */

+		)

+{

+	Set_zero(mem, 18);                     /* old_A[0..M-1] = 0, old_rc[0..1] = 0 */

+	return;

+}

+

+

+void Levinson(

+		Word16 Rh[],                          /* (i)     : Rh[M+1] Vector of autocorrelations (msb) */

+		Word16 Rl[],                          /* (i)     : Rl[M+1] Vector of autocorrelations (lsb) */

+		Word16 A[],                           /* (o) Q12 : A[M]    LPC coefficients  (m = 16)       */

+		Word16 rc[],                          /* (o) Q15 : rc[M]   Reflection coefficients.         */

+		Word16 * mem                          /* (i/o)   :static memory (18 words)                  */

+	     )

+{

+	Word32 i, j;

+	Word16 hi, lo;

+	Word16 Kh, Kl;                         /* reflection coefficient; hi and lo           */

+	Word16 alp_h, alp_l, alp_exp;          /* Prediction gain; hi lo and exponent         */

+	Word16 Ah[M + 1], Al[M + 1];           /* LPC coef. in double prec.                   */

+	Word16 Anh[M + 1], Anl[M + 1];         /* LPC coef.for next iteration in double prec. */

+	Word32 t0, t1, t2;                     /* temporary variable                          */

+	Word16 *old_A, *old_rc;

+

+	/* Last A(z) for case of unstable filter */

+	old_A = mem;                           

+	old_rc = mem + M;                      

+

+	/* K = A[1] = -R[1] / R[0] */

+

+	t1 = ((Rh[1] << 16) + (Rl[1] << 1));   /* R[1] in Q31 */

+	t2 = L_abs(t1);                        /* abs R[1]         */

+	t0 = Div_32(t2, Rh[0], Rl[0]);         /* R[1]/R[0] in Q31 */

+	if (t1 > 0)

+		t0 = -t0;                          /* -R[1]/R[0]       */

+

+	Kh = t0 >> 16;

+	Kl = (t0 & 0xffff)>>1;

+	rc[0] = Kh;                            

+	t0 = (t0 >> 4);                        /* A[1] in Q27      */

+

+	Ah[1] = t0 >> 16;

+	Al[1] = (t0 & 0xffff)>>1;

+

+	/* Alpha = R[0] * (1-K**2) */

+	t0 = Mpy_32(Kh, Kl, Kh, Kl);           /* K*K      in Q31 */

+	t0 = L_abs(t0);                        /* Some case <0 !! */

+	t0 = vo_L_sub((Word32) 0x7fffffffL, t0);  /* 1 - K*K  in Q31 */

+

+	hi = t0 >> 16;

+	lo = (t0 & 0xffff)>>1;

+

+	t0 = Mpy_32(Rh[0], Rl[0], hi, lo);     /* Alpha in Q31    */

+

+	/* Normalize Alpha */

+	alp_exp = norm_l(t0);

+	t0 = (t0 << alp_exp);

+

+	alp_h = t0 >> 16;

+	alp_l = (t0 & 0xffff)>>1;

+	/*--------------------------------------*

+	 * ITERATIONS  I=2 to M                 *

+	 *--------------------------------------*/

+	for (i = 2; i <= M; i++)

+	{

+		/* t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) +  R[i] */

+		t0 = 0;                           

+		for (j = 1; j < i; j++)

+			t0 = vo_L_add(t0, Mpy_32(Rh[j], Rl[j], Ah[i - j], Al[i - j]));

+

+		t0 = t0 << 4;                 /* result in Q27 -> convert to Q31 */

+		/* No overflow possible            */

+		t1 = ((Rh[i] << 16) + (Rl[i] << 1));

+		t0 = vo_L_add(t0, t1);                /* add R[i] in Q31                 */

+

+		/* K = -t0 / Alpha */

+		t1 = L_abs(t0);

+		t2 = Div_32(t1, alp_h, alp_l);     /* abs(t0)/Alpha                   */

+		if (t0 > 0)

+			t2 = -t2;                   /* K =-t0/Alpha                    */

+		t2 = (t2 << alp_exp);           /* denormalize; compare to Alpha   */

+

+		Kh = t2 >> 16;

+		Kl = (t2 & 0xffff)>>1;

+

+		rc[i - 1] = Kh;                   

+		/* Test for unstable filter. If unstable keep old A(z) */

+		if (abs_s(Kh) > 32750)

+		{

+			A[0] = 4096;                    /* Ai[0] not stored (always 1.0) */

+			for (j = 0; j < M; j++)

+			{

+				A[j + 1] = old_A[j];       

+			}

+			rc[0] = old_rc[0];             /* only two rc coefficients are needed */

+			rc[1] = old_rc[1];

+			return;

+		}

+		/*------------------------------------------*

+		 *  Compute new LPC coeff. -> An[i]         *

+		 *  An[j]= A[j] + K*A[i-j]     , j=1 to i-1 *

+		 *  An[i]= K                                *

+		 *------------------------------------------*/

+		for (j = 1; j < i; j++)

+		{

+			t0 = Mpy_32(Kh, Kl, Ah[i - j], Al[i - j]);

+			t0 = vo_L_add(t0, ((Ah[j] << 16) + (Al[j] << 1)));

+			Anh[j] = t0 >> 16;

+			Anl[j] = (t0 & 0xffff)>>1;

+		}

+		t2 = (t2 >> 4);                 /* t2 = K in Q31 ->convert to Q27  */

+

+		VO_L_Extract(t2, &Anh[i], &Anl[i]);   /* An[i] in Q27                    */

+

+		/* Alpha = Alpha * (1-K**2) */

+		t0 = Mpy_32(Kh, Kl, Kh, Kl);               /* K*K      in Q31 */

+		t0 = L_abs(t0);                            /* Some case <0 !! */

+		t0 = vo_L_sub((Word32) 0x7fffffffL, t0);   /* 1 - K*K  in Q31 */

+		hi = t0 >> 16;

+		lo = (t0 & 0xffff)>>1;

+		t0 = Mpy_32(alp_h, alp_l, hi, lo); /* Alpha in Q31    */

+

+		/* Normalize Alpha */

+		j = norm_l(t0);

+		t0 = (t0 << j);

+		alp_h = t0 >> 16;

+		alp_l = (t0 & 0xffff)>>1;

+		alp_exp += j;         /* Add normalization to alp_exp */

+

+		/* A[j] = An[j] */

+		for (j = 1; j <= i; j++)

+		{

+			Ah[j] = Anh[j];               

+			Al[j] = Anl[j];                

+		}

+	}

+	/* Truncate A[i] in Q27 to Q12 with rounding */

+	A[0] = 4096;                          

+	for (i = 1; i <= M; i++)

+	{

+		t0 = (Ah[i] << 16) + (Al[i] << 1);

+		old_A[i - 1] = A[i] = vo_round((t0 << 1));      

+	}

+	old_rc[0] = rc[0];                    

+	old_rc[1] = rc[1];                    

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/log2.c b/media/libstagefright/codecs/amrwbenc/src/log2.c
new file mode 100644
index 0000000..cd3d815
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/log2.c
@@ -0,0 +1,111 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*                                                                      *

+*      File             : log2.c                                       *

+*      Purpose          : Computes log2(L_x)                           *

+*                                                                      *

+************************************************************************/

+

+#include "log2.h"

+/********************************************************************************

+*                         INCLUDE FILES

+*********************************************************************************/

+#include "typedef.h"

+#include "basic_op.h"

+

+/*********************************************************************************

+*                         LOCAL VARIABLES AND TABLES

+**********************************************************************************/

+#include "log2_tab.h"     /* Table for Log2() */

+

+/*************************************************************************

+*

+*   FUNCTION:   Log2_norm()

+*

+*   PURPOSE:   Computes log2(L_x, exp),  where   L_x is positive and

+*              normalized, and exp is the normalisation exponent

+*              If L_x is negative or zero, the result is 0.

+*

+*   DESCRIPTION:

+*        The function Log2(L_x) is approximated by a table and linear

+*        interpolation. The following steps are used to compute Log2(L_x)

+*

+*           1- exponent = 30-norm_exponent

+*           2- i = bit25-b31 of L_x;  32<=i<=63  (because of normalization).

+*           3- a = bit10-b24

+*           4- i -=32

+*           5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2

+*

+*************************************************************************/

+

+void Log2_norm (

+		Word32 L_x,         /* (i) : input value (normalized)                    */

+		Word16 exp,         /* (i) : norm_l (L_x)                                */

+		Word16 *exponent,   /* (o) : Integer part of Log2.   (range: 0<=val<=30) */

+		Word16 *fraction    /* (o) : Fractional part of Log2. (range: 0<=val<1)  */

+	       )

+{

+	Word16 i, a, tmp;

+	Word32 L_y;

+	if (L_x <= (Word32) 0)

+	{

+		*exponent = 0; 

+		*fraction = 0; 

+		return;

+	}

+	*exponent = (30 - exp); 

+	L_x = (L_x >> 9);

+	i = extract_h (L_x);                /* Extract b25-b31 */

+	L_x = (L_x >> 1);

+	a = (Word16)(L_x);                /* Extract b10-b24 of fraction */

+	a = (Word16)(a & (Word16)0x7fff);

+	i -= 32;

+	L_y = L_deposit_h (table[i]);       /* table[i] << 16        */

+	tmp = vo_sub(table[i], table[i + 1]); /* table[i] - table[i+1] */

+	L_y = vo_L_msu (L_y, tmp, a);          /* L_y -= tmp*a*2        */

+	*fraction = extract_h (L_y); 

+

+	return;

+}

+

+/*************************************************************************

+*

+*   FUNCTION:   Log2()

+*

+*   PURPOSE:   Computes log2(L_x),  where   L_x is positive.

+*              If L_x is negative or zero, the result is 0.

+*

+*   DESCRIPTION:

+*        normalizes L_x and then calls Log2_norm().

+*

+*************************************************************************/

+

+void Log2 (

+		Word32 L_x,         /* (i) : input value                                 */

+		Word16 *exponent,   /* (o) : Integer part of Log2.   (range: 0<=val<=30) */

+		Word16 *fraction    /* (o) : Fractional part of Log2. (range: 0<=val<1) */

+	  )

+{

+	Word16 exp;

+

+	exp = norm_l(L_x);

+	Log2_norm ((L_x << exp), exp, exponent, fraction);

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c b/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c
new file mode 100644
index 0000000..63b746b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c
@@ -0,0 +1,70 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: lp_dec2.c                                                *

+*                                                                      *

+*	Description:Decimate a vector by 2 with 2nd order fir filter   *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "cnst.h"

+

+#define L_FIR  5

+#define L_MEM  (L_FIR-2)

+

+/* static float h_fir[L_FIR] = {0.13, 0.23, 0.28, 0.23, 0.13}; */

+/* fixed-point: sum of coef = 32767 to avoid overflow on DC */

+static Word16 h_fir[L_FIR] = {4260, 7536, 9175, 7536, 4260};

+

+void LP_Decim2(

+		Word16 x[],                           /* in/out: signal to process         */

+		Word16 l,                             /* input : size of filtering         */

+		Word16 mem[]                          /* in/out: memory (size=3)           */

+	      )

+{

+	Word16 *p_x, x_buf[L_FRAME + L_MEM];

+	Word32 i, j;

+	Word32 L_tmp;

+	/* copy initial filter states into buffer */

+	p_x = x_buf;                           

+	for (i = 0; i < L_MEM; i++)

+	{

+		*p_x++ = mem[i];  

+		mem[i] = x[l - L_MEM + i];  

+	}

+	for (i = 0; i < l; i++)

+	{

+		*p_x++ = x[i];                     

+	}

+	for (i = 0, j = 0; i < l; i += 2, j++)

+	{

+		p_x = &x_buf[i];  

+		L_tmp  = ((*p_x++) * h_fir[0]);

+		L_tmp += ((*p_x++) * h_fir[1]);

+		L_tmp += ((*p_x++) * h_fir[2]);

+		L_tmp += ((*p_x++) * h_fir[3]);

+		L_tmp += ((*p_x++) * h_fir[4]);

+		x[j] = (L_tmp + 0x4000)>>15;              

+	}

+	return;

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/math_op.c b/media/libstagefright/codecs/amrwbenc/src/math_op.c
new file mode 100644
index 0000000..1c95ed0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/math_op.c
@@ -0,0 +1,219 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/*___________________________________________________________________________

+|                                                                           |

+|  This file contains mathematic operations in fixed point.                 |

+|                                                                           |

+|  Isqrt()              : inverse square root (16 bits precision).          |

+|  Pow2()               : 2^x  (16 bits precision).                         |

+|  Log2()               : log2 (16 bits precision).                         |

+|  Dot_product()        : scalar product of <x[],y[]>                       |

+|                                                                           |

+|  These operations are not standard double precision operations.           |

+|  They are used where low complexity is important and the full 32 bits     |

+|  precision is not necessary. For example, the function Div_32() has a     |

+|  24 bits precision which is enough for our purposes.                      |

+|                                                                           |

+|  In this file, the values use theses representations:                     |

+|                                                                           |

+|  Word32 L_32     : standard signed 32 bits format                         |

+|  Word16 hi, lo   : L_32 = hi<<16 + lo<<1  (DPF - Double Precision Format) |

+|  Word32 frac, Word16 exp : L_32 = frac << exp-31  (normalised format)     |

+|  Word16 int, frac        : L_32 = int.frac        (fractional format)     |

+|___________________________________________________________________________|

+*/

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : Isqrt                                                   |

+|                                                                           |

+|       Compute 1/sqrt(L_x).                                                |

+|       if L_x is negative or zero, result is 1 (7fffffff).                 |

+|---------------------------------------------------------------------------|

+|  Algorithm:                                                               |

+|                                                                           |

+|   1- Normalization of L_x.                                                |

+|   2- call Isqrt_n(L_x, exponant)                                          |

+|   3- L_y = L_x << exponant                                                |

+|___________________________________________________________________________|

+*/

+Word32 Isqrt(                              /* (o) Q31 : output value (range: 0<=val<1)         */

+		Word32 L_x                            /* (i) Q0  : input value  (range: 0<=val<=7fffffff) */

+	    )

+{

+	Word16 exp;

+	Word32 L_y;

+	exp = norm_l(L_x);

+	L_x = (L_x << exp);                 /* L_x is normalized */

+	exp = (31 - exp);

+	Isqrt_n(&L_x, &exp);

+	L_y = (L_x << exp);                 /* denormalization   */

+	return (L_y);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : Isqrt_n                                                 |

+|                                                                           |

+|       Compute 1/sqrt(value).                                              |

+|       if value is negative or zero, result is 1 (frac=7fffffff, exp=0).   |

+|---------------------------------------------------------------------------|

+|  Algorithm:                                                               |

+|                                                                           |

+|   The function 1/sqrt(value) is approximated by a table and linear        |

+|   interpolation.                                                          |

+|                                                                           |

+|   1- If exponant is odd then shift fraction right once.                   |

+|   2- exponant = -((exponant-1)>>1)                                        |

+|   3- i = bit25-b30 of fraction, 16 <= i <= 63 ->because of normalization. |

+|   4- a = bit10-b24                                                        |

+|   5- i -=16                                                               |

+|   6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2            |

+|___________________________________________________________________________|

+*/

+static Word16 table_isqrt[49] =

+{

+	32767, 31790, 30894, 30070, 29309, 28602, 27945, 27330, 26755, 26214,

+	25705, 25225, 24770, 24339, 23930, 23541, 23170, 22817, 22479, 22155,

+	21845, 21548, 21263, 20988, 20724, 20470, 20225, 19988, 19760, 19539,

+	19326, 19119, 18919, 18725, 18536, 18354, 18176, 18004, 17837, 17674,

+	17515, 17361, 17211, 17064, 16921, 16782, 16646, 16514, 16384

+};

+

+void Isqrt_n(

+		Word32 * frac,                        /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */

+		Word16 * exp                          /* (i/o)    : exponent (value = frac x 2^exponent) */

+	    )

+{

+	Word16 i, a, tmp;

+

+	if (*frac <= (Word32) 0)

+	{

+		*exp = 0;                          

+		*frac = 0x7fffffffL;               

+		return;

+	}

+

+	if((*exp & 1) == 1)                       /*If exponant odd -> shift right */

+		*frac = (*frac) >> 1;

+

+	*exp = negate((*exp - 1) >> 1);   

+

+	*frac = (*frac >> 9);               

+	i = extract_h(*frac);                  /* Extract b25-b31 */

+	*frac = (*frac >> 1);              

+	a = (Word16)(*frac);                  /* Extract b10-b24 */

+	a = (Word16) (a & (Word16) 0x7fff);    

+	i -= 16;

+	*frac = L_deposit_h(table_isqrt[i]);   /* table[i] << 16         */

+	tmp = vo_sub(table_isqrt[i], table_isqrt[i + 1]);      /* table[i] - table[i+1]) */

+	*frac = vo_L_msu(*frac, tmp, a);          /* frac -=  tmp*a*2       */

+

+	return;

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : Pow2()                                                  |

+|                                                                           |

+|     L_x = pow(2.0, exponant.fraction)         (exponant = interger part)  |

+|         = pow(2.0, 0.fraction) << exponant                                |

+|---------------------------------------------------------------------------|

+|  Algorithm:                                                               |

+|                                                                           |

+|   The function Pow2(L_x) is approximated by a table and linear            |

+|   interpolation.                                                          |

+|                                                                           |

+|   1- i = bit10-b15 of fraction,   0 <= i <= 31                            |

+|   2- a = bit0-b9   of fraction                                            |

+|   3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2                 |

+|   4- L_x = L_x >> (30-exponant)     (with rounding)                       |

+|___________________________________________________________________________|

+*/

+static Word16 table_pow2[33] =

+{

+	16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911,

+	20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726,

+	25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706,

+	31379, 32066, 32767

+};

+

+Word32 Pow2(                               /* (o) Q0  : result       (range: 0<=val<=0x7fffffff) */

+		Word16 exponant,                      /* (i) Q0  : Integer part.      (range: 0<=val<=30)   */

+		Word16 fraction                       /* (i) Q15 : Fractionnal part.  (range: 0.0<=val<1.0) */

+	   )

+{

+	Word16 exp, i, a, tmp;

+	Word32 L_x;

+

+	L_x = vo_L_mult(fraction, 32);            /* L_x = fraction<<6           */

+	i = extract_h(L_x);                    /* Extract b10-b16 of fraction */

+	L_x =L_x >> 1;

+	a = (Word16)(L_x);                    /* Extract b0-b9   of fraction */

+	a = (Word16) (a & (Word16) 0x7fff); 

+

+	L_x = L_deposit_h(table_pow2[i]);      /* table[i] << 16        */

+	tmp = vo_sub(table_pow2[i], table_pow2[i + 1]);        /* table[i] - table[i+1] */

+	L_x -= (tmp * a)<<1;              /* L_x -= tmp*a*2        */

+

+	exp = vo_sub(30, exponant);

+	L_x = vo_L_shr_r(L_x, exp);

+

+	return (L_x);

+}

+

+/*___________________________________________________________________________

+|                                                                           |

+|   Function Name : Dot_product12()                                         |

+|                                                                           |

+|       Compute scalar product of <x[],y[]> using accumulator.              |

+|                                                                           |

+|       The result is normalized (in Q31) with exponent (0..30).            |

+|---------------------------------------------------------------------------|

+|  Algorithm:                                                               |

+|                                                                           |

+|       dot_product = sum(x[i]*y[i])     i=0..N-1                           |

+|___________________________________________________________________________|

+*/

+

+Word32 Dot_product12(                      /* (o) Q31: normalized result (1 < val <= -1) */

+		Word16 x[],                           /* (i) 12bits: x vector                       */

+		Word16 y[],                           /* (i) 12bits: y vector                       */

+		Word16 lg,                            /* (i)    : vector length                     */

+		Word16 * exp                          /* (o)    : exponent of result (0..+30)       */

+		)

+{

+	Word16 sft;

+	Word32 i, L_sum;

+	L_sum = 0;

+	for (i = 0; i < lg; i++)

+	{

+		L_sum += x[i] * y[i];

+	}

+	L_sum = (L_sum << 1) + 1;

+	/* Normalize acc in Q31 */

+	sft = norm_l(L_sum);

+	L_sum = L_sum << sft;

+	*exp = 30 - sft;            /* exponent = 0..30 */

+	return (L_sum);

+

+}

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/mem_align.c b/media/libstagefright/codecs/amrwbenc/src/mem_align.c
new file mode 100644
index 0000000..e58915a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/mem_align.c
@@ -0,0 +1,107 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** 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.
+ */
+
+/*******************************************************************************
+	File:		mem_align.c
+
+	Content:	Memory alloc alignments functions
+
+*******************************************************************************/
+
+
+#include	"mem_align.h"
+
+/*****************************************************************************
+*
+* function name: mem_malloc
+* description:  malloc the alignments memory 
+* returns:      the point of the memory
+*
+**********************************************************************************/
+void *
+mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID)
+{
+	int ret;
+	unsigned char *mem_ptr;
+	VO_MEM_INFO MemInfo;
+
+	if (!alignment) {
+
+		MemInfo.Flag = 0;
+		MemInfo.Size = size + 1;
+		ret = pMemop->Alloc(CodecID, &MemInfo);
+		if(ret != 0)
+			return 0;
+		mem_ptr = (unsigned char *)MemInfo.VBuffer;
+
+		pMemop->Set(CodecID, mem_ptr, 0, size + 1);
+
+		*mem_ptr = (unsigned char)1;
+
+		return ((void *)(mem_ptr+1));
+	} else {
+		unsigned char *tmp;
+
+		MemInfo.Flag = 0;
+		MemInfo.Size = size + alignment;
+		ret = pMemop->Alloc(CodecID, &MemInfo);
+		if(ret != 0)
+			return 0;
+
+		tmp = (unsigned char *)MemInfo.VBuffer;
+
+		pMemop->Set(CodecID, tmp, 0, size + alignment);
+
+		mem_ptr =
+			(unsigned char *) ((unsigned int) (tmp + alignment - 1) &
+					(~((unsigned int) (alignment - 1))));
+
+		if (mem_ptr == tmp)
+			mem_ptr += alignment;
+
+		*(mem_ptr - 1) = (unsigned char) (mem_ptr - tmp);
+
+		return ((void *)mem_ptr);
+	}
+
+	return(0);
+}
+
+
+/*****************************************************************************
+*
+* function name: mem_free
+* description:  free the memory
+*
+*******************************************************************************/
+void
+mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID)
+{
+
+	unsigned char *ptr;
+
+	if (mem_ptr == 0)
+		return;
+
+	ptr = mem_ptr;
+
+	ptr -= *(ptr - 1);
+
+	pMemop->Free(CodecID, ptr);
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/oper_32b.c b/media/libstagefright/codecs/amrwbenc/src/oper_32b.c
new file mode 100644
index 0000000..5f1523e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/oper_32b.c
@@ -0,0 +1,223 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/*****************************************************************************

+ *  This file contains operations in double precision.                       *

+ *  These operations are not standard double precision operations.           *

+ *  They are used where single precision is not enough but the full 32 bits  *

+ *  precision is not necessary. For example, the function Div_32() has a     *

+ *  24 bits precision which is enough for our purposes.                      *

+ *                                                                           *

+ *  The double precision numbers use a special representation:               *

+ *                                                                           *

+ *     L_32 = hi<<16 + lo<<1                                                 *

+ *                                                                           *

+ *  L_32 is a 32 bit integer.                                                *

+ *  hi and lo are 16 bit signed integers.                                    *

+ *  As the low part also contains the sign, this allows fast multiplication. *

+ *                                                                           *

+ *      0x8000 0000 <= L_32 <= 0x7fff fffe.                                  *

+ *                                                                           *

+ *  We will use DPF (Double Precision Format )in this file to specify        *

+ *  this special format.                                                     *

+ *****************************************************************************

+*/

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+

+/*****************************************************************************

+ *                                                                           *

+ *  Function L_Extract()                                                     *

+ *                                                                           *

+ *  Extract from a 32 bit integer two 16 bit DPF.                            *

+ *                                                                           *

+ *  Arguments:                                                               *

+ *                                                                           *

+ *   L_32      : 32 bit integer.                                             *

+ *               0x8000 0000 <= L_32 <= 0x7fff ffff.                         *

+ *   hi        : b16 to b31 of L_32                                          *

+ *   lo        : (L_32 - hi<<16)>>1                                          *

+ *****************************************************************************

+*/

+

+__inline void VO_L_Extract (Word32 L_32, Word16 *hi, Word16 *lo)

+{

+	*hi = (Word16)(L_32 >> 16);

+	*lo = (Word16)((L_32 & 0xffff) >> 1);

+	return;

+}

+

+/*****************************************************************************

+ *                                                                           *

+ *  Function L_Comp()                                                        *

+ *                                                                           *

+ *  Compose from two 16 bit DPF a 32 bit integer.                            *

+ *                                                                           *

+ *     L_32 = hi<<16 + lo<<1                                                 *

+ *                                                                           *

+ *  Arguments:                                                               *

+ *                                                                           *

+ *   hi        msb                                                           *

+ *   lo        lsf (with sign)                                               *

+ *                                                                           *

+ *   Return Value :                                                          *

+ *                                                                           *

+ *             32 bit long signed integer (Word32) whose value falls in the  *

+ *             range : 0x8000 0000 <= L_32 <= 0x7fff fff0.                   *

+ *                                                                           *

+ *****************************************************************************

+*/

+

+Word32 L_Comp (Word16 hi, Word16 lo)

+{

+	Word32 L_32;

+

+	L_32 = L_deposit_h (hi);

+

+	return (L_mac (L_32, lo, 1));       /* = hi<<16 + lo<<1 */

+}

+

+/*****************************************************************************

+ * Function Mpy_32()                                                         *

+ *                                                                           *

+ *   Multiply two 32 bit integers (DPF). The result is divided by 2**31      *

+ *                                                                           *

+ *   L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1              *

+ *                                                                           *

+ *   This operation can also be viewed as the multiplication of two Q31      *

+ *   number and the result is also in Q31.                                   *

+ *                                                                           *

+ * Arguments:                                                                *

+ *                                                                           *

+ *  hi1         hi part of first number                                      *

+ *  lo1         lo part of first number                                      *

+ *  hi2         hi part of second number                                     *

+ *  lo2         lo part of second number                                     *

+ *                                                                           *

+ *****************************************************************************

+*/

+

+__inline Word32  Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)

+{

+	Word32 L_32;

+	L_32 = (hi1 * hi2);

+	L_32 += (hi1 * lo2) >> 15;

+	L_32 += (lo1 * hi2) >> 15;

+	L_32 <<= 1;

+

+	return (L_32);

+}

+

+/*****************************************************************************

+ * Function Mpy_32_16()                                                      *

+ *                                                                           *

+ *   Multiply a 16 bit integer by a 32 bit (DPF). The result is divided      *

+ *   by 2**15                                                                *

+ *                                                                           *

+ *                                                                           *

+ *   L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1                                *

+ *                                                                           *

+ * Arguments:                                                                *

+ *                                                                           *

+ *  hi          hi part of 32 bit number.                                    *

+ *  lo          lo part of 32 bit number.                                    *

+ *  n           16 bit number.                                               *

+ *                                                                           *

+ *****************************************************************************

+*/

+

+__inline Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n)

+{

+	Word32 L_32;

+

+	L_32 = (hi * n)<<1;

+	L_32 += (((lo * n)>>15)<<1);

+

+	return (L_32);

+}

+

+/*****************************************************************************

+ *                                                                           *

+ *   Function Name : Div_32                                                  *

+ *                                                                           *

+ *   Purpose :                                                               *

+ *             Fractional integer division of two 32 bit numbers.            *

+ *             L_num / L_denom.                                              *

+ *             L_num and L_denom must be positive and L_num < L_denom.       *

+ *             L_denom = denom_hi<<16 + denom_lo<<1                          *

+ *             denom_hi is a normalize number.                               *

+ *                                                                           *

+ *   Inputs :                                                                *

+ *                                                                           *

+ *    L_num                                                                  *

+ *             32 bit long signed integer (Word32) whose value falls in the  *

+ *             range : 0x0000 0000 < L_num < L_denom                         *

+ *                                                                           *

+ *    L_denom = denom_hi<<16 + denom_lo<<1      (DPF)                        *

+ *                                                                           *

+ *       denom_hi                                                            *

+ *             16 bit positive normalized integer whose value falls in the   *

+ *             range : 0x4000 < hi < 0x7fff                                  *

+ *       denom_lo                                                            *

+ *             16 bit positive integer whose value falls in the              *

+ *             range : 0 < lo < 0x7fff                                       *

+ *                                                                           *

+ *   Return Value :                                                          *

+ *                                                                           *

+ *    L_div                                                                  *

+ *             32 bit long signed integer (Word32) whose value falls in the  *

+ *             range : 0x0000 0000 <= L_div <= 0x7fff ffff.                  *

+ *                                                                           *

+ *  Algorithm:                                                               *

+ *                                                                           *

+ *  - find = 1/L_denom.                                                      *

+ *      First approximation: approx = 1 / denom_hi                           *

+ *      1/L_denom = approx * (2.0 - L_denom * approx )                       *

+ *                                                                           *

+ *  -  result = L_num * (1/L_denom)                                          *

+ *****************************************************************************

+*/

+

+Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo)

+{

+	Word16 approx, hi, lo, n_hi, n_lo;

+	Word32 L_32;

+

+	/* First approximation: 1 / L_denom = 1/denom_hi */

+

+	approx = div_s ((Word16) 0x3fff, denom_hi);

+

+	/* 1/L_denom = approx * (2.0 - L_denom * approx) */

+

+	L_32 = Mpy_32_16 (denom_hi, denom_lo, approx);

+

+	L_32 = L_sub ((Word32) 0x7fffffffL, L_32);

+	hi = L_32 >> 16;

+	lo = (L_32 & 0xffff) >> 1;

+

+	L_32 = Mpy_32_16 (hi, lo, approx);

+

+	/* L_num * (1/L_denom) */

+	hi = L_32 >> 16;

+	lo = (L_32 & 0xffff) >> 1;

+	VO_L_Extract (L_num, &n_hi, &n_lo);

+	L_32 = Mpy_32 (n_hi, n_lo, hi, lo);

+	L_32 = L_shl2(L_32, 2);

+

+	return (L_32);

+}

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c b/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c
new file mode 100644
index 0000000..39ee966
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c
@@ -0,0 +1,256 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: p_med_ol.c                                                *

+*                                                                      *

+*      Description: Compute the open loop pitch lag                    *

+*	            output: open loop pitch lag                        *                            

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "acelp.h"

+#include "oper_32b.h"

+#include "math_op.h"

+#include "p_med_ol.tab"

+

+Word16 Pitch_med_ol(

+		   Word16      wsp[],        /*   i: signal used to compute the open loop pitch*/  

+                                     /*      wsp[-pit_max] to wsp[-1] should be known */

+		   Coder_State *st,          /* i/o: codec global structure */

+		   Word16      L_frame       /*   i: length of frame to compute pitch */

+		)

+{

+	Word16 Tm;

+	Word16 hi, lo;

+	Word16 *ww, *we, *hp_wsp;

+	Word16 exp_R0, exp_R1, exp_R2;

+	Word32 i, j, max, R0, R1, R2;

+	Word16 *p1, *p2;

+	Word16 L_min = 17;                   /* minimum pitch lag: PIT_MIN / OPL_DECIM */

+	Word16 L_max = 115;                  /* maximum pitch lag: PIT_MAX / OPL_DECIM */

+	Word16 L_0 = st->old_T0_med;         /* old open-loop pitch */

+	Word16 *gain = &(st->ol_gain);       /* normalize correlation of hp_wsp for the lag */

+	Word16 *hp_wsp_mem = st->hp_wsp_mem; /* memory of the hypass filter for hp_wsp[] (lg = 9)*/

+	Word16 *old_hp_wsp = st->old_hp_wsp; /* hypass wsp[] */

+	Word16 wght_flg = st->ol_wght_flg;   /* is weighting function used */

+

+	ww = &corrweight[198];

+	we = &corrweight[98 + L_max - L_0];

+

+	max = MIN_32;                          

+	Tm = 0;                                

+	for (i = L_max; i > L_min; i--)

+	{

+		/* Compute the correlation */

+		R0 = 0;

+		p1 = wsp;

+		p2 = &wsp[-i];

+		for (j = 0; j < L_frame; j+=4)

+		{

+			R0 += vo_L_mult((*p1++), (*p2++));

+			R0 += vo_L_mult((*p1++), (*p2++));

+			R0 += vo_L_mult((*p1++), (*p2++));

+			R0 += vo_L_mult((*p1++), (*p2++));     

+		}

+		/* Weighting of the correlation function.   */

+		hi = R0>>16;

+		lo = (R0 & 0xffff)>>1;

+

+		R0 = Mpy_32_16(hi, lo, *ww);

+		ww--;

+

+		if ((L_0 > 0) && (wght_flg > 0))

+		{

+			/* Weight the neighbourhood of the old lag. */

+			hi = R0>>16;

+			lo = (R0 & 0xffff)>>1;

+			R0 = Mpy_32_16(hi, lo, *we);

+			we--;

+		}

+		if(R0 >= max)

+		{

+			max = R0;

+			Tm = i;

+		}

+	}

+

+	/* Hypass the wsp[] vector */

+	hp_wsp = old_hp_wsp + L_max;           

+	Hp_wsp(wsp, hp_wsp, L_frame, hp_wsp_mem);

+

+	/* Compute normalize correlation at delay Tm */

+	R0 = 0;                                

+	R1 = 0;                               

+	R2 = 0; 

+	p1 = hp_wsp;

+	p2 = hp_wsp - Tm;

+	for (j = 0; j < L_frame; j+=4)

+	{

+		R2 += vo_mult32(*p1, *p1);

+		R1 += vo_mult32(*p2, *p2);

+		R0 += vo_mult32(*p1++, *p2++);

+		R2 += vo_mult32(*p1, *p1);

+		R1 += vo_mult32(*p2, *p2);

+		R0 += vo_mult32(*p1++, *p2++);

+		R2 += vo_mult32(*p1, *p1);

+		R1 += vo_mult32(*p2, *p2);

+		R0 += vo_mult32(*p1++, *p2++);

+		R2 += vo_mult32(*p1, *p1);

+		R1 += vo_mult32(*p2, *p2);

+		R0 += vo_mult32(*p1++, *p2++);

+	}

+	R0 = R0 <<1;

+	R1 = (R1 <<1) + 1L;

+	R2 = (R2 <<1) + 1L;

+	/* gain = R0/ sqrt(R1*R2) */

+

+	exp_R0 = norm_l(R0);

+	R0 = (R0 << exp_R0);

+

+	exp_R1 = norm_l(R1);

+	R1 = (R1 << exp_R1);

+

+	exp_R2 = norm_l(R2);

+	R2 = (R2 << exp_R2);

+

+

+	R1 = vo_L_mult(vo_round(R1), vo_round(R2));

+

+	i = norm_l(R1);

+	R1 = (R1 << i);

+

+	exp_R1 += exp_R2;

+	exp_R1 += i;

+	exp_R1 = 62 - exp_R1;

+

+	Isqrt_n(&R1, &exp_R1);

+

+	R0 = vo_L_mult(voround(R0), voround(R1));

+	exp_R0 = 31 - exp_R0;

+	exp_R0 += exp_R1;

+

+	*gain = vo_round(L_shl(R0, exp_R0));

+

+	/* Shitf hp_wsp[] for next frame */

+

+	for (i = 0; i < L_max; i++)

+	{

+		old_hp_wsp[i] = old_hp_wsp[i + L_frame];

+	}

+

+	return (Tm);

+}

+

+/************************************************************************

+*  Function: median5                                                    *

+*                                                                       *

+*      Returns the median of the set {X[-2], X[-1],..., X[2]},          *

+*      whose elements are 16-bit integers.                              *

+*                                                                       *

+*  Input:                                                               *

+*      X[-2:2]   16-bit integers.                                       *

+*                                                                       *

+*  Return:                                                              *

+*      The median of {X[-2], X[-1],..., X[2]}.                          *

+************************************************************************/

+

+Word16 median5(Word16 x[])

+{

+	Word16 x1, x2, x3, x4, x5;

+	Word16 tmp;

+

+	x1 = x[-2];                            

+	x2 = x[-1];                            

+	x3 = x[0];                             

+	x4 = x[1];                             

+	x5 = x[2];                             

+

+	if (x2 < x1)

+	{

+		tmp = x1;

+		x1 = x2;

+		x2 = tmp;                          

+	}

+	if (x3 < x1)

+	{

+		tmp = x1;

+		x1 = x3;

+		x3 = tmp;                          

+	}

+	if (x4 < x1)

+	{

+		tmp = x1;

+		x1 = x4;

+		x4 = tmp;                          

+	}

+	if (x5 < x1)

+	{

+		x5 = x1;                           

+	}

+	if (x3 < x2)

+	{

+		tmp = x2;

+		x2 = x3;

+		x3 = tmp;                          

+	}

+	if (x4 < x2)

+	{

+		tmp = x2;

+		x2 = x4;

+		x4 = tmp;                          

+	}

+	if (x5 < x2)

+	{

+		x5 = x2;                           

+	}

+	if (x4 < x3)

+	{

+		x3 = x4;                           

+	}

+	if (x5 < x3)

+	{

+		x3 = x5;                           

+	}

+	return (x3);

+}

+

+

+Word16 Med_olag(                           /* output : median of  5 previous open-loop lags       */

+		Word16 prev_ol_lag,                /* input  : previous open-loop lag                     */

+		Word16 old_ol_lag[5]

+	       )

+{

+	Word32 i;

+

+	/* Use median of 5 previous open-loop lags as old lag */

+

+	for (i = 4; i > 0; i--)

+	{

+		old_ol_lag[i] = old_ol_lag[i - 1]; 

+	}

+

+	old_ol_lag[0] = prev_ol_lag;           

+

+	i = median5(&old_ol_lag[2]);

+

+	return i;

+

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c b/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c
new file mode 100644
index 0000000..c8a227c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c
@@ -0,0 +1,49 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: pit_shrp.c                                                *

+*                                                                      *

+*      Description: Performs Pitch sharpening routine                  *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+void Pit_shrp(

+		Word16 * x,                           /* in/out: impulse response (or algebraic code) */

+		Word16 pit_lag,                       /* input : pitch lag                            */

+		Word16 sharp,                         /* input : pitch sharpening factor (Q15)        */

+		Word16 L_subfr                        /* input : subframe size                        */

+	     )

+{

+	Word32 i;

+	Word32 L_tmp;

+	Word16 *x_ptr = x + pit_lag;

+

+	for (i = pit_lag; i < L_subfr; i++)

+	{

+		L_tmp = (*x_ptr << 15);

+		L_tmp += *x++ * sharp;

+		*x_ptr++ = ((L_tmp + 0x4000)>>15);

+	}

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c b/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c
new file mode 100644
index 0000000..c115b11
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c
@@ -0,0 +1,324 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: pitch_f4.c                                                *

+*                                                                      *

+*      Description: Find the closed loop pitch period with             *

+*	            1/4 subsample resolution.                          *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+#include "acelp.h"

+#include "cnst.h"

+

+#define UP_SAMP      4

+#define L_INTERPOL1  4

+

+/* Local functions */

+

+#ifdef ASM_OPT

+void Norm_corr_asm(

+		Word16 exc[],                         /* (i)     : excitation buffer                     */

+		Word16 xn[],                          /* (i)     : target vector                         */

+		Word16 h[],                           /* (i) Q15 : impulse response of synth/wgt filters */

+		Word16 L_subfr,

+		Word16 t_min,                         /* (i)     : minimum value of pitch lag.           */

+		Word16 t_max,                         /* (i)     : maximum value of pitch lag.           */

+		Word16 corr_norm[]                    /* (o) Q15 : normalized correlation                */

+		);

+#else

+static void Norm_Corr(

+		Word16 exc[],                         /* (i)     : excitation buffer                     */

+		Word16 xn[],                          /* (i)     : target vector                         */

+		Word16 h[],                           /* (i) Q15 : impulse response of synth/wgt filters */

+		Word16 L_subfr,

+		Word16 t_min,                         /* (i)     : minimum value of pitch lag.           */

+		Word16 t_max,                         /* (i)     : maximum value of pitch lag.           */

+		Word16 corr_norm[]                    /* (o) Q15 : normalized correlation                */

+		);

+#endif

+

+static Word16 Interpol_4(                  /* (o)  : interpolated value  */

+		Word16 * x,                           /* (i)  : input vector        */

+		Word32 frac                           /* (i)  : fraction (-4..+3)   */

+		);

+

+

+Word16 Pitch_fr4(                          /* (o)     : pitch period.                         */

+		Word16 exc[],                         /* (i)     : excitation buffer                     */

+		Word16 xn[],                          /* (i)     : target vector                         */

+		Word16 h[],                           /* (i) Q15 : impulse response of synth/wgt filters */

+		Word16 t0_min,                        /* (i)     : minimum value in the searched range.  */

+		Word16 t0_max,                        /* (i)     : maximum value in the searched range.  */

+		Word16 * pit_frac,                    /* (o)     : chosen fraction (0, 1, 2 or 3).       */

+		Word16 i_subfr,                       /* (i)     : indicator for first subframe.         */

+		Word16 t0_fr2,                        /* (i)     : minimum value for resolution 1/2      */

+		Word16 t0_fr1,                        /* (i)     : minimum value for resolution 1        */

+		Word16 L_subfr                        /* (i)     : Length of subframe                    */

+		)

+{

+	Word32 fraction, i;

+	Word16 t_min, t_max;

+	Word16 max, t0, step, temp;

+	Word16 *corr;

+	Word16 corr_v[40];                     /* Total length = t0_max-t0_min+1+2*L_inter */

+

+	/* Find interval to compute normalized correlation */

+

+	t_min = t0_min - L_INTERPOL1;

+	t_max = t0_max + L_INTERPOL1;

+	corr = &corr_v[-t_min];

+	/* Compute normalized correlation between target and filtered excitation */

+#ifdef ASM_OPT               /* asm optimization branch */

+    Norm_corr_asm(exc, xn, h, L_subfr, t_min, t_max, corr);

+#else

+	Norm_Corr(exc, xn, h, L_subfr, t_min, t_max, corr);

+#endif 

+

+	/* Find integer pitch */

+

+	max = corr[t0_min];

+	t0 = t0_min;

+	for (i = t0_min + 1; i <= t0_max; i++)

+	{

+		if (corr[i] >= max)

+		{

+			max = corr[i];                 

+			t0 = i;                        

+		}

+	}

+	/* If first subframe and t0 >= t0_fr1, do not search fractionnal pitch */

+	if ((i_subfr == 0) && (t0 >= t0_fr1))

+	{

+		*pit_frac = 0;

+		return (t0);

+	}

+	/*------------------------------------------------------------------*

+	 * Search fractionnal pitch with 1/4 subsample resolution.          *

+	 * Test the fractions around t0 and choose the one which maximizes  *

+	 * the interpolated normalized correlation.                         *

+	 *------------------------------------------------------------------*/

+

+	step = 1;               /* 1/4 subsample resolution */

+	fraction = -3;

+	if ((t0_fr2 == PIT_MIN)||((i_subfr == 0) && (t0 >= t0_fr2)))

+	{

+		step = 2;              /* 1/2 subsample resolution */

+		fraction = -2;

+	}

+	if(t0 == t0_min)

+	{

+		fraction = 0;

+	}

+	max = Interpol_4(&corr[t0], fraction);

+

+	for (i = fraction + step; i <= 3; i += step)

+	{

+		temp = Interpol_4(&corr[t0], i);

+		if(temp > max)

+		{

+			max = temp;

+			fraction = i;

+		}

+	}

+	/* limit the fraction value in the interval [0,1,2,3] */

+	if (fraction < 0)

+	{

+		fraction += UP_SAMP;

+		t0 -= 1;

+	}

+	*pit_frac = fraction;

+	return (t0);

+}

+

+

+/***********************************************************************************

+* Function:  Norm_Corr()                                                            *

+*                                                                                   *

+* Description: Find the normalized correlation between the target vector and the    *

+* filtered past excitation.                                                         *

+* (correlation between target and filtered excitation divided by the                *

+*  square root of energy of target and filtered excitation).                        *

+************************************************************************************/

+#ifndef ASM_OPT

+static void Norm_Corr(

+		Word16 exc[],                         /* (i)     : excitation buffer                     */

+		Word16 xn[],                          /* (i)     : target vector                         */

+		Word16 h[],                           /* (i) Q15 : impulse response of synth/wgt filters */

+		Word16 L_subfr,

+		Word16 t_min,                         /* (i)     : minimum value of pitch lag.           */

+		Word16 t_max,                         /* (i)     : maximum value of pitch lag.           */

+		Word16 corr_norm[])                   /* (o) Q15 : normalized correlation                */

+{

+	Word32 i, k, t;

+	Word32 corr, exp_corr, norm, exp, scale;

+	Word16 exp_norm, excf[L_SUBFR], tmp;

+	Word32 L_tmp, L_tmp1, L_tmp2;

+

+	/* compute the filtered excitation for the first delay t_min */

+	k = -t_min;

+

+#ifdef ASM_OPT              /* asm optimization branch */

+	Convolve_asm(&exc[k], h, excf, 64);

+#else

+	Convolve(&exc[k], h, excf, 64);

+#endif

+

+	/* Compute rounded down 1/sqrt(energy of xn[]) */

+	L_tmp = 0; 

+	for (i = 0; i < 64; i+=4)

+	{

+		L_tmp += (xn[i] * xn[i]);

+		L_tmp += (xn[i+1] * xn[i+1]);

+		L_tmp += (xn[i+2] * xn[i+2]);

+		L_tmp += (xn[i+3] * xn[i+3]);

+	}

+

+	L_tmp = (L_tmp << 1) + 1;

+	exp = norm_l(L_tmp);

+	exp = (32 - exp);

+	//exp = exp + 2;                     /* energy of xn[] x 2 + rounded up     */

+	scale = -(exp >> 1);           /* (1<<scale) < 1/sqrt(energy rounded) */

+

+	/* loop for every possible period */

+

+	for (t = t_min; t <= t_max; t++)

+	{

+		/* Compute correlation between xn[] and excf[] */

+		L_tmp  = 0;  

+		L_tmp1 = 0;

+		for (i = 0; i < 64; i+=4)

+		{

+			L_tmp  += (xn[i] * excf[i]);

+			L_tmp1 += (excf[i] * excf[i]);

+			L_tmp  += (xn[i+1] * excf[i+1]);

+			L_tmp1 += (excf[i+1] * excf[i+1]);

+			L_tmp  += (xn[i+2] * excf[i+2]);

+			L_tmp1 += (excf[i+2] * excf[i+2]);

+			L_tmp  += (xn[i+3] * excf[i+3]);

+			L_tmp1 += (excf[i+3] * excf[i+3]);

+		}

+

+		L_tmp = (L_tmp << 1) + 1;

+		L_tmp1 = (L_tmp1 << 1) + 1;

+

+		exp = norm_l(L_tmp);

+		L_tmp = (L_tmp << exp);

+		exp_corr = (30 - exp);

+		corr = extract_h(L_tmp);

+

+		exp = norm_l(L_tmp1);

+		L_tmp = (L_tmp1 << exp);

+		exp_norm = (30 - exp);

+

+		Isqrt_n(&L_tmp, &exp_norm);

+		norm = extract_h(L_tmp);

+

+		/* Normalize correlation = correlation * (1/sqrt(energy)) */

+

+		L_tmp = vo_L_mult(corr, norm);

+

+		L_tmp2 = exp_corr + exp_norm + scale;

+		if(L_tmp2 < 0)

+		{

+			L_tmp2 = -L_tmp2;

+			L_tmp = L_tmp >> L_tmp2;

+		}

+		else

+		{

+			L_tmp = L_tmp << L_tmp2;

+		}

+

+		corr_norm[t] = vo_round(L_tmp);      

+		/* modify the filtered excitation excf[] for the next iteration */

+

+		if(t != t_max)

+		{

+			k = -(t + 1);

+			tmp = exc[k];

+			for (i = 63; i > 0; i--)

+			{

+				excf[i] = add1(vo_mult(tmp, h[i]), excf[i - 1]);

+			}

+			excf[0] = vo_mult(tmp, h[0]);

+		}

+	}

+	return;

+}

+

+#endif

+/************************************************************************************

+* Function: Interpol_4()                                                             *

+*                                                                                    *

+* Description: For interpolating the normalized correlation with 1/4 resolution.     *

+**************************************************************************************/

+

+/* 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) in Q14 */

+static Word16 inter4_1[4][8] =

+{

+	{-12, 420, -1732, 5429, 13418, -1242, 73, 32},

+	{-26, 455, -2142, 9910, 9910,  -2142, 455, -26},

+	{32,  73, -1242, 13418, 5429, -1732, 420, -12},

+	{206, -766, 1376, 14746, 1376, -766, 206, 0}

+};

+

+/*** Coefficients in floating point

+static float inter4_1[UP_SAMP*L_INTERPOL1+1] = {

+0.900000,

+0.818959,  0.604850,  0.331379,  0.083958,

+-0.075795, -0.130717, -0.105685, -0.046774,

+0.004467,  0.027789,  0.025642,  0.012571,

+0.001927, -0.001571, -0.000753,  0.000000};

+***/

+

+static Word16 Interpol_4(                  /* (o)  : interpolated value  */

+		Word16 * x,                           /* (i)  : input vector        */

+		Word32 frac                           /* (i)  : fraction (-4..+3)   */

+		)

+{

+	Word16 sum;

+	Word32  k, L_sum;

+	Word16 *ptr;

+

+	if (frac < 0)

+	{

+		frac += UP_SAMP;

+		x--;

+	}

+	x = x - L_INTERPOL1 + 1;

+	k = UP_SAMP - 1 - frac;

+	ptr = &(inter4_1[k][0]);

+

+	L_sum  = vo_mult32(x[0], (*ptr++));

+	L_sum += vo_mult32(x[1], (*ptr++));

+	L_sum += vo_mult32(x[2], (*ptr++));

+	L_sum += vo_mult32(x[3], (*ptr++));

+	L_sum += vo_mult32(x[4], (*ptr++));  

+	L_sum += vo_mult32(x[5], (*ptr++));

+	L_sum += vo_mult32(x[6], (*ptr++));

+	L_sum += vo_mult32(x[7], (*ptr++));   

+

+	sum = extract_h(L_add(L_shl2(L_sum, 2), 0x8000));

+	return (sum);

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c b/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c
new file mode 100644
index 0000000..ac1ff22
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c
@@ -0,0 +1,120 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: pred_lt4.c                                                *

+*                                                                      *

+*      Description: Compute the result of long term prediction with    *

+*      fractional interpolation of resolution 1/4                      *

+*      on return exc[0..L_subr-1] contains the interpolated signal     *

+*      (adaptive codebook excitation)                                  *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+#define UP_SAMP      4

+#define L_INTERPOL2  16

+

+/* 1/4 resolution interpolation filter (-3 dB at 0.856*fs/2) in Q14 */

+

+Word16 inter4_2[4][32] =

+{

+	{0,-2,4,-2,-10,38,-88,165,-275,424,-619,871,-1207,1699,-2598,5531,14031,-2147,780,-249,

+	-16,153,-213,226,-209,175,-133,91,-55,28,-10,2},

+

+	{1,-7,19,-33,47,-52,43,-9,-60,175,-355,626,-1044,1749,-3267,10359,10359,-3267,1749,-1044,

+	626,-355,175,-60,-9,43,-52,47,-33,19, -7, 1},

+

+	{2,-10,28,-55,91,-133,175,-209,226,-213,153,-16,-249,780,-2147,14031,5531,-2598,1699,-1207,

+	871,-619,424,-275,165,-88,38,-10,-2,4,-2,0},

+

+	{1,-7,22,-49,92,-153,231,-325,431,-544,656,-762,853,-923,968,15401,968,-923,853,-762,

+	656,-544,431,-325,231,-153,92,-49,22,-7, 1, 0}

+

+};

+

+void Pred_lt4(

+		Word16 exc[],                         /* in/out: excitation buffer */

+		Word16 T0,                            /* input : integer pitch lag */

+		Word16 frac,                          /* input : fraction of lag   */

+		Word16 L_subfr                        /* input : subframe size     */

+	     )

+{

+	Word16 j, k, *x;

+	Word32 L_sum;

+	Word16 *ptr, *ptr1;

+	Word16 *ptr2;

+

+	x = exc - T0;   

+	frac = -frac;

+	if (frac < 0)

+	{

+		frac += UP_SAMP;

+		x--;

+	}   

+	x -= 15;                                     /* x = L_INTERPOL2 - 1 */

+	k = 3 - frac;                                /* k = UP_SAMP - 1 - frac */

+

+	ptr2 = &(inter4_2[k][0]);

+	for (j = 0; j < L_subfr; j++)

+	{

+		ptr = ptr2;

+		ptr1 = x;

+		L_sum  = vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+		L_sum += vo_mult32((*ptr1++), (*ptr++));

+

+		L_sum = L_shl2(L_sum, 2);

+		exc[j] = extract_h(L_add(L_sum, 0x8000));

+		x++;

+	}

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/preemph.c b/media/libstagefright/codecs/amrwbenc/src/preemph.c
new file mode 100644
index 0000000..f5bcd33
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/preemph.c
@@ -0,0 +1,88 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: preemph.c                                                *

+*                                                                     *

+*      Description: Preemphasis: filtering through 1 - g z^-1         *

+*	           Preemph2 --> signal is multiplied by 2             *

+*                                                                     *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+void Preemph(

+		Word16 x[],                           /* (i/o)   : input signal overwritten by the output */

+		Word16 mu,                            /* (i) Q15 : preemphasis coefficient                */

+		Word16 lg,                            /* (i)     : lenght of filtering                    */

+		Word16 * mem                          /* (i/o)   : memory (x[-1])                         */

+	    )

+{

+	Word16 temp;

+	Word32 i, L_tmp;

+

+	temp = x[lg - 1];                     

+

+	for (i = lg - 1; i > 0; i--)

+	{

+		L_tmp = L_deposit_h(x[i]);

+		L_tmp -= (x[i - 1] * mu)<<1;

+		x[i] = (L_tmp + 0x8000)>>16;               

+	}

+

+	L_tmp = L_deposit_h(x[0]);

+	L_tmp -= ((*mem) * mu)<<1;

+	x[0] = (L_tmp + 0x8000)>>16;                   

+

+	*mem = temp;                           

+

+	return;

+}

+

+

+void Preemph2(

+		Word16 x[],                           /* (i/o)   : input signal overwritten by the output */

+		Word16 mu,                            /* (i) Q15 : preemphasis coefficient                */

+		Word16 lg,                            /* (i)     : lenght of filtering                    */

+		Word16 * mem                          /* (i/o)   : memory (x[-1])                         */

+	     )

+{

+	Word16 temp;

+	Word32 i, L_tmp;

+

+	temp = x[lg - 1];                     

+

+	for (i = (Word16) (lg - 1); i > 0; i--)

+	{

+		L_tmp = L_deposit_h(x[i]);

+		L_tmp -= (x[i - 1] * mu)<<1;

+		L_tmp = (L_tmp << 1);

+		x[i] = (L_tmp + 0x8000)>>16;               

+	}

+

+	L_tmp = L_deposit_h(x[0]);

+	L_tmp -= ((*mem) * mu)<<1;

+	L_tmp = (L_tmp << 1);

+	x[0] = (L_tmp + 0x8000)>>16;                   

+

+	*mem = temp;                           

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/q_gain2.c b/media/libstagefright/codecs/amrwbenc/src/q_gain2.c
new file mode 100644
index 0000000..59eefe4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/q_gain2.c
@@ -0,0 +1,346 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/**************************************************************************

+*  File: q_gain2.c                                                         *

+*                                                                          *

+*  Description:                                                            *

+* Quantization of pitch and codebook gains.                                *

+* MA prediction is performed on the innovation energy (in dB with mean     *

+* removed).                                                                *

+* An initial predicted gain, g_0, is first determined and the correction   *

+* factor     alpha = gain / g_0    is quantized.                           *

+* The pitch gain and the correction factor are vector quantized and the    *

+* mean-squared weighted error criterion is used in the quantizer search.   *

+****************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "math_op.h"

+#include "log2.h"

+#include "acelp.h"

+#include "q_gain2.tab"

+

+#define MEAN_ENER    30

+#define RANGE        64

+#define PRED_ORDER   4

+

+

+/* MA prediction coeff ={0.5, 0.4, 0.3, 0.2} in Q13 */

+static Word16 pred[PRED_ORDER] = {4096, 3277, 2458, 1638};

+

+

+void Init_Q_gain2(

+		Word16 * mem                          /* output  :static memory (2 words)      */

+		)

+{

+	Word32 i;

+

+	/* 4nd order quantizer energy predictor (init to -14.0 in Q10) */

+	for (i = 0; i < PRED_ORDER; i++)

+	{

+		mem[i] = -14336;                     /* past_qua_en[i] */

+	}

+

+	return;

+}

+

+Word16 Q_gain2(                            /* Return index of quantization.          */

+		Word16 xn[],                          /* (i) Q_xn: Target vector.               */

+		Word16 y1[],                          /* (i) Q_xn: Adaptive codebook.           */

+		Word16 Q_xn,                          /* (i)     : xn and y1 format             */

+		Word16 y2[],                          /* (i) Q9  : Filtered innovative vector.  */

+		Word16 code[],                        /* (i) Q9  : Innovative vector.           */

+		Word16 g_coeff[],                     /* (i)     : Correlations <xn y1> <y1 y1> */

+		/*           Compute in G_pitch().        */

+		Word16 L_subfr,                       /* (i)     : Subframe lenght.             */

+		Word16 nbits,                         /* (i)     : number of bits (6 or 7)      */

+		Word16 * gain_pit,                    /* (i/o)Q14: Pitch gain.                  */

+		Word32 * gain_cod,                    /* (o) Q16 : Code gain.                   */

+		Word16 gp_clip,                       /* (i)     : Gp Clipping flag             */

+		Word16 * mem                          /* (i/o)   : static memory (2 words)      */

+	      )

+{

+	Word16 index, *p, min_ind, size;

+	Word16 exp, frac, gcode0, exp_gcode0, e_max, exp_code, qua_ener;

+	Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo;

+	Word16 coeff[5], coeff_lo[5], exp_coeff[5];

+	Word16 exp_max[5];

+	Word32 i, j, L_tmp, dist_min;

+	Word16 *past_qua_en, *t_qua_gain;

+

+	past_qua_en = mem;                     

+

+	/*-----------------------------------------------------------------*

+	 * - Find the initial quantization pitch index                     *

+	 * - Set gains search range                                        *

+	 *-----------------------------------------------------------------*/

+	if (nbits == 6)

+	{

+		t_qua_gain = t_qua_gain6b;         

+		min_ind = 0;                       

+		size = RANGE;                      

+

+		if(gp_clip == 1)

+		{

+			size = size - 16;          /* limit gain pitch to 1.0 */

+		}

+	} else

+	{

+		t_qua_gain = t_qua_gain7b;         

+

+		p = t_qua_gain7b + RANGE;            /* pt at 1/4th of table */

+

+		j = nb_qua_gain7b - RANGE;         

+

+		if (gp_clip == 1)

+		{

+			j = j - 27;                /* limit gain pitch to 1.0 */

+		}

+		min_ind = 0;                       

+		g_pitch = *gain_pit;               

+

+		for (i = 0; i < j; i++, p += 2)

+		{

+			if (g_pitch > *p)

+			{

+				min_ind = min_ind + 1;

+			}

+		}

+		size = RANGE;                      

+	}

+

+	/*------------------------------------------------------------------*

+	 *  Compute coefficient need for the quantization.                  *

+	 *                                                                  *

+	 *  coeff[0] =    y1 y1                                             *

+	 *  coeff[1] = -2 xn y1                                             *

+	 *  coeff[2] =    y2 y2                                             *

+	 *  coeff[3] = -2 xn y2                                             *

+	 *  coeff[4] =  2 y1 y2                                             *

+	 *                                                                  *

+	 * Product <y1 y1> and <xn y1> have been compute in G_pitch() and   *

+	 * are in vector g_coeff[].                                         *

+	 *------------------------------------------------------------------*/

+

+	coeff[0] = g_coeff[0];                 

+	exp_coeff[0] = g_coeff[1];             

+	coeff[1] = negate(g_coeff[2]);                    /* coeff[1] = -2 xn y1 */

+	exp_coeff[1] = g_coeff[3] + 1;     

+

+	/* Compute scalar product <y2[],y2[]> */

+#ifdef ASM_OPT                   /* asm optimization branch */

+	coeff[2] = extract_h(Dot_product12_asm(y2, y2, L_subfr, &exp));

+#else

+	coeff[2] = extract_h(Dot_product12(y2, y2, L_subfr, &exp));

+#endif

+	exp_coeff[2] = (exp - 18) + (Q_xn << 1);     /* -18 (y2 Q9) */

+

+	/* Compute scalar product -2*<xn[],y2[]> */

+#ifdef ASM_OPT                  /* asm optimization branch */

+	coeff[3] = extract_h(L_negate(Dot_product12_asm(xn, y2, L_subfr, &exp)));

+#else

+	coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_subfr, &exp)));

+#endif

+

+	exp_coeff[3] = (exp - 8) + Q_xn;  /* -9 (y2 Q9), +1 (2 xn y2) */

+

+	/* Compute scalar product 2*<y1[],y2[]> */

+#ifdef ASM_OPT                 /* asm optimization branch */

+	coeff[4] = extract_h(Dot_product12_asm(y1, y2, L_subfr, &exp));

+#else

+	coeff[4] = extract_h(Dot_product12(y1, y2, L_subfr, &exp));

+#endif

+	exp_coeff[4] = (exp - 8) + Q_xn;  /* -9 (y2 Q9), +1 (2 y1 y2) */

+

+	/*-----------------------------------------------------------------*

+	 *  Find energy of code and compute:                               *

+	 *                                                                 *

+	 *    L_tmp = MEAN_ENER - 10log10(energy of code/ L_subfr)         *

+	 *          = MEAN_ENER - 3.0103*log2(energy of code/ L_subfr)     *

+	 *-----------------------------------------------------------------*/

+#ifdef ASM_OPT                 /* asm optimization branch */

+	L_tmp = Dot_product12_asm(code, code, L_subfr, &exp_code);

+#else

+	L_tmp = Dot_product12(code, code, L_subfr, &exp_code);

+#endif

+	/* exp_code: -18 (code in Q9), -6 (/L_subfr), -31 (L_tmp Q31->Q0) */

+	exp_code = (exp_code - (18 + 6 + 31));

+

+	Log2(L_tmp, &exp, &frac);

+	exp += exp_code;

+	L_tmp = Mpy_32_16(exp, frac, -24660);  /* x -3.0103(Q13) -> Q14 */

+

+	L_tmp += (MEAN_ENER * 8192)<<1; /* + MEAN_ENER in Q14 */

+

+	/*-----------------------------------------------------------------*

+	 * Compute gcode0.                                                 *

+	 *  = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code    *

+	 *-----------------------------------------------------------------*/

+	L_tmp = (L_tmp << 10);              /* From Q14 to Q24 */

+	L_tmp += (pred[0] * past_qua_en[0])<<1;      /* Q13*Q10 -> Q24 */

+	L_tmp += (pred[1] * past_qua_en[1])<<1;      /* Q13*Q10 -> Q24 */

+	L_tmp += (pred[2] * past_qua_en[2])<<1;      /* Q13*Q10 -> Q24 */

+	L_tmp += (pred[3] * past_qua_en[3])<<1;      /* Q13*Q10 -> Q24 */

+

+	gcode0 = extract_h(L_tmp);             /* From Q24 to Q8  */

+

+	/*-----------------------------------------------------------------*

+	 * gcode0 = pow(10.0, gcode0/20)                                   *

+	 *        = pow(2, 3.321928*gcode0/20)                             *

+	 *        = pow(2, 0.166096*gcode0)                                *

+	 *-----------------------------------------------------------------*/

+

+	L_tmp = vo_L_mult(gcode0, 5443);          /* *0.166096 in Q15 -> Q24     */

+	L_tmp = L_tmp >> 8;               /* From Q24 to Q16             */

+	VO_L_Extract(L_tmp, &exp_gcode0, &frac);  /* Extract exponent of gcode0  */

+

+	gcode0 = (Word16)(Pow2(14, frac));    /* Put 14 as exponent so that  */

+	/* output of Pow2() will be:   */

+	/* 16384 < Pow2() <= 32767     */

+	exp_gcode0 -= 14;

+

+	/*-------------------------------------------------------------------------*

+	 * Find the best quantizer                                                 *

+	 * ~~~~~~~~~~~~~~~~~~~~~~~                                                 *

+	 * Before doing the computation we need to aling exponents of coeff[]      *

+	 * to be sure to have the maximum precision.                               *

+	 *                                                                         *

+	 * In the table the pitch gains are in Q14, the code gains are in Q11 and  *

+	 * are multiply by gcode0 which have been multiply by 2^exp_gcode0.        *

+	 * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code  *

+	 * we divide by 2^15.                                                      *

+	 * Considering all the scaling above we have:                              *

+	 *                                                                         *

+	 *   exp_code = exp_gcode0-11+15 = exp_gcode0+4                            *

+	 *                                                                         *

+	 *   g_pitch*g_pitch  = -14-14+15                                          *

+	 *   g_pitch          = -14                                                *

+	 *   g_code*g_code    = (2*exp_code)+15                                    *

+	 *   g_code           = exp_code                                           *

+	 *   g_pitch*g_code   = -14 + exp_code +15                                 *

+	 *                                                                         *

+	 *   g_pitch*g_pitch * coeff[0]  ;exp_max0 = exp_coeff[0] - 13             *

+	 *   g_pitch         * coeff[1]  ;exp_max1 = exp_coeff[1] - 14             *

+	 *   g_code*g_code   * coeff[2]  ;exp_max2 = exp_coeff[2] +15+(2*exp_code) *

+	 *   g_code          * coeff[3]  ;exp_max3 = exp_coeff[3] + exp_code       *

+	 *   g_pitch*g_code  * coeff[4]  ;exp_max4 = exp_coeff[4] + 1 + exp_code   *

+	 *-------------------------------------------------------------------------*/

+

+	exp_code = (exp_gcode0 + 4);

+	exp_max[0] = (exp_coeff[0] - 13);    

+	exp_max[1] = (exp_coeff[1] - 14);    

+	exp_max[2] = (exp_coeff[2] + (15 + (exp_code << 1)));  

+	exp_max[3] = (exp_coeff[3] + exp_code);   

+	exp_max[4] = (exp_coeff[4] + (1 + exp_code));  

+

+	/* Find maximum exponant */

+

+	e_max = exp_max[0];                   

+	for (i = 1; i < 5; i++)

+	{

+		if(exp_max[i] > e_max)

+		{

+			e_max = exp_max[i];            

+		}

+	}

+

+	/* align coeff[] and save in special 32 bit double precision */

+

+	for (i = 0; i < 5; i++)

+	{

+		j = add1(vo_sub(e_max, exp_max[i]), 2);/* /4 to avoid overflow */

+		L_tmp = L_deposit_h(coeff[i]);

+		L_tmp = L_shr(L_tmp, j);

+		VO_L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);

+		coeff_lo[i] = (coeff_lo[i] >> 3);   /* lo >> 3 */

+	}

+

+	/* Codebook search */

+	dist_min = MAX_32;                     

+	p = &t_qua_gain[min_ind << 1];      

+

+	index = 0;                             

+	for (i = 0; i < size; i++)

+	{

+		g_pitch = *p++;                    

+		g_code = *p++;                     

+

+		g_code = ((g_code * gcode0) + 0x4000)>>15;

+		g2_pitch = ((g_pitch * g_pitch) + 0x4000)>>15;

+		g_pit_cod = ((g_code * g_pitch) + 0x4000)>>15;

+		L_tmp = (g_code * g_code)<<1;

+		VO_L_Extract(L_tmp, &g2_code, &g2_code_lo);

+

+		L_tmp = (coeff[2] * g2_code_lo)<<1;

+		L_tmp =  (L_tmp >> 3);

+		L_tmp += (coeff_lo[0] * g2_pitch)<<1;

+		L_tmp += (coeff_lo[1] * g_pitch)<<1;

+		L_tmp += (coeff_lo[2] * g2_code)<<1;

+		L_tmp += (coeff_lo[3] * g_code)<<1;

+		L_tmp += (coeff_lo[4] * g_pit_cod)<<1;

+		L_tmp =  (L_tmp >> 12);

+		L_tmp += (coeff[0] * g2_pitch)<<1;

+		L_tmp += (coeff[1] * g_pitch)<<1;

+		L_tmp += (coeff[2] * g2_code)<<1;

+		L_tmp += (coeff[3] * g_code)<<1;

+		L_tmp += (coeff[4] * g_pit_cod)<<1;

+

+		if(L_tmp < dist_min)

+		{

+			dist_min = L_tmp;              

+			index = i;                     

+		}

+	}

+

+	/* Read the quantized gains */

+	index = index + min_ind;

+	p = &t_qua_gain[(index + index)];    

+	*gain_pit = *p++;                       /* selected pitch gain in Q14 */

+	g_code = *p++;                          /* selected code gain in Q11  */

+

+	L_tmp = vo_L_mult(g_code, gcode0);             /* Q11*Q0 -> Q12 */

+	L_tmp = L_shl(L_tmp, (exp_gcode0 + 4));   /* Q12 -> Q16 */

+

+	*gain_cod = L_tmp;                       /* gain of code in Q16 */

+

+	/*---------------------------------------------------*

+	 * qua_ener = 20*log10(g_code)                       *

+	 *          = 6.0206*log2(g_code)                    *

+	 *          = 6.0206*(log2(g_codeQ11) - 11)          *

+	 *---------------------------------------------------*/

+

+	L_tmp = L_deposit_l(g_code);

+	Log2(L_tmp, &exp, &frac);

+	exp -= 11;

+	L_tmp = Mpy_32_16(exp, frac, 24660);   /* x 6.0206 in Q12 */

+

+	qua_ener = (Word16)(L_tmp >> 3); /* result in Q10 */

+

+	/* update table of past quantized energies */

+

+	past_qua_en[3] = past_qua_en[2];       

+	past_qua_en[2] = past_qua_en[1];       

+	past_qua_en[1] = past_qua_en[0];       

+	past_qua_en[0] = qua_ener;             

+

+	return (index);

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/q_pulse.c b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
new file mode 100644
index 0000000..a28ba40
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
@@ -0,0 +1,400 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: q_pulse.c                                                 *

+*                                                                      *

+*      Description: Coding and decoding of algebraic codebook          *

+*                                                                      *

+************************************************************************/

+

+#include <stdio.h>

+#include "typedef.h"

+#include "basic_op.h"

+#include "q_pulse.h"

+

+#define NB_POS 16                          /* pos in track, mask for sign bit */

+

+Word32 quant_1p_N1(                        /* (o) return N+1 bits             */

+		Word16 pos,                        /* (i) position of the pulse       */

+		Word16 N)                          /* (i) number of bits for position */

+{

+	Word16 mask;

+	Word32 index;

+

+	mask = (1 << N) - 1;              /* mask = ((1<<N)-1); */

+	/*-------------------------------------------------------*

+	 * Quantization of 1 pulse with N+1 bits:                *

+	 *-------------------------------------------------------*/

+	index = L_deposit_l((Word16) (pos & mask));

+	if ((pos & NB_POS) != 0)

+	{

+		index = vo_L_add(index, L_deposit_l(1 << N));   /* index += 1 << N; */

+	}

+	return (index);

+}

+

+

+Word32 quant_2p_2N1(                       /* (o) return (2*N)+1 bits         */

+		Word16 pos1,                          /* (i) position of the pulse 1     */

+		Word16 pos2,                          /* (i) position of the pulse 2     */

+		Word16 N)                             /* (i) number of bits for position */

+{

+	Word16 mask, tmp;

+	Word32 index;

+	mask = (1 << N) - 1;              /* mask = ((1<<N)-1); */

+	/*-------------------------------------------------------*

+	 * Quantization of 2 pulses with 2*N+1 bits:             *

+	 *-------------------------------------------------------*/

+	if (((pos2 ^ pos1) & NB_POS) == 0)

+	{

+		/* sign of 1st pulse == sign of 2th pulse */

+		if(pos1 <= pos2)          /* ((pos1 - pos2) <= 0) */

+		{

+			/* index = ((pos1 & mask) << N) + (pos2 & mask); */

+			index = L_deposit_l(add1((((Word16) (pos1 & mask)) << N), ((Word16) (pos2 & mask))));

+		} else

+		{

+			/* ((pos2 & mask) << N) + (pos1 & mask); */

+			index = L_deposit_l(add1((((Word16) (pos2 & mask)) << N), ((Word16) (pos1 & mask))));

+		}

+		if ((pos1 & NB_POS) != 0)

+		{

+			tmp = (N << 1);

+			index = vo_L_add(index, (1L << tmp));       /* index += 1 << (2*N); */

+		}

+	} else

+	{

+		/* sign of 1st pulse != sign of 2th pulse */

+		if (vo_sub((Word16) (pos1 & mask), (Word16) (pos2 & mask)) <= 0)

+		{

+			/* index = ((pos2 & mask) << N) + (pos1 & mask); */

+			index = L_deposit_l(add1((((Word16) (pos2 & mask)) << N), ((Word16) (pos1 & mask)))); 

+			if ((pos2 & NB_POS) != 0)

+			{

+				tmp = (N << 1);           /* index += 1 << (2*N); */

+				index = vo_L_add(index, (1L << tmp));

+			}

+		} else

+		{

+			/* index = ((pos1 & mask) << N) + (pos2 & mask);	 */

+			index = L_deposit_l(add1((((Word16) (pos1 & mask)) << N), ((Word16) (pos2 & mask)))); 

+			if ((pos1 & NB_POS) != 0)

+			{

+				tmp = (N << 1);

+				index = vo_L_add(index, (1 << tmp));    /* index += 1 << (2*N); */

+			}

+		}

+	}

+	return (index);

+}

+

+

+Word32 quant_3p_3N1(                       /* (o) return (3*N)+1 bits         */

+		Word16 pos1,                          /* (i) position of the pulse 1     */

+		Word16 pos2,                          /* (i) position of the pulse 2     */

+		Word16 pos3,                          /* (i) position of the pulse 3     */

+		Word16 N)                             /* (i) number of bits for position */

+{

+	Word16 nb_pos;

+	Word32 index;

+

+	nb_pos =(1 <<(N - 1));            /* nb_pos = (1<<(N-1)); */

+	/*-------------------------------------------------------*

+	 * Quantization of 3 pulses with 3*N+1 bits:             *

+	 *-------------------------------------------------------*/

+	if (((pos1 ^ pos2) & nb_pos) == 0)

+	{

+		index = quant_2p_2N1(pos1, pos2, sub(N, 1));    /* index = quant_2p_2N1(pos1, pos2, (N-1)); */

+		/* index += (pos1 & nb_pos) << N; */

+		index = vo_L_add(index, (L_deposit_l((Word16) (pos1 & nb_pos)) << N));  

+		/* index += quant_1p_N1(pos3, N) << (2*N); */

+		index = vo_L_add(index, (quant_1p_N1(pos3, N)<<(N << 1)));

+

+	} else if (((pos1 ^ pos3) & nb_pos) == 0)

+	{

+		index = quant_2p_2N1(pos1, pos3, sub(N, 1));    /* index = quant_2p_2N1(pos1, pos3, (N-1)); */

+		index = vo_L_add(index, (L_deposit_l((Word16) (pos1 & nb_pos)) << N)); 

+		/* index += (pos1 & nb_pos) << N; */

+		index = vo_L_add(index, (quant_1p_N1(pos2, N) << (N << 1)));

+		/* index += quant_1p_N1(pos2, N) <<

+		 * (2*N); */

+	} else

+	{

+		index = quant_2p_2N1(pos2, pos3, (N - 1));    /* index = quant_2p_2N1(pos2, pos3, (N-1)); */

+		/* index += (pos2 & nb_pos) << N;			 */

+		index = vo_L_add(index, (L_deposit_l((Word16) (pos2 & nb_pos)) << N));  

+		/* index += quant_1p_N1(pos1, N) << (2*N);	 */

+		index = vo_L_add(index, (quant_1p_N1(pos1, N) << (N << 1)));

+	}

+	return (index);

+}

+

+

+Word32 quant_4p_4N1(                       /* (o) return (4*N)+1 bits         */

+		Word16 pos1,                          /* (i) position of the pulse 1     */

+		Word16 pos2,                          /* (i) position of the pulse 2     */

+		Word16 pos3,                          /* (i) position of the pulse 3     */

+		Word16 pos4,                          /* (i) position of the pulse 4     */

+		Word16 N)                             /* (i) number of bits for position */

+{

+	Word16 nb_pos;

+	Word32 index;

+

+	nb_pos = 1 << (N - 1);            /* nb_pos = (1<<(N-1));  */

+	/*-------------------------------------------------------*

+	 * Quantization of 4 pulses with 4*N+1 bits:             *

+	 *-------------------------------------------------------*/

+	if (((pos1 ^ pos2) & nb_pos) == 0)

+	{

+		index = quant_2p_2N1(pos1, pos2, sub(N, 1));    /* index = quant_2p_2N1(pos1, pos2, (N-1)); */

+		/* index += (pos1 & nb_pos) << N;	 */

+		index = vo_L_add(index, (L_deposit_l((Word16) (pos1 & nb_pos)) << N));  

+		/* index += quant_2p_2N1(pos3, pos4, N) << (2*N); */

+		index = vo_L_add(index, (quant_2p_2N1(pos3, pos4, N) << (N << 1)));

+	} else if (((pos1 ^ pos3) & nb_pos) == 0)

+	{

+		index = quant_2p_2N1(pos1, pos3, (N - 1));

+		/* index += (pos1 & nb_pos) << N; */

+		index = vo_L_add(index, (L_deposit_l((Word16) (pos1 & nb_pos)) << N));  

+		/* index += quant_2p_2N1(pos2, pos4, N) << (2*N); */

+		index = vo_L_add(index, (quant_2p_2N1(pos2, pos4, N) << (N << 1)));

+	} else

+	{

+		index = quant_2p_2N1(pos2, pos3, (N - 1));

+		/* index += (pos2 & nb_pos) << N; */

+		index = vo_L_add(index, (L_deposit_l((Word16) (pos2 & nb_pos)) << N));  

+		/* index += quant_2p_2N1(pos1, pos4, N) << (2*N); */

+		index = vo_L_add(index, (quant_2p_2N1(pos1, pos4, N) << (N << 1)));

+	}

+	return (index);

+}

+

+

+Word32 quant_4p_4N(                        /* (o) return 4*N bits             */

+		Word16 pos[],                         /* (i) position of the pulse 1..4  */

+		Word16 N)                             /* (i) number of bits for position */

+{

+	Word16 nb_pos, mask, n_1, tmp;

+	Word16 posA[4], posB[4];

+	Word32 i, j, k, index;

+

+	n_1 = (Word16) (N - 1);                

+	nb_pos = (1 << n_1);                  /* nb_pos = (1<<n_1); */

+	mask = vo_sub((1 << N), 1);              /* mask = ((1<<N)-1); */

+

+	i = 0;                                 

+	j = 0;                                 

+	for (k = 0; k < 4; k++)

+	{

+		if ((pos[k] & nb_pos) == 0)

+		{

+			posA[i++] = pos[k];            

+		} else

+		{

+			posB[j++] = pos[k];            

+		}

+	}

+

+	switch (i)

+	{

+		case 0:

+			tmp = vo_sub((N << 2), 3);           /* index = 1 << ((4*N)-3); */

+			index = (1L << tmp);

+			/* index += quant_4p_4N1(posB[0], posB[1], posB[2], posB[3], n_1); */

+			index = vo_L_add(index, quant_4p_4N1(posB[0], posB[1], posB[2], posB[3], n_1));

+			break;

+		case 1:

+			/* index = quant_1p_N1(posA[0], n_1) << ((3*n_1)+1); */

+			tmp = add1((Word16)((vo_L_mult(3, n_1) >> 1)), 1);

+			index = L_shl(quant_1p_N1(posA[0], n_1), tmp);

+			/* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1); */

+			index = vo_L_add(index, quant_3p_3N1(posB[0], posB[1], posB[2], n_1));

+			break;

+		case 2:

+			tmp = ((n_1 << 1) + 1);         /* index = quant_2p_2N1(posA[0], posA[1], n_1) << ((2*n_1)+1); */

+			index = L_shl(quant_2p_2N1(posA[0], posA[1], n_1), tmp);

+			/* index += quant_2p_2N1(posB[0], posB[1], n_1); */

+			index = vo_L_add(index, quant_2p_2N1(posB[0], posB[1], n_1));

+			break;

+		case 3:

+			/* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << N; */

+			index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), N);

+			index = vo_L_add(index, quant_1p_N1(posB[0], n_1));        /* index += quant_1p_N1(posB[0], n_1); */

+			break;

+		case 4:

+			index = quant_4p_4N1(posA[0], posA[1], posA[2], posA[3], n_1);

+			break;

+		default:

+			index = 0;

+			fprintf(stderr, "Error in function quant_4p_4N\n");

+	}

+	tmp = ((N << 2) - 2);               /* index += (i & 3) << ((4*N)-2); */

+	index = vo_L_add(index, L_shl((L_deposit_l(i) & (3L)), tmp));

+

+	return (index);

+}

+

+

+

+Word32 quant_5p_5N(                        /* (o) return 5*N bits             */

+		Word16 pos[],                         /* (i) position of the pulse 1..5  */

+		Word16 N)                             /* (i) number of bits for position */

+{

+	Word16 nb_pos, n_1, tmp;

+	Word16 posA[5], posB[5];

+	Word32 i, j, k, index, tmp2;

+

+	n_1 = (Word16) (N - 1);                

+	nb_pos = (1 << n_1);                  /* nb_pos = (1<<n_1); */

+

+	i = 0;                                 

+	j = 0;                                 

+	for (k = 0; k < 5; k++)

+	{

+		if ((pos[k] & nb_pos) == 0)

+		{

+			posA[i++] = pos[k];            

+		} else

+		{

+			posB[j++] = pos[k];            

+		}

+	}

+

+	switch (i)

+	{

+		case 0:

+			tmp = vo_sub((Word16)((vo_L_mult(5, N) >> 1)), 1);        /* ((5*N)-1)) */

+			index = L_shl(1L, tmp);   /* index = 1 << ((5*N)-1); */

+			tmp = add1((N << 1), 1);  /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) << ((2*N)+1);*/

+			tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);

+			index = vo_L_add(index, tmp2);

+			index = vo_L_add(index, quant_2p_2N1(posB[3], posB[4], N));        /* index += quant_2p_2N1(posB[3], posB[4], N); */

+			break;

+		case 1:

+			tmp = vo_sub((Word16)((vo_L_mult(5, N) >> 1)), 1);        /* index = 1 << ((5*N)-1); */

+			index = L_shl(1L, tmp);

+			tmp = add1((N << 1), 1);   /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) <<((2*N)+1);  */

+			tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);

+			index = vo_L_add(index, tmp2);

+			index = vo_L_add(index, quant_2p_2N1(posB[3], posA[0], N));        /* index += quant_2p_2N1(posB[3], posA[0], N); */

+			break;

+		case 2:

+			tmp = vo_sub((Word16)((vo_L_mult(5, N) >> 1)), 1);        /* ((5*N)-1)) */

+			index = L_shl(1L, tmp);            /* index = 1 << ((5*N)-1); */

+			tmp = add1((N << 1), 1);           /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) << ((2*N)+1);  */

+			tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);

+			index = vo_L_add(index, tmp2);

+			index = vo_L_add(index, quant_2p_2N1(posA[0], posA[1], N));        /* index += quant_2p_2N1(posA[0], posA[1], N); */

+			break;

+		case 3:

+			tmp = add1((N << 1), 1);           /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1);  */

+			index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);

+			index = vo_L_add(index, quant_2p_2N1(posB[0], posB[1], N));        /* index += quant_2p_2N1(posB[0], posB[1], N); */

+			break;

+		case 4:

+			tmp = add1((N << 1), 1);           /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1);  */

+			index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);

+			index = vo_L_add(index, quant_2p_2N1(posA[3], posB[0], N));        /* index += quant_2p_2N1(posA[3], posB[0], N); */

+			break;

+		case 5:

+			tmp = add1((N << 1), 1);           /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1);  */

+			index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);

+			index = vo_L_add(index, quant_2p_2N1(posA[3], posA[4], N));        /* index += quant_2p_2N1(posA[3], posA[4], N); */

+			break;

+		default:

+			index = 0;

+			fprintf(stderr, "Error in function quant_5p_5N\n");

+	}

+

+	return (index);

+}

+

+

+Word32 quant_6p_6N_2(                      /* (o) return (6*N)-2 bits         */

+		Word16 pos[],                         /* (i) position of the pulse 1..6  */

+		Word16 N)                             /* (i) number of bits for position */

+{

+	Word16 nb_pos, n_1;

+	Word16 posA[6], posB[6];

+	Word32 i, j, k, index;

+

+	/* !!  N and n_1 are constants -> it doesn't need to be operated by Basic Operators */

+	n_1 = (Word16) (N - 1);                

+	nb_pos = (1 << n_1);                  /* nb_pos = (1<<n_1); */

+

+	i = 0;                                 

+	j = 0;                                 

+	for (k = 0; k < 6; k++)

+	{

+		if ((pos[k] & nb_pos) == 0)

+		{

+			posA[i++] = pos[k];            

+		} else

+		{

+			posB[j++] = pos[k];            

+		}

+	}

+

+	switch (i)

+	{

+		case 0:

+			index = (1 << (Word16) (6 * N - 5));        /* index = 1 << ((6*N)-5); */

+			index = vo_L_add(index, (quant_5p_5N(posB, n_1) << N)); /* index += quant_5p_5N(posB, n_1) << N; */

+			index = vo_L_add(index, quant_1p_N1(posB[5], n_1));        /* index += quant_1p_N1(posB[5], n_1); */

+			break;

+		case 1:

+			index = (1L << (Word16) (6 * N - 5));        /* index = 1 << ((6*N)-5); */

+			index = vo_L_add(index, (quant_5p_5N(posB, n_1) << N)); /* index += quant_5p_5N(posB, n_1) << N; */

+			index = vo_L_add(index, quant_1p_N1(posA[0], n_1));        /* index += quant_1p_N1(posA[0], n_1); */

+			break;

+		case 2:

+			index = (1L << (Word16) (6 * N - 5));        /* index = 1 << ((6*N)-5); */

+			/* index += quant_4p_4N(posB, n_1) << ((2*n_1)+1); */

+			index = vo_L_add(index, (quant_4p_4N(posB, n_1) << (Word16) (2 * n_1 + 1)));

+			index = vo_L_add(index, quant_2p_2N1(posA[0], posA[1], n_1));      /* index += quant_2p_2N1(posA[0], posA[1], n_1); */

+			break;

+		case 3:

+			index = (quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << (Word16) (3 * n_1 + 1));    

+			                                  /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((3*n_1)+1); */

+			index =vo_L_add(index, quant_3p_3N1(posB[0], posB[1], posB[2], n_1));     

+			                                 /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1); */

+			break;

+		case 4:

+			i = 2;                            

+			index = (quant_4p_4N(posA, n_1) << (Word16) (2 * n_1 + 1));  /* index = quant_4p_4N(posA, n_1) << ((2*n_1)+1); */

+			index = vo_L_add(index, quant_2p_2N1(posB[0], posB[1], n_1));      /* index += quant_2p_2N1(posB[0], posB[1], n_1); */

+			break;

+		case 5:

+			i = 1;                            

+			index = (quant_5p_5N(posA, n_1) << N);       /* index = quant_5p_5N(posA, n_1) << N; */

+			index = vo_L_add(index, quant_1p_N1(posB[0], n_1));        /* index += quant_1p_N1(posB[0], n_1); */

+			break;

+		case 6:

+			i = 0;                             

+			index = (quant_5p_5N(posA, n_1) << N);       /* index = quant_5p_5N(posA, n_1) << N; */

+			index = vo_L_add(index, quant_1p_N1(posA[5], n_1));        /* index += quant_1p_N1(posA[5], n_1); */

+			break;

+		default:

+			index = 0;

+			fprintf(stderr, "Error in function quant_6p_6N_2\n");

+	}

+	index = vo_L_add(index, ((L_deposit_l(i) & 3L) << (Word16) (6 * N - 4)));   /* index += (i & 3) << ((6*N)-4); */

+

+	return (index);

+}

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/qisf_ns.c b/media/libstagefright/codecs/amrwbenc/src/qisf_ns.c
new file mode 100644
index 0000000..00b0a53
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/qisf_ns.c
@@ -0,0 +1,111 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***************************************************************************

+*      File: qisf_ns.c                                                     *

+*                                                                          *

+*      Description: Coding/Decoding of ISF parameters for background noise.*

+*                    The ISF vector is quantized using VQ with split-by-5  *

+*                                                                          *

+****************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "acelp.h"

+#include "qisf_ns.tab"                     /* Codebooks of ISFs */

+

+/*------------------------------------------------------------------*

+* routine:   Qisf_ns()                                             *

+*            ~~~~~~~~~                                             *

+*------------------------------------------------------------------*/

+

+void Qisf_ns(

+		Word16 * isf1,                        /* input : ISF in the frequency domain (0..0.5) */

+		Word16 * isf_q,                       /* output: quantized ISF                        */

+		Word16 * indice                       /* output: quantization indices                 */

+	    )

+{

+	Word16 i;

+	Word32 tmp;

+

+	for (i = 0; i < ORDER; i++)

+	{

+		isf_q[i] = sub(isf1[i], mean_isf_noise[i]);     

+	}

+

+	indice[0] = Sub_VQ(&isf_q[0], dico1_isf_noise, 2, SIZE_BK_NOISE1, &tmp);    

+	indice[1] = Sub_VQ(&isf_q[2], dico2_isf_noise, 3, SIZE_BK_NOISE2, &tmp);    

+	indice[2] = Sub_VQ(&isf_q[5], dico3_isf_noise, 3, SIZE_BK_NOISE3, &tmp);    

+	indice[3] = Sub_VQ(&isf_q[8], dico4_isf_noise, 4, SIZE_BK_NOISE4, &tmp);    

+	indice[4] = Sub_VQ(&isf_q[12], dico5_isf_noise, 4, SIZE_BK_NOISE5, &tmp);   

+

+	/* decoding the ISFs */

+

+	Disf_ns(indice, isf_q);

+

+	return;

+}

+

+/********************************************************************

+* Function:   Disf_ns()                                             *

+*            ~~~~~~~~~                                              *

+* Decoding of ISF parameters                                        *

+*-------------------------------------------------------------------*

+*  Arguments:                                                       *

+*    indice[] : indices of the selected codebook entries            *

+*    isf[]    : quantized ISFs (in frequency domain)                *

+*********************************************************************/

+

+void Disf_ns(

+		Word16 * indice,                      /* input:  quantization indices                  */

+		Word16 * isf_q                        /* input : ISF in the frequency domain (0..0.5)  */

+	    )

+{

+	Word16 i;

+

+	for (i = 0; i < 2; i++)

+	{

+		isf_q[i] = dico1_isf_noise[indice[0] * 2 + i];  

+	}

+	for (i = 0; i < 3; i++)

+	{

+		isf_q[i + 2] = dico2_isf_noise[indice[1] * 3 + i];      

+	}

+	for (i = 0; i < 3; i++)

+	{

+		isf_q[i + 5] = dico3_isf_noise[indice[2] * 3 + i];      

+	}

+	for (i = 0; i < 4; i++)

+	{

+		isf_q[i + 8] = dico4_isf_noise[indice[3] * 4 + i];      

+	}

+	for (i = 0; i < 4; i++)

+	{

+		isf_q[i + 12] = dico5_isf_noise[indice[4] * 4 + i];     

+	}

+

+	for (i = 0; i < ORDER; i++)

+	{

+		isf_q[i] = add(isf_q[i], mean_isf_noise[i]);   

+	}

+

+	Reorder_isf(isf_q, ISF_GAP, ORDER);

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c b/media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c
new file mode 100644
index 0000000..ccedb5c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c
@@ -0,0 +1,542 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: apisf_2s.c                                               *

+*                                                                      *

+*       Description: Coding/Decodeing of ISF parameters with predication

+*       The ISF vector is quantized using two-stage VQ with split-by-2 *

+*       in 1st stage and split-by-5(or 3) in the second stage          *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "cnst.h"

+#include "acelp.h"

+#include "qpisf_2s.tab"                    /* Codebooks of isfs */

+

+#define MU         10923                   /* Prediction factor   (1.0/3.0) in Q15 */

+#define N_SURV_MAX 4                       /* 4 survivors max */

+#define ALPHA      29491                   /* 0. 9 in Q15     */

+#define ONE_ALPHA (32768-ALPHA)            /* (1.0 - ALPHA) in Q15 */

+

+/* private functions */

+static void VQ_stage1(

+		Word16 * x,                           /* input : ISF residual vector           */

+		Word16 * dico,                        /* input : quantization codebook         */

+		Word16 dim,                           /* input : dimention of vector           */

+		Word16 dico_size,                     /* input : size of quantization codebook */

+		Word16 * index,                       /* output: indices of survivors          */

+		Word16 surv                           /* input : number of survivor            */

+		);

+

+/**************************************************************************

+* Function:   Qpisf_2s_46B()                                              *

+*                                                                         *

+* Description: Quantization of isf parameters with prediction. (46 bits)  *

+*                                                                         *

+* The isf vector is quantized using two-stage VQ with split-by-2 in       *

+*  1st stage and split-by-5 in the second stage.                          *

+***************************************************************************/

+

+void Qpisf_2s_46b(

+		Word16 * isf1,                        /* (i) Q15 : ISF in the frequency domain (0..0.5) */

+		Word16 * isf_q,                       /* (o) Q15 : quantized ISF               (0..0.5) */

+		Word16 * past_isfq,                   /* (io)Q15 : past ISF quantizer                   */

+		Word16 * indice,                      /* (o)     : quantization indices                 */

+		Word16 nb_surv                        /* (i)     : number of survivor (1, 2, 3 or 4)    */

+		)

+{

+	Word16 tmp_ind[5];

+	Word16 surv1[N_SURV_MAX];              /* indices of survivors from 1st stage */

+	Word32 i, k, temp, min_err, distance;

+	Word16 isf[ORDER];

+	Word16 isf_stage2[ORDER];

+

+	for (i = 0; i < ORDER; i++)

+	{

+		isf[i] = vo_sub(isf1[i], mean_isf[i]);

+		isf[i] = vo_sub(isf[i], vo_mult(MU, past_isfq[i])); 

+	}

+

+	VQ_stage1(&isf[0], dico1_isf, 9, SIZE_BK1, surv1, nb_surv);

+

+	distance = MAX_32;          

+

+	for (k = 0; k < nb_surv; k++)

+	{

+		for (i = 0; i < 9; i++)

+		{

+			isf_stage2[i] = vo_sub(isf[i], dico1_isf[i + surv1[k] * 9]); 

+		}

+		tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico21_isf, 3, SIZE_BK21, &min_err); 

+		temp = min_err;

+		tmp_ind[1] = Sub_VQ(&isf_stage2[3], dico22_isf, 3, SIZE_BK22, &min_err); 

+		temp = vo_L_add(temp, min_err);

+		tmp_ind[2] = Sub_VQ(&isf_stage2[6], dico23_isf, 3, SIZE_BK23, &min_err);  

+		temp = vo_L_add(temp, min_err);

+

+		if(temp < distance)

+		{

+			distance = temp;               

+			indice[0] = surv1[k];          

+			for (i = 0; i < 3; i++)

+			{

+				indice[i + 2] = tmp_ind[i];

+			}

+		}

+	}

+

+

+	VQ_stage1(&isf[9], dico2_isf, 7, SIZE_BK2, surv1, nb_surv);

+

+	distance = MAX_32;                   

+

+	for (k = 0; k < nb_surv; k++)

+	{

+		for (i = 0; i < 7; i++)

+		{

+			isf_stage2[i] = vo_sub(isf[9 + i], dico2_isf[i + surv1[k] * 7]);       

+		}

+

+		tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico24_isf, 3, SIZE_BK24, &min_err);

+		temp = min_err; 

+		tmp_ind[1] = Sub_VQ(&isf_stage2[3], dico25_isf, 4, SIZE_BK25, &min_err);

+		temp = vo_L_add(temp, min_err);

+

+		if(temp < distance)

+		{

+			distance = temp;               

+			indice[1] = surv1[k];          

+			for (i = 0; i < 2; i++)

+			{

+				indice[i + 5] = tmp_ind[i];

+			}

+		}

+	}

+

+	Dpisf_2s_46b(indice, isf_q, past_isfq, isf_q, isf_q, 0, 0);

+

+	return;

+}

+

+/*****************************************************************************

+* Function:   Qpisf_2s_36B()                                                 *

+*                                                                            *

+* Description: Quantization of isf parameters with prediction. (36 bits)     *

+*                                                                            *

+* The isf vector is quantized using two-stage VQ with split-by-2 in          *

+*  1st stage and split-by-3 in the second stage.                             *

+******************************************************************************/

+

+void Qpisf_2s_36b(

+		Word16 * isf1,                        /* (i) Q15 : ISF in the frequency domain (0..0.5) */

+		Word16 * isf_q,                       /* (o) Q15 : quantized ISF               (0..0.5) */

+		Word16 * past_isfq,                   /* (io)Q15 : past ISF quantizer                   */

+		Word16 * indice,                      /* (o)     : quantization indices                 */

+		Word16 nb_surv                        /* (i)     : number of survivor (1, 2, 3 or 4)    */

+		)

+{

+	Word16 i, k, tmp_ind[5];

+	Word16 surv1[N_SURV_MAX];              /* indices of survivors from 1st stage */

+	Word32 temp, min_err, distance;

+	Word16 isf[ORDER];

+	Word16 isf_stage2[ORDER];

+

+	for (i = 0; i < ORDER; i++)

+	{

+		isf[i] = vo_sub(isf1[i], mean_isf[i]);

+		isf[i] = vo_sub(isf[i], vo_mult(MU, past_isfq[i]));

+	}

+

+	VQ_stage1(&isf[0], dico1_isf, 9, SIZE_BK1, surv1, nb_surv);

+

+	distance = MAX_32;                  

+

+	for (k = 0; k < nb_surv; k++)

+	{

+		for (i = 0; i < 9; i++)

+		{

+			isf_stage2[i] = vo_sub(isf[i], dico1_isf[i + surv1[k] * 9]); 

+		}

+

+		tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico21_isf_36b, 5, SIZE_BK21_36b, &min_err);        

+		temp = min_err;                  

+		tmp_ind[1] = Sub_VQ(&isf_stage2[5], dico22_isf_36b, 4, SIZE_BK22_36b, &min_err);        

+		temp = vo_L_add(temp, min_err);

+

+		if(temp < distance)

+		{

+			distance = temp;               

+			indice[0] = surv1[k];          

+			for (i = 0; i < 2; i++)

+			{

+				indice[i + 2] = tmp_ind[i];

+			}

+		}

+	}

+

+	VQ_stage1(&isf[9], dico2_isf, 7, SIZE_BK2, surv1, nb_surv);

+	distance = MAX_32;                    

+

+	for (k = 0; k < nb_surv; k++)

+	{

+		for (i = 0; i < 7; i++)

+		{

+			isf_stage2[i] = vo_sub(isf[9 + i], dico2_isf[i + surv1[k] * 7]);     

+		}

+

+		tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico23_isf_36b, 7, SIZE_BK23_36b, &min_err);  

+		temp = min_err;                  

+

+		if(temp < distance)

+		{

+			distance = temp;               

+			indice[1] = surv1[k];          

+			indice[4] = tmp_ind[0];        

+		}

+	}

+

+	Dpisf_2s_36b(indice, isf_q, past_isfq, isf_q, isf_q, 0, 0);

+

+	return;

+}

+

+/*********************************************************************

+* Function: Dpisf_2s_46b()                                           *

+*                                                                    *

+* Description: Decoding of ISF parameters                            *

+**********************************************************************/

+

+void Dpisf_2s_46b(

+		Word16 * indice,                      /* input:  quantization indices                       */

+		Word16 * isf_q,                       /* output: quantized ISF in frequency domain (0..0.5) */

+		Word16 * past_isfq,                   /* i/0   : past ISF quantizer                    */

+		Word16 * isfold,                      /* input : past quantized ISF                    */

+		Word16 * isf_buf,                     /* input : isf buffer                                                        */

+		Word16 bfi,                           /* input : Bad frame indicator                   */

+		Word16 enc_dec

+		)

+{

+	Word16 ref_isf[M], tmp;

+	Word32 i, j, L_tmp;

+

+	if (bfi == 0)                          /* Good frame */

+	{

+		for (i = 0; i < 9; i++)

+		{

+			isf_q[i] = dico1_isf[indice[0] * 9 + i];    

+		}

+		for (i = 0; i < 7; i++)

+		{

+			isf_q[i + 9] = dico2_isf[indice[1] * 7 + i];       

+		}

+

+		for (i = 0; i < 3; i++)

+		{

+			isf_q[i] = add1(isf_q[i], dico21_isf[indice[2] * 3 + i]);   

+			isf_q[i + 3] = add1(isf_q[i + 3], dico22_isf[indice[3] * 3 + i]);  

+			isf_q[i + 6] = add1(isf_q[i + 6], dico23_isf[indice[4] * 3 + i]); 

+			isf_q[i + 9] = add1(isf_q[i + 9], dico24_isf[indice[5] * 3 + i]); 

+		}

+

+		for (i = 0; i < 4; i++)

+		{

+			isf_q[i + 12] = add1(isf_q[i + 12], dico25_isf[indice[6] * 4 + i]);  

+		}

+

+		for (i = 0; i < ORDER; i++)

+		{

+			tmp = isf_q[i];               

+			isf_q[i] = add1(tmp, mean_isf[i]);  

+			isf_q[i] = add1(isf_q[i], vo_mult(MU, past_isfq[i]));

+			past_isfq[i] = tmp;  

+		}

+

+		if (enc_dec)

+		{

+			for (i = 0; i < M; i++)

+			{

+				for (j = (L_MEANBUF - 1); j > 0; j--)

+				{

+					isf_buf[j * M + i] = isf_buf[(j - 1) * M + i]; 

+				}

+				isf_buf[i] = isf_q[i]; 

+			}

+		}

+	} else

+	{                                      /* bad frame */

+		for (i = 0; i < M; i++)

+		{

+			L_tmp = mean_isf[i] << 14;

+			for (j = 0; j < L_MEANBUF; j++)

+			{

+				L_tmp += (isf_buf[j * M + i] << 14);

+			}

+			ref_isf[i] = vo_round(L_tmp);

+		}

+

+		/* use the past ISFs slightly shifted towards their mean */

+		for (i = 0; i < ORDER; i++)

+		{

+			isf_q[i] = add1(vo_mult(ALPHA, isfold[i]), vo_mult(ONE_ALPHA, ref_isf[i])); 

+		}

+

+		/* estimate past quantized residual to be used in next frame */

+		for (i = 0; i < ORDER; i++)

+		{

+			tmp = add1(ref_isf[i], vo_mult(past_isfq[i], MU));      /* predicted ISF */

+			past_isfq[i] = vo_sub(isf_q[i], tmp); 

+			past_isfq[i] = (past_isfq[i] >> 1);        /* past_isfq[i] *= 0.5 */

+		}

+	}

+

+	Reorder_isf(isf_q, ISF_GAP, ORDER);

+	return;

+}

+

+/*********************************************************************

+* Function:   Disf_2s_36b()                                          *

+*                                                                    *

+* Description: Decoding of ISF parameters                            *

+*********************************************************************/

+

+void Dpisf_2s_36b(

+		Word16 * indice,                      /* input:  quantization indices                       */

+		Word16 * isf_q,                       /* output: quantized ISF in frequency domain (0..0.5) */

+		Word16 * past_isfq,                   /* i/0   : past ISF quantizer                    */

+		Word16 * isfold,                      /* input : past quantized ISF                    */

+		Word16 * isf_buf,                     /* input : isf buffer                                                        */

+		Word16 bfi,                           /* input : Bad frame indicator                   */

+		Word16 enc_dec

+		)

+{

+	Word16 ref_isf[M], tmp;

+	Word32 i, j, L_tmp;

+

+	if (bfi == 0)                          /* Good frame */

+	{

+		for (i = 0; i < 9; i++)

+		{

+			isf_q[i] = dico1_isf[indice[0] * 9 + i];    

+		}

+		for (i = 0; i < 7; i++)

+		{

+			isf_q[i + 9] = dico2_isf[indice[1] * 7 + i];       

+		}

+

+		for (i = 0; i < 5; i++)

+		{

+			isf_q[i] = add1(isf_q[i], dico21_isf_36b[indice[2] * 5 + i]);       

+		}

+		for (i = 0; i < 4; i++)

+		{

+			isf_q[i + 5] = add1(isf_q[i + 5], dico22_isf_36b[indice[3] * 4 + i]);        

+		}

+		for (i = 0; i < 7; i++)

+		{

+			isf_q[i + 9] = add1(isf_q[i + 9], dico23_isf_36b[indice[4] * 7 + i]);       

+		}

+

+		for (i = 0; i < ORDER; i++)

+		{

+			tmp = isf_q[i];

+			isf_q[i] = add1(tmp, mean_isf[i]);   

+			isf_q[i] = add1(isf_q[i], vo_mult(MU, past_isfq[i]));   

+			past_isfq[i] = tmp;           

+		}

+

+

+		if (enc_dec)

+		{

+			for (i = 0; i < M; i++)

+			{

+				for (j = (L_MEANBUF - 1); j > 0; j--)

+				{

+					isf_buf[j * M + i] = isf_buf[(j - 1) * M + i];      

+				}

+				isf_buf[i] = isf_q[i];    

+			}

+		}

+	} else

+	{                                      /* bad frame */

+		for (i = 0; i < M; i++)

+		{

+			L_tmp = (mean_isf[i] << 14);

+			for (j = 0; j < L_MEANBUF; j++)

+			{

+				L_tmp += (isf_buf[j * M + i] << 14);

+			}

+			ref_isf[i] = vo_round(L_tmp);    

+		}

+

+		/* use the past ISFs slightly shifted towards their mean */

+		for (i = 0; i < ORDER; i++)

+		{

+			isf_q[i] = add1(vo_mult(ALPHA, isfold[i]), vo_mult(ONE_ALPHA, ref_isf[i]));        

+		}

+

+		/* estimate past quantized residual to be used in next frame */

+		for (i = 0; i < ORDER; i++)

+		{

+			tmp = add1(ref_isf[i], vo_mult(past_isfq[i], MU));      /* predicted ISF */

+			past_isfq[i] = vo_sub(isf_q[i], tmp);  

+			past_isfq[i] = past_isfq[i] >> 1;         /* past_isfq[i] *= 0.5 */

+		}

+	}

+

+	Reorder_isf(isf_q, ISF_GAP, ORDER);

+

+	return;

+}

+

+

+/***************************************************************************

+* Function:  Reorder_isf()                                                 *

+*                                                                          *

+* Description: To make sure that the  isfs are properly order and to       *

+*              keep a certain minimum distance between consecutive isfs.   *

+*--------------------------------------------------------------------------*

+*    Argument         description                     in/out               *

+*                                                                          *

+*     isf[]           vector of isfs                    i/o                *

+*     min_dist        minimum required distance         i                  *

+*     n               LPC order                         i                  *

+****************************************************************************/

+

+void Reorder_isf(

+		Word16 * isf,                         /* (i/o) Q15: ISF in the frequency domain (0..0.5) */

+		Word16 min_dist,                      /* (i) Q15  : minimum distance to keep             */

+		Word16 n                              /* (i)      : number of ISF                        */

+		)

+{

+	Word32 i; 

+	Word16 isf_min;

+

+	isf_min = min_dist;                    

+	for (i = 0; i < n - 1; i++)

+	{

+		if(isf[i] < isf_min)

+		{

+			isf[i] = isf_min;              

+		}

+		isf_min = (isf[i] + min_dist);

+	}

+	return;

+}

+

+

+Word16 Sub_VQ(                             /* output: return quantization index     */

+		Word16 * x,                           /* input : ISF residual vector           */

+		Word16 * dico,                        /* input : quantization codebook         */

+		Word16 dim,                           /* input : dimention of vector           */

+		Word16 dico_size,                     /* input : size of quantization codebook */

+		Word32 * distance                     /* output: error of quantization         */

+	     )

+{

+	Word16 temp, *p_dico;

+	Word32 i, j, index;

+	Word32 dist_min, dist;

+

+	dist_min = MAX_32;                     

+	p_dico = dico;                         

+

+	index = 0;                             

+	for (i = 0; i < dico_size; i++)

+	{

+		dist = 0;  

+

+		for (j = 0; j < dim; j++)

+		{

+			temp = x[j] - (*p_dico++);

+			dist += (temp * temp)<<1;

+		}

+

+		if(dist < dist_min)

+		{

+			dist_min = dist;               

+			index = i;                     

+		}

+	}

+

+	*distance = dist_min;                  

+

+	/* Reading the selected vector */

+	p_dico = &dico[index * dim];           

+	for (j = 0; j < dim; j++)

+	{

+		x[j] = *p_dico++;                  

+	}

+

+	return index;

+}

+

+

+static void VQ_stage1(

+		Word16 * x,                           /* input : ISF residual vector           */

+		Word16 * dico,                        /* input : quantization codebook         */

+		Word16 dim,                           /* input : dimention of vector           */

+		Word16 dico_size,                     /* input : size of quantization codebook */

+		Word16 * index,                       /* output: indices of survivors          */

+		Word16 surv                           /* input : number of survivor            */

+		)

+{

+	Word16 temp, *p_dico;

+	Word32 i, j, k, l;

+	Word32 dist_min[N_SURV_MAX], dist;

+

+	dist_min[0] = MAX_32;

+	dist_min[1] = MAX_32;

+	dist_min[2] = MAX_32;

+	dist_min[3] = MAX_32;

+	index[0] = 0;

+	index[1] = 1;

+	index[2] = 2;

+	index[3] = 3;

+

+	p_dico = dico;                         

+

+	for (i = 0; i < dico_size; i++)

+	{

+		dist = 0;                          

+		for (j = 0; j < dim; j++)

+		{

+			temp = x[j] -  (*p_dico++);

+			dist += (temp * temp)<<1;

+		}

+

+		for (k = 0; k < surv; k++)

+		{

+			if(dist < dist_min[k])

+			{

+				for (l = surv - 1; l > k; l--)

+				{

+					dist_min[l] = dist_min[l - 1];      

+					index[l] = index[l - 1];    

+				}

+				dist_min[k] = dist;        

+				index[k] = i;              

+				break;

+			}

+		}

+	}

+	return;

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/random.c b/media/libstagefright/codecs/amrwbenc/src/random.c
new file mode 100644
index 0000000..8baa8bf
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/random.c
@@ -0,0 +1,33 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: random.c                                                 *

+*                                                                      *

+*       Description: Signed 16 bits random generator                   *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+Word16 Random(Word16 * seed)

+{

+	/* static Word16 seed = 21845; */

+	*seed = (Word16)(L_add((L_mult(*seed, 31821) >> 1), 13849L));

+	return (*seed);

+}

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/residu.c b/media/libstagefright/codecs/amrwbenc/src/residu.c
new file mode 100644
index 0000000..6829882
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/residu.c
@@ -0,0 +1,67 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*  File: residu.c                                                      *

+*                                                                      *

+*  Description: Compute the LPC residual by filtering                  *

+*             the input speech through A(z)                            *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+void Residu(

+		Word16 a[],                           /* (i) Q12 : prediction coefficients                     */

+		Word16 x[],                           /* (i)     : speech (values x[-m..-1] are needed         */

+		Word16 y[],                           /* (o) x2  : residual signal                             */

+		Word16 lg                             /* (i)     : size of filtering                           */

+		)

+{

+	Word16 i,*p1, *p2;

+	Word32 s;

+	for (i = 0; i < lg; i++)

+	{

+		p1 = a;

+		p2 = &x[i];

+		s  = vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1++), (*p2--));

+		s += vo_mult32((*p1), (*p2));

+

+		s = L_shl2(s, 5); 

+		y[i] = extract_h(L_add(s, 0x8000));

+	}

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/scale.c b/media/libstagefright/codecs/amrwbenc/src/scale.c
new file mode 100644
index 0000000..af40121
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/scale.c
@@ -0,0 +1,57 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: scale.c                                                  *

+*                                                                      *

+*       Description: Scale signal to get maximum of dynamic            *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+void Scale_sig(

+		Word16 x[],                           /* (i/o) : signal to scale               */

+		Word16 lg,                            /* (i)   : size of x[]                   */

+		Word16 exp                            /* (i)   : exponent: x = round(x << exp) */

+	      )

+{

+	Word32 i;

+	Word32 L_tmp;

+	if(exp > 0)

+	{

+		for (i = lg - 1 ; i >= 0; i--)

+		{

+			L_tmp = L_shl2(x[i], 16 + exp);  

+			x[i] = extract_h(L_add(L_tmp, 0x8000));            

+		}

+	}

+	else

+	{

+		exp = -exp;

+		for (i = lg - 1; i >= 0; i--)

+		{

+			L_tmp = x[i] << 16;

+			L_tmp >>= exp; 

+			x[i] = (L_tmp + 0x8000)>>16;            

+		}

+	}

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/stream.c b/media/libstagefright/codecs/amrwbenc/src/stream.c
new file mode 100644
index 0000000..a708235
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/stream.c
@@ -0,0 +1,58 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: stream.c                                                 *

+*                                                                      *

+*       Description: VOME API Buffer Operator Implement Code           *

+*                                                                      *

+************************************************************************/

+

+#include "stream.h"

+

+void voAWB_InitFrameBuffer(FrameStream *stream)

+{

+	stream->set_ptr = NULL;

+	stream->frame_ptr_bk = stream->frame_ptr;

+	stream->set_len = 0;

+	stream->framebuffer_len = 0;

+	stream->frame_storelen = 0;	

+}

+

+void voAWB_UpdateFrameBuffer(

+		FrameStream *stream, 

+		VO_MEM_OPERATOR *pMemOP

+		)

+{

+	int  len;

+	len  = MIN(Frame_Maxsize - stream->frame_storelen, stream->set_len);

+	pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk + stream->frame_storelen , stream->set_ptr, len);

+	stream->set_len -= len;

+	stream->set_ptr += len;

+	stream->framebuffer_len = stream->frame_storelen + len;

+	stream->frame_ptr = stream->frame_ptr_bk;

+	stream->used_len += len;

+}

+

+void voAWB_FlushFrameBuffer(FrameStream *stream)

+{

+	stream->set_ptr = NULL;

+	stream->frame_ptr_bk = stream->frame_ptr;

+	stream->set_len = 0;

+	stream->framebuffer_len = 0;

+	stream->frame_storelen = 0;	

+}

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/syn_filt.c b/media/libstagefright/codecs/amrwbenc/src/syn_filt.c
new file mode 100644
index 0000000..6c1fb8e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/syn_filt.c
@@ -0,0 +1,160 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: syn_filt.c                                               *

+*                                                                      *

+*       Description: Do the synthesis filtering 1/A(z)                 *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+#include "cnst.h"

+

+void Syn_filt(

+		Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients           */

+		Word16 x[],                           /* (i)     : input signal                             */

+		Word16 y[],                           /* (o)     : output signal                            */

+		Word16 lg,                            /* (i)     : size of filtering                        */

+		Word16 mem[],                         /* (i/o)   : memory associated with this filtering.   */

+		Word16 update                         /* (i)     : 0=no update, 1=update of memory.         */

+	     )

+{

+	Word32 i, a0;

+	Word16 y_buf[L_SUBFR16k + M16k];

+	Word32 L_tmp;

+	Word16 *yy, *p1, *p2;

+	yy = &y_buf[0];                        

+	/* copy initial filter states into synthesis buffer */

+	for (i = 0; i < 16; i++)

+	{

+		*yy++ = mem[i];                    

+	}

+	a0 = (a[0] >> 1);                     /* input / 2 */

+	/* Do the filtering. */

+	for (i = 0; i < lg; i++)

+	{

+		p1 = &a[1];

+		p2 = &yy[i-1];

+		L_tmp  = vo_mult32(a0, x[i]);

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1++), (*p2--));

+		L_tmp -= vo_mult32((*p1), (*p2));

+

+		L_tmp = L_shl2(L_tmp, 4);

+		y[i] = yy[i] = extract_h(L_add(L_tmp, 0x8000));  

+	}

+	/* Update memory if required */

+	if (update)

+		for (i = 0; i < 16; i++)

+		{

+			mem[i] = yy[lg - 16 + i];

+		}

+	return;

+}

+

+

+void Syn_filt_32(

+		Word16 a[],                           /* (i) Q12 : a[m+1] prediction coefficients */

+		Word16 m,                             /* (i)     : order of LP filter             */

+		Word16 exc[],                         /* (i) Qnew: excitation (exc[i] >> Qnew)    */

+		Word16 Qnew,                          /* (i)     : exc scaling = 0(min) to 8(max) */

+		Word16 sig_hi[],                      /* (o) /16 : synthesis high                 */

+		Word16 sig_lo[],                      /* (o) /16 : synthesis low                  */

+		Word16 lg                             /* (i)     : size of filtering              */

+		)

+{

+	Word32 i,a0;

+	Word32 L_tmp, L_tmp1;

+	Word16 *p1, *p2, *p3;

+	a0 = a[0] >> (4 + Qnew);          /* input / 16 and >>Qnew */

+	/* Do the filtering. */

+	for (i = 0; i < lg; i++)

+	{

+		L_tmp  = 0; 

+		L_tmp1 = 0;

+		p1 = a;

+		p2 = &sig_lo[i - 1];

+		p3 = &sig_hi[i - 1];

+

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+		L_tmp  -= vo_mult32((*p2--), (*p1));

+		L_tmp1 -= vo_mult32((*p3--), (*p1++));

+

+		L_tmp = L_tmp >> 11;      

+		L_tmp += vo_L_mult(exc[i], a0);

+

+		/* sig_hi = bit16 to bit31 of synthesis */

+		L_tmp = L_tmp - (L_tmp1<<1);

+

+		L_tmp = L_tmp >> 3;           /* ai in Q12 */

+		sig_hi[i] = extract_h(L_tmp);      

+

+		/* sig_lo = bit4 to bit15 of synthesis */

+		L_tmp >>= 4;           /* 4 : sig_lo[i] >> 4 */

+		sig_lo[i] = (Word16)((L_tmp - (sig_hi[i] << 13)));  

+	}

+

+	return;

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/updt_tar.c b/media/libstagefright/codecs/amrwbenc/src/updt_tar.c
new file mode 100644
index 0000000..f3e5650
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/updt_tar.c
@@ -0,0 +1,49 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: updt_tar.c                                               *

+*                                                                      *

+*       Description: Update the target vector for codebook search      *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+void Updt_tar(

+		Word16 * x,                           /* (i) Q0  : old target (for pitch search)     */

+		Word16 * x2,                          /* (o) Q0  : new target (for codebook search)  */

+		Word16 * y,                           /* (i) Q0  : filtered adaptive codebook vector */

+		Word16 gain,                          /* (i) Q14 : adaptive codebook gain            */

+		Word16 L                              /* (i)     : subframe size                     */

+	     )

+{

+	Word32 i;

+	Word32 L_tmp;

+

+	for (i = 0; i < L; i++)

+	{

+		L_tmp = x[i] << 15;

+		L_tmp -= (y[i] * gain)<<1;

+		x2[i] = extract_h(L_shl2(L_tmp, 1)); 

+	}

+

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/util.c b/media/libstagefright/codecs/amrwbenc/src/util.c
new file mode 100644
index 0000000..78141dd
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/util.c
@@ -0,0 +1,74 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: util.c                                                   *

+*                                                                      *

+*       Description: Reset and Copy buffer                             *

+*                                                                      *

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+/***********************************************************************

+* Function:  Set_zero()                                             *

+* Description: Set vector x[] to zero                               *

+************************************************************************/

+

+void Set_zero(

+		Word16 x[],                           /* (o)    : vector to clear     */

+		Word16 L                              /* (i)    : length of vector    */

+	     )

+{

+	Word32 num = (Word32)L;

+	do{

+		*x++ = 0;

+	}while(--num !=0);

+}

+

+

+/*********************************************************************

+* Function: Copy()                                                   *

+*                                                                    *

+* Description: Copy vector x[] to y[]                                *

+*********************************************************************/

+

+void Copy(

+		Word16 x[],                           /* (i)   : input vector   */

+		Word16 y[],                           /* (o)   : output vector  */

+		Word16 L                              /* (i)   : vector length  */

+	 )

+{

+	Word32	temp1,temp2,num;

+	if(L&1)

+	{

+		temp1 = *x++;

+		*y++ = temp1;

+	}

+	num = (Word32)(L>>1);

+	temp1 = *x++;

+	temp2 = *x++;

+	do{

+		*y++ = temp1;

+		*y++ = temp2;

+		temp1 = *x++;

+		temp2 = *x++;

+	}while(--num!=0);

+}

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c
new file mode 100644
index 0000000..d0d99a7
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c
@@ -0,0 +1,1941 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: voAMRWBEnc.c                                              *

+*                                                                      *

+*      Description: Performs the main encoder routine                  *

+*                   Fixed-point C simulation of AMR WB ACELP coding    *

+*		    algorithm with 20 msspeech frames for              *

+*		    wideband speech signals.                           *

+*                                                                      *

+************************************************************************/

+

+#include <stdio.h>

+#include <stdlib.h>

+#include "typedef.h"

+#include "basic_op.h"

+#include "oper_32b.h"

+#include "math_op.h"

+#include "cnst.h"

+#include "acelp.h"

+#include "cod_main.h"

+#include "bits.h"

+#include "main.h"

+#include "voAMRWB.h"

+#include "mem_align.h"

+#include "cmnMemory.h"

+

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */

+static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767};

+

+/* isp tables for initialization */

+static Word16 isp_init[M] =

+{

+	32138, 30274, 27246, 23170, 18205, 12540, 6393, 0,

+	-6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475

+};

+

+static Word16 isf_init[M] =

+{

+	1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192,

+	9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840

+};

+

+/* High Band encoding */

+static const Word16 HP_gain[16] =

+{

+	3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264,

+	11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728

+};

+

+/* Private function declaration */

+static Word16 synthesis(

+			Word16 Aq[],                          /* A(z)  : quantized Az               */

+			Word16 exc[],                         /* (i)   : excitation at 12kHz        */

+			Word16 Q_new,                         /* (i)   : scaling performed on exc   */

+			Word16 synth16k[],                    /* (o)   : 16kHz synthesis signal     */

+			Coder_State * st                      /* (i/o) : State structure            */

+			);

+

+/* Codec some parameters initialization */

+void Reset_encoder(void *st, Word16 reset_all)

+{

+	Word16 i;

+	Coder_State *cod_state;

+	cod_state = (Coder_State *) st;

+	Set_zero(cod_state->old_exc, PIT_MAX + L_INTERPOL);

+	Set_zero(cod_state->mem_syn, M);

+	Set_zero(cod_state->past_isfq, M);

+	cod_state->mem_w0 = 0;                 

+	cod_state->tilt_code = 0;              

+	cod_state->first_frame = 1;            

+	Init_gp_clip(cod_state->gp_clip);

+	cod_state->L_gc_thres = 0;             

+	if (reset_all != 0)

+	{

+		/* Static vectors to zero */

+		Set_zero(cod_state->old_speech, L_TOTAL - L_FRAME);

+		Set_zero(cod_state->old_wsp, (PIT_MAX / OPL_DECIM));

+		Set_zero(cod_state->mem_decim2, 3);

+		/* routines initialization */

+		Init_Decim_12k8(cod_state->mem_decim);

+		Init_HP50_12k8(cod_state->mem_sig_in);

+		Init_Levinson(cod_state->mem_levinson);

+		Init_Q_gain2(cod_state->qua_gain);

+		Init_Hp_wsp(cod_state->hp_wsp_mem);

+		/* isp initialization */

+		Copy(isp_init, cod_state->ispold, M);

+		Copy(isp_init, cod_state->ispold_q, M);

+		/* variable initialization */

+		cod_state->mem_preemph = 0;        

+		cod_state->mem_wsp = 0;            

+		cod_state->Q_old = 15;             

+		cod_state->Q_max[0] = 15;          

+		cod_state->Q_max[1] = 15;          

+		cod_state->old_wsp_max = 0;        

+		cod_state->old_wsp_shift = 0;      

+		/* pitch ol initialization */

+		cod_state->old_T0_med = 40;        

+		cod_state->ol_gain = 0;            

+		cod_state->ada_w = 0;              

+		cod_state->ol_wght_flg = 0;        

+		for (i = 0; i < 5; i++)

+		{

+			cod_state->old_ol_lag[i] = 40; 

+		}

+		Set_zero(cod_state->old_hp_wsp, (L_FRAME / 2) / OPL_DECIM + (PIT_MAX / OPL_DECIM));

+		Set_zero(cod_state->mem_syn_hf, M);

+		Set_zero(cod_state->mem_syn_hi, M);

+		Set_zero(cod_state->mem_syn_lo, M);

+		Init_HP50_12k8(cod_state->mem_sig_out);

+		Init_Filt_6k_7k(cod_state->mem_hf);

+		Init_HP400_12k8(cod_state->mem_hp400);

+		Copy(isf_init, cod_state->isfold, M);

+		cod_state->mem_deemph = 0;         

+		cod_state->seed2 = 21845;          

+		Init_Filt_6k_7k(cod_state->mem_hf2);

+		cod_state->gain_alpha = 32767;     

+		cod_state->vad_hist = 0;

+		wb_vad_reset(cod_state->vadSt);

+		dtx_enc_reset(cod_state->dtx_encSt, isf_init);

+	}

+	return;

+}

+

+/*-----------------------------------------------------------------*

+*   Funtion  coder                                                *

+*            ~~~~~                                                *

+*   ->Main coder routine.                                         *

+*                                                                 *

+*-----------------------------------------------------------------*/

+void coder(

+		Word16 * mode,                        /* input :  used mode                             */

+		Word16 speech16k[],                   /* input :  320 new speech samples (at 16 kHz)    */

+		Word16 prms[],                        /* output:  output parameters                     */

+		Word16 * ser_size,                    /* output:  bit rate of the used mode             */

+		void *spe_state,                      /* i/o   :  State structure                       */

+		Word16 allow_dtx                      /* input :  DTX ON/OFF                            */

+	  )

+{

+	/* Coder states */

+	Coder_State *st;

+	/* Speech vector */

+	Word16 old_speech[L_TOTAL];

+	Word16 *new_speech, *speech, *p_window;

+

+	/* Weighted speech vector */

+	Word16 old_wsp[L_FRAME + (PIT_MAX / OPL_DECIM)];

+	Word16 *wsp;

+

+	/* Excitation vector */

+	Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];

+	Word16 *exc;

+

+	/* LPC coefficients */

+	Word16 r_h[M + 1], r_l[M + 1];         /* Autocorrelations of windowed speech  */

+	Word16 rc[M];                          /* Reflection coefficients.             */

+	Word16 Ap[M + 1];                      /* A(z) with spectral expansion         */

+	Word16 ispnew[M];                      /* immittance spectral pairs at 4nd sfr */

+	Word16 ispnew_q[M];                    /* quantized ISPs at 4nd subframe       */

+	Word16 isf[M];                         /* ISF (frequency domain) at 4nd sfr    */

+	Word16 *p_A, *p_Aq;                    /* ptr to A(z) for the 4 subframes      */

+	Word16 A[NB_SUBFR * (M + 1)];          /* A(z) unquantized for the 4 subframes */

+	Word16 Aq[NB_SUBFR * (M + 1)];         /* A(z)   quantized for the 4 subframes */

+

+	/* Other vectors */

+	Word16 xn[L_SUBFR];                    /* Target vector for pitch search     */

+	Word16 xn2[L_SUBFR];                   /* Target vector for codebook search  */

+	Word16 dn[L_SUBFR];                    /* Correlation between xn2 and h1     */

+	Word16 cn[L_SUBFR];                    /* Target vector in residual domain   */

+	Word16 h1[L_SUBFR];                    /* Impulse response vector            */

+	Word16 h2[L_SUBFR];                    /* Impulse response vector            */

+	Word16 code[L_SUBFR];                  /* Fixed codebook excitation          */

+	Word16 y1[L_SUBFR];                    /* Filtered adaptive excitation       */

+	Word16 y2[L_SUBFR];                    /* Filtered adaptive excitation       */

+	Word16 error[M + L_SUBFR];             /* error of quantization              */

+	Word16 synth[L_SUBFR];                 /* 12.8kHz synthesis vector           */

+	Word16 exc2[L_FRAME];                  /* excitation vector                  */

+	Word16 buf[L_FRAME];                   /* VAD buffer                         */

+

+	/* Scalars */

+	Word32 i, j, i_subfr, select, pit_flag, clip_gain, vad_flag;

+	Word16 codec_mode;

+	Word16 T_op, T_op2, T0, T0_min, T0_max, T0_frac, index;

+	Word16 gain_pit, gain_code, g_coeff[4], g_coeff2[4];

+	Word16 tmp, gain1, gain2, exp, Q_new, mu, shift, max;

+	Word16 voice_fac;

+	Word16 indice[8];

+	Word32 L_tmp, L_gain_code, L_max, L_tmp1;

+	Word16 code2[L_SUBFR];                         /* Fixed codebook excitation  */

+	Word16 stab_fac, fac, gain_code_lo;

+

+	Word16 corr_gain;

+	Word16 *vo_p0, *vo_p1, *vo_p2, *vo_p3;

+

+	st = (Coder_State *) spe_state;

+

+	*ser_size = nb_of_bits[*mode];         

+	codec_mode = *mode;                    

+

+	/*--------------------------------------------------------------------------*

+	 *          Initialize pointers to speech vector.                           *

+	 *                                                                          *

+	 *                                                                          *

+	 *                    |-------|-------|-------|-------|-------|-------|     *

+	 *                     past sp   sf1     sf2     sf3     sf4    L_NEXT      *

+	 *                    <-------  Total speech buffer (L_TOTAL)   ------>     *

+	 *              old_speech                                                  *

+	 *                    <-------  LPC analysis window (L_WINDOW)  ------>     *

+	 *                    |       <-- present frame (L_FRAME) ---->             *

+	 *                   p_window |       <----- new speech (L_FRAME) ---->     *

+	 *                            |       |                                     *

+	 *                          speech    |                                     *

+	 *                                 new_speech                               *

+	 *--------------------------------------------------------------------------*/

+

+	new_speech = old_speech + L_TOTAL - L_FRAME - L_FILT;         /* New speech     */

+	speech = old_speech + L_TOTAL - L_FRAME - L_NEXT;             /* Present frame  */

+	p_window = old_speech + L_TOTAL - L_WINDOW; 

+

+	exc = old_exc + PIT_MAX + L_INTERPOL;  

+	wsp = old_wsp + (PIT_MAX / OPL_DECIM); 

+

+	/* copy coder memory state into working space */

+	Copy(st->old_speech, old_speech, L_TOTAL - L_FRAME);

+	Copy(st->old_wsp, old_wsp, PIT_MAX / OPL_DECIM);

+	Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL);

+

+	/*---------------------------------------------------------------*

+	 * Down sampling signal from 16kHz to 12.8kHz                    *

+	 * -> The signal is extended by L_FILT samples (padded to zero)  *

+	 * to avoid additional delay (L_FILT samples) in the coder.      *

+	 * The last L_FILT samples are approximated after decimation and *

+	 * are used (and windowed) only in autocorrelations.             *

+	 *---------------------------------------------------------------*/

+

+	Decim_12k8(speech16k, L_FRAME16k, new_speech, st->mem_decim);

+

+	/* last L_FILT samples for autocorrelation window */

+	Copy(st->mem_decim, code, 2 * L_FILT16k);

+	Set_zero(error, L_FILT16k);            /* set next sample to zero */

+	Decim_12k8(error, L_FILT16k, new_speech + L_FRAME, code);

+

+	/*---------------------------------------------------------------*

+	 * Perform 50Hz HP filtering of input signal.                    *

+	 *---------------------------------------------------------------*/

+

+	HP50_12k8(new_speech, L_FRAME, st->mem_sig_in);

+

+	/* last L_FILT samples for autocorrelation window */

+	Copy(st->mem_sig_in, code, 6);

+	HP50_12k8(new_speech + L_FRAME, L_FILT, code);

+

+	/*---------------------------------------------------------------*

+	 * Perform fixed preemphasis through 1 - g z^-1                  *

+	 * Scale signal to get maximum of precision in filtering         *

+	 *---------------------------------------------------------------*/

+

+	mu = PREEMPH_FAC >> 1;              /* Q15 --> Q14 */

+

+	/* get max of new preemphased samples (L_FRAME+L_FILT) */

+	L_tmp = new_speech[0] << 15;

+	L_tmp -= (st->mem_preemph * mu)<<1;

+	L_max = L_abs(L_tmp);

+

+	for (i = 1; i < L_FRAME + L_FILT; i++)

+	{

+		L_tmp = new_speech[i] << 15;

+		L_tmp -= (new_speech[i - 1] * mu)<<1;

+		L_tmp = L_abs(L_tmp);

+		if(L_tmp > L_max)

+		{

+			L_max = L_tmp;                 

+		}

+	}

+

+	/* get scaling factor for new and previous samples */

+	/* limit scaling to Q_MAX to keep dynamic for ringing in low signal */

+	/* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */

+	tmp = extract_h(L_max);

+	if (tmp == 0)

+	{

+		shift = Q_MAX;                     

+	} else

+	{

+		shift = norm_s(tmp) - 1;

+		if (shift < 0)

+		{

+			shift = 0;                     

+		}

+		if (shift > Q_MAX)

+		{

+			shift = Q_MAX;                 

+		}

+	}

+	Q_new = shift;                         

+	if (Q_new > st->Q_max[0])

+	{

+		Q_new = st->Q_max[0];              

+	}

+	if (Q_new > st->Q_max[1])

+	{

+		Q_new = st->Q_max[1];              

+	}

+	exp = (Q_new - st->Q_old);

+	st->Q_old = Q_new;                     

+	st->Q_max[1] = st->Q_max[0];           

+	st->Q_max[0] = shift;                  

+

+	/* preemphasis with scaling (L_FRAME+L_FILT) */

+	tmp = new_speech[L_FRAME - 1];         

+

+	for (i = L_FRAME + L_FILT - 1; i > 0; i--)

+	{

+		L_tmp = new_speech[i] << 15;

+		L_tmp -= (new_speech[i - 1] * mu)<<1;

+		L_tmp = (L_tmp << Q_new);

+		new_speech[i] = vo_round(L_tmp);      

+	}

+

+	L_tmp = new_speech[0] << 15;

+	L_tmp -= (st->mem_preemph * mu)<<1;

+	L_tmp = (L_tmp << Q_new);

+	new_speech[0] = vo_round(L_tmp);          

+

+	st->mem_preemph = tmp;                 

+

+	/* scale previous samples and memory */

+

+	Scale_sig(old_speech, L_TOTAL - L_FRAME - L_FILT, exp);

+	Scale_sig(old_exc, PIT_MAX + L_INTERPOL, exp);

+	Scale_sig(st->mem_syn, M, exp);

+	Scale_sig(st->mem_decim2, 3, exp);

+	Scale_sig(&(st->mem_wsp), 1, exp);

+	Scale_sig(&(st->mem_w0), 1, exp);

+

+	/*------------------------------------------------------------------------*

+	 *  Call VAD                                                              *

+	 *  Preemphesis scale down signal in low frequency and keep dynamic in HF.*

+	 *  Vad work slightly in futur (new_speech = speech + L_NEXT - L_FILT).   *

+	 *------------------------------------------------------------------------*/

+	Copy(new_speech, buf, L_FRAME);

+

+#ifdef ASM_OPT        /* asm optimization branch */

+	Scale_sig_opt(buf, L_FRAME, 1 - Q_new);

+#else

+	Scale_sig(buf, L_FRAME, 1 - Q_new);

+#endif

+

+	vad_flag = wb_vad(st->vadSt, buf);          /* Voice Activity Detection */ 

+	if (vad_flag == 0)

+	{

+		st->vad_hist = (st->vad_hist + 1);        

+	} else

+	{

+		st->vad_hist = 0;             

+	}

+

+	/* DTX processing */

+	if (allow_dtx != 0)

+	{

+		/* Note that mode may change here */

+		tx_dtx_handler(st->dtx_encSt, vad_flag, mode);

+		*ser_size = nb_of_bits[*mode]; 

+	}

+

+	if(*mode != MRDTX)

+	{

+		Parm_serial(vad_flag, 1, &prms);

+	}

+	/*------------------------------------------------------------------------*

+	 *  Perform LPC analysis                                                  *

+	 *  ~~~~~~~~~~~~~~~~~~~~                                                  *

+	 *   - autocorrelation + lag windowing                                    *

+	 *   - Levinson-durbin algorithm to find a[]                              *

+	 *   - convert a[] to isp[]                                               *

+	 *   - convert isp[] to isf[] for quantization                            *

+	 *   - quantize and code the isf[]                                        *

+	 *   - convert isf[] to isp[] for interpolation                           *

+	 *   - find the interpolated ISPs and convert to a[] for the 4 subframes  *

+	 *------------------------------------------------------------------------*/

+

+	/* LP analysis centered at 4nd subframe */

+	Autocorr(p_window, M, r_h, r_l);                        /* Autocorrelations */

+	Lag_window(r_h, r_l);                                   /* Lag windowing    */

+	Levinson(r_h, r_l, A, rc, st->mem_levinson);            /* Levinson Durbin  */

+	Az_isp(A, ispnew, st->ispold);                          /* From A(z) to ISP */

+

+	/* Find the interpolated ISPs and convert to a[] for all subframes */

+	Int_isp(st->ispold, ispnew, interpol_frac, A);

+

+	/* update ispold[] for the next frame */

+	Copy(ispnew, st->ispold, M);

+

+	/* Convert ISPs to frequency domain 0..6400 */

+	Isp_isf(ispnew, isf, M);

+

+	/* check resonance for pitch clipping algorithm */

+	Gp_clip_test_isf(isf, st->gp_clip);

+

+	/*----------------------------------------------------------------------*

+	 *  Perform PITCH_OL analysis                                           *

+	 *  ~~~~~~~~~~~~~~~~~~~~~~~~~                                           *

+	 * - Find the residual res[] for the whole speech frame                 *

+	 * - Find the weighted input speech wsp[] for the whole speech frame    *

+	 * - scale wsp[] to avoid overflow in pitch estimation                  *

+	 * - Find open loop pitch lag for whole speech frame                    *

+	 *----------------------------------------------------------------------*/

+	p_A = A;                             

+	for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)

+	{

+		/* Weighting of LPC coefficients */

+		Weight_a(p_A, Ap, GAMMA1, M);

+

+#ifdef ASM_OPT                    /* asm optimization branch */

+		Residu_opt(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);

+#else

+		Residu(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);

+#endif

+

+		p_A += (M + 1);                    

+	}

+

+	Deemph2(wsp, TILT_FAC, L_FRAME, &(st->mem_wsp));

+

+	/* find maximum value on wsp[] for 12 bits scaling */

+	max = 0;                              

+	for (i = 0; i < L_FRAME; i++)

+	{

+		tmp = abs_s(wsp[i]);

+		if(tmp > max)

+		{

+			max = tmp;                     

+		}

+	}

+	tmp = st->old_wsp_max;                 

+	if(max > tmp)

+	{

+		tmp = max;                         /* tmp = max(wsp_max, old_wsp_max) */

+	}

+	st->old_wsp_max = max;                

+

+	shift = norm_s(tmp) - 3;

+	if (shift > 0)

+	{

+		shift = 0;                         /* shift = 0..-3 */

+	}

+	/* decimation of wsp[] to search pitch in LF and to reduce complexity */

+	LP_Decim2(wsp, L_FRAME, st->mem_decim2);

+

+	/* scale wsp[] in 12 bits to avoid overflow */

+#ifdef  ASM_OPT                  /* asm optimization branch */

+	Scale_sig_opt(wsp, L_FRAME / OPL_DECIM, shift);

+#else

+	Scale_sig(wsp, L_FRAME / OPL_DECIM, shift);

+#endif

+	/* scale old_wsp (warning: exp must be Q_new-Q_old) */

+	exp = exp + (shift - st->old_wsp_shift);

+	st->old_wsp_shift = shift;

+

+	Scale_sig(old_wsp, PIT_MAX / OPL_DECIM, exp);

+	Scale_sig(st->old_hp_wsp, PIT_MAX / OPL_DECIM, exp);

+

+	scale_mem_Hp_wsp(st->hp_wsp_mem, exp);

+

+	/* Find open loop pitch lag for whole speech frame */

+

+	if(*ser_size == NBBITS_7k)

+	{

+		/* Find open loop pitch lag for whole speech frame */

+		T_op = Pitch_med_ol(wsp, st, L_FRAME / OPL_DECIM);

+	} else

+	{

+		/* Find open loop pitch lag for first 1/2 frame */

+		T_op = Pitch_med_ol(wsp, st, (L_FRAME/2) / OPL_DECIM);

+	}

+

+	if(st->ol_gain > 19661)       /* 0.6 in Q15 */

+	{

+		st->old_T0_med = Med_olag(T_op, st->old_ol_lag);       

+		st->ada_w = 32767;                 

+	} else

+	{

+		st->ada_w = vo_mult(st->ada_w, 29491);

+	}

+

+	if(st->ada_w < 26214)

+		st->ol_wght_flg = 0;

+	else

+		st->ol_wght_flg = 1;

+

+	wb_vad_tone_detection(st->vadSt, st->ol_gain);

+	T_op *= OPL_DECIM;                     

+

+	if(*ser_size != NBBITS_7k)

+	{

+		/* Find open loop pitch lag for second 1/2 frame */

+		T_op2 = Pitch_med_ol(wsp + ((L_FRAME / 2) / OPL_DECIM), st, (L_FRAME/2) / OPL_DECIM);

+

+		if(st->ol_gain > 19661)   /* 0.6 in Q15 */

+		{

+			st->old_T0_med = Med_olag(T_op2, st->old_ol_lag);  

+			st->ada_w = 32767;             

+		} else

+		{

+			st->ada_w = mult(st->ada_w, 29491); 

+		}

+

+		if(st->ada_w < 26214)

+			st->ol_wght_flg = 0;

+		else

+			st->ol_wght_flg = 1;

+

+		wb_vad_tone_detection(st->vadSt, st->ol_gain);

+

+		T_op2 *= OPL_DECIM;                

+

+	} else

+	{

+		T_op2 = T_op;                      

+	}

+	/*----------------------------------------------------------------------*

+	 *                              DTX-CNG                                 *

+	 *----------------------------------------------------------------------*/

+	if(*mode == MRDTX)            /* CNG mode */

+	{

+		/* Buffer isf's and energy */

+#ifdef ASM_OPT                   /* asm optimization branch */

+		Residu_opt(&A[3 * (M + 1)], speech, exc, L_FRAME);

+#else

+		Residu(&A[3 * (M + 1)], speech, exc, L_FRAME);

+#endif

+

+		for (i = 0; i < L_FRAME; i++)

+		{

+			exc2[i] = shr(exc[i], Q_new);  

+		}

+

+		L_tmp = 0;                         

+		for (i = 0; i < L_FRAME; i++)

+			L_tmp += (exc2[i] * exc2[i])<<1;

+

+		L_tmp >>= 1;

+

+		dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);

+

+		/* Quantize and code the ISFs */

+		dtx_enc(st->dtx_encSt, isf, exc2, &prms);

+

+		/* Convert ISFs to the cosine domain */

+		Isf_isp(isf, ispnew_q, M);

+		Isp_Az(ispnew_q, Aq, M, 0);

+

+		for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)

+		{

+			corr_gain = synthesis(Aq, &exc2[i_subfr], 0, &speech16k[i_subfr * 5 / 4], st);

+		}

+		Copy(isf, st->isfold, M);

+

+		/* reset speech coder memories */

+		Reset_encoder(st, 0);

+

+		/*--------------------------------------------------*

+		 * Update signal for next frame.                    *

+		 * -> save past of speech[] and wsp[].              *

+		 *--------------------------------------------------*/

+

+		Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);

+		Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);

+

+		return;

+	}

+	/*----------------------------------------------------------------------*

+	 *                               ACELP                                  *

+	 *----------------------------------------------------------------------*/

+

+	/* Quantize and code the ISFs */

+

+	if (*ser_size <= NBBITS_7k)

+	{

+		Qpisf_2s_36b(isf, isf, st->past_isfq, indice, 4);

+

+		Parm_serial(indice[0], 8, &prms);

+		Parm_serial(indice[1], 8, &prms);

+		Parm_serial(indice[2], 7, &prms);

+		Parm_serial(indice[3], 7, &prms);

+		Parm_serial(indice[4], 6, &prms);

+	} else

+	{

+		Qpisf_2s_46b(isf, isf, st->past_isfq, indice, 4);

+

+		Parm_serial(indice[0], 8, &prms);

+		Parm_serial(indice[1], 8, &prms);

+		Parm_serial(indice[2], 6, &prms);

+		Parm_serial(indice[3], 7, &prms);

+		Parm_serial(indice[4], 7, &prms);

+		Parm_serial(indice[5], 5, &prms);

+		Parm_serial(indice[6], 5, &prms);

+	}

+

+	/* Check stability on isf : distance between old isf and current isf */

+

+	L_tmp = 0;                           

+	for (i = 0; i < M - 1; i++)

+	{

+		tmp = vo_sub(isf[i], st->isfold[i]);

+		L_tmp += (tmp * tmp)<<1;

+	}

+

+	tmp = extract_h(L_shl2(L_tmp, 8)); 

+

+	tmp = vo_mult(tmp, 26214);                /* tmp = L_tmp*0.8/256 */

+	tmp = vo_sub(20480, tmp);                 /* 1.25 - tmp (in Q14) */

+

+	stab_fac = shl(tmp, 1); 

+

+	if (stab_fac < 0)

+	{

+		stab_fac = 0;                      

+	}

+	Copy(isf, st->isfold, M);

+

+	/* Convert ISFs to the cosine domain */

+	Isf_isp(isf, ispnew_q, M);

+

+	if (st->first_frame != 0)

+	{

+		st->first_frame = 0;              

+		Copy(ispnew_q, st->ispold_q, M);

+	}

+	/* Find the interpolated ISPs and convert to a[] for all subframes */

+

+	Int_isp(st->ispold_q, ispnew_q, interpol_frac, Aq);

+

+	/* update ispold[] for the next frame */

+	Copy(ispnew_q, st->ispold_q, M);

+

+	p_Aq = Aq;

+	for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)

+	{

+#ifdef ASM_OPT               /* asm optimization branch */

+		Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);

+#else

+		Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);

+#endif

+		p_Aq += (M + 1);                   

+	}

+

+	/* Buffer isf's and energy for dtx on non-speech frame */

+	if (vad_flag == 0)

+	{

+		for (i = 0; i < L_FRAME; i++)

+		{

+			exc2[i] = exc[i] >> Q_new;

+		}

+		L_tmp = 0;                         

+		for (i = 0; i < L_FRAME; i++)

+			L_tmp += (exc2[i] * exc2[i])<<1;

+		L_tmp >>= 1;

+

+		dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);

+	}

+	/* range for closed loop pitch search in 1st subframe */

+

+	T0_min = T_op - 8;

+	if (T0_min < PIT_MIN)

+	{

+		T0_min = PIT_MIN;                  

+	}

+	T0_max = (T0_min + 15);

+

+	if(T0_max > PIT_MAX)

+	{

+		T0_max = PIT_MAX;                  

+		T0_min = T0_max - 15;          

+	}

+	/*------------------------------------------------------------------------*

+	 *          Loop for every subframe in the analysis frame                 *

+	 *------------------------------------------------------------------------*

+	 *  To find the pitch and innovation parameters. The subframe size is     *

+	 *  L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times.               *

+	 *     - compute the target signal for pitch search                       *

+	 *     - compute impulse response of weighted synthesis filter (h1[])     *

+	 *     - find the closed-loop pitch parameters                            *

+	 *     - encode the pitch dealy                                           *

+	 *     - find 2 lt prediction (with / without LP filter for lt pred)      *

+	 *     - find 2 pitch gains and choose the best lt prediction.            *

+	 *     - find target vector for codebook search                           *

+	 *     - update the impulse response h1[] for codebook search             *

+	 *     - correlation between target vector and impulse response           *

+	 *     - codebook search and encoding                                     *

+	 *     - VQ of pitch and codebook gains                                   *

+	 *     - find voicing factor and tilt of code for next subframe.          *

+	 *     - update states of weighting filter                                *

+	 *     - find excitation and synthesis speech                             *

+	 *------------------------------------------------------------------------*/

+	p_A = A;                               

+	p_Aq = Aq;                             

+	for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)

+	{

+		pit_flag = i_subfr;                

+		if ((i_subfr == 2 * L_SUBFR) && (*ser_size > NBBITS_7k))

+		{

+			pit_flag = 0;                 

+			/* range for closed loop pitch search in 3rd subframe */

+			T0_min = (T_op2 - 8);

+

+			if (T0_min < PIT_MIN)

+			{

+				T0_min = PIT_MIN;          

+			}

+			T0_max = (T0_min + 15);

+			if (T0_max > PIT_MAX)

+			{

+				T0_max = PIT_MAX;         

+				T0_min = (T0_max - 15);

+			}

+		}

+		/*-----------------------------------------------------------------------*

+		 *                                                                       *

+		 *        Find the target vector for pitch search:                       *

+		 *        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                        *

+		 *                                                                       *

+		 *             |------|  res[n]                                          *

+		 * speech[n]---| A(z) |--------                                          *

+		 *             |------|       |   |--------| error[n]  |------|          *

+		 *                   zero -- (-)--| 1/A(z) |-----------| W(z) |-- target *

+		 *                   exc          |--------|           |------|          *

+		 *                                                                       *

+		 * Instead of subtracting the zero-input response of filters from        *

+		 * the weighted input speech, the above configuration is used to         *

+		 * compute the target vector.                                            *

+		 *                                                                       *

+		 *-----------------------------------------------------------------------*/

+

+		for (i = 0; i < M; i++)

+		{

+			error[i] = vo_sub(speech[i + i_subfr - M], st->mem_syn[i]);

+		}

+

+#ifdef ASM_OPT              /* asm optimization branch */

+		Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);

+#else

+		Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);

+#endif

+		Syn_filt(p_Aq, &exc[i_subfr], error + M, L_SUBFR, error, 0);

+		Weight_a(p_A, Ap, GAMMA1, M);

+

+#ifdef ASM_OPT             /* asm optimization branch */

+		Residu_opt(Ap, error + M, xn, L_SUBFR);

+#else

+		Residu(Ap, error + M, xn, L_SUBFR);

+#endif

+		Deemph2(xn, TILT_FAC, L_SUBFR, &(st->mem_w0));

+

+		/*----------------------------------------------------------------------*

+		 * Find approx. target in residual domain "cn[]" for inovation search.  *

+		 *----------------------------------------------------------------------*/

+		/* first half: xn[] --> cn[] */

+		Set_zero(code, M);

+		Copy(xn, code + M, L_SUBFR / 2);

+		tmp = 0;                          

+		Preemph2(code + M, TILT_FAC, L_SUBFR / 2, &tmp);

+		Weight_a(p_A, Ap, GAMMA1, M);

+		Syn_filt(Ap,code + M, code + M, L_SUBFR / 2, code, 0);

+

+#ifdef ASM_OPT                /* asm optimization branch */

+		Residu_opt(p_Aq,code + M, cn, L_SUBFR / 2);

+#else

+		Residu(p_Aq,code + M, cn, L_SUBFR / 2);

+#endif

+

+		/* second half: res[] --> cn[] (approximated and faster) */

+		Copy(&exc[i_subfr + (L_SUBFR / 2)], cn + (L_SUBFR / 2), L_SUBFR / 2);

+

+		/*---------------------------------------------------------------*

+		 * Compute impulse response, h1[], of weighted synthesis filter  * 

+		 *---------------------------------------------------------------*/

+

+		Set_zero(error, M + L_SUBFR);

+		Weight_a(p_A, error + M, GAMMA1, M);

+

+		vo_p0 = error+M;

+		vo_p3 = h1;

+		for (i = 0; i < L_SUBFR; i++)

+		{

+			L_tmp = *vo_p0 << 14;        /* x4 (Q12 to Q14) */

+			vo_p1 = p_Aq + 1;

+			vo_p2 = vo_p0-1;

+			for (j = 1; j <= M/4; j++)

+			{

+				L_tmp -= *vo_p1++ * *vo_p2--;

+				L_tmp -= *vo_p1++ * *vo_p2--;

+				L_tmp -= *vo_p1++ * *vo_p2--;

+				L_tmp -= *vo_p1++ * *vo_p2--;

+			}

+			*vo_p3++ = *vo_p0++ = vo_round((L_tmp <<4));

+		}

+		/* deemph without division by 2 -> Q14 to Q15 */

+		tmp = 0; 

+		Deemph2(h1, TILT_FAC, L_SUBFR, &tmp);   /* h1 in Q14 */

+

+		/* h2 in Q12 for codebook search */

+		Copy(h1, h2, L_SUBFR);

+

+		/*---------------------------------------------------------------*

+		 * scale xn[] and h1[] to avoid overflow in dot_product12()      *

+		 *---------------------------------------------------------------*/

+#ifdef  ASM_OPT                  /* asm optimization branch */

+		Scale_sig_opt(h2, L_SUBFR, -2);

+		Scale_sig_opt(xn, L_SUBFR, shift);     /* scaling of xn[] to limit dynamic at 12 bits */

+		Scale_sig_opt(h1, L_SUBFR, 1 + shift);  /* set h1[] in Q15 with scaling for convolution */

+#else

+		Scale_sig(h2, L_SUBFR, -2);

+		Scale_sig(xn, L_SUBFR, shift);     /* scaling of xn[] to limit dynamic at 12 bits */

+		Scale_sig(h1, L_SUBFR, 1 + shift);  /* set h1[] in Q15 with scaling for convolution */

+#endif

+		/*----------------------------------------------------------------------*

+		 *                 Closed-loop fractional pitch search                  *

+		 *----------------------------------------------------------------------*/

+		/* find closed loop fractional pitch  lag */

+		if(*ser_size <= NBBITS_9k)

+		{

+			T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,

+					pit_flag, PIT_MIN, PIT_FR1_8b, L_SUBFR);

+

+			/* encode pitch lag */

+			if (pit_flag == 0)             /* if 1st/3rd subframe */

+			{

+				/*--------------------------------------------------------------*

+				 * The pitch range for the 1st/3rd subframe is encoded with     *

+				 * 8 bits and is divided as follows:                            *

+				 *   PIT_MIN to PIT_FR1-1  resolution 1/2 (frac = 0 or 2)       *

+				 *   PIT_FR1 to PIT_MAX    resolution 1   (frac = 0)            *

+				 *--------------------------------------------------------------*/

+				if (T0 < PIT_FR1_8b)

+				{

+					index = ((T0 << 1) + (T0_frac >> 1) - (PIT_MIN<<1));

+				} else

+				{

+					index = ((T0 - PIT_FR1_8b) + ((PIT_FR1_8b - PIT_MIN)*2));

+				}

+

+				Parm_serial(index, 8, &prms);

+

+				/* find T0_min and T0_max for subframe 2 and 4 */

+				T0_min = (T0 - 8);

+				if (T0_min < PIT_MIN)

+				{

+					T0_min = PIT_MIN;

+				}

+				T0_max = T0_min + 15;

+				if (T0_max > PIT_MAX)

+				{

+					T0_max = PIT_MAX;

+					T0_min = (T0_max - 15);

+				}

+			} else

+			{                              /* if subframe 2 or 4 */

+				/*--------------------------------------------------------------*

+				 * The pitch range for subframe 2 or 4 is encoded with 5 bits:  *

+				 *   T0_min  to T0_max     resolution 1/2 (frac = 0 or 2)       *

+				 *--------------------------------------------------------------*/

+				i = (T0 - T0_min);

+				index = (i << 1) + (T0_frac >> 1);

+

+				Parm_serial(index, 5, &prms);

+			}

+		} else

+		{

+			T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,

+					pit_flag, PIT_FR2, PIT_FR1_9b, L_SUBFR);

+

+			/* encode pitch lag */

+			if (pit_flag == 0)             /* if 1st/3rd subframe */

+			{

+				/*--------------------------------------------------------------*

+				 * The pitch range for the 1st/3rd subframe is encoded with     *

+				 * 9 bits and is divided as follows:                            *

+				 *   PIT_MIN to PIT_FR2-1  resolution 1/4 (frac = 0,1,2 or 3)   *

+				 *   PIT_FR2 to PIT_FR1-1  resolution 1/2 (frac = 0 or 1)       *

+				 *   PIT_FR1 to PIT_MAX    resolution 1   (frac = 0)            *

+				 *--------------------------------------------------------------*/

+

+				if (T0 < PIT_FR2)

+				{

+					index = ((T0 << 2) + T0_frac) - (PIT_MIN << 2);

+				} else if(T0 < PIT_FR1_9b)

+				{

+					index = ((((T0 << 1) + (T0_frac >> 1)) - (PIT_FR2<<1)) + ((PIT_FR2 - PIT_MIN)<<2));

+				} else

+				{

+					index = (((T0 - PIT_FR1_9b) + ((PIT_FR2 - PIT_MIN)<<2)) + ((PIT_FR1_9b - PIT_FR2)<<1));

+				}

+

+				Parm_serial(index, 9, &prms);

+

+				/* find T0_min and T0_max for subframe 2 and 4 */

+

+				T0_min = (T0 - 8);

+				if (T0_min < PIT_MIN)

+				{

+					T0_min = PIT_MIN; 

+				}

+				T0_max = T0_min + 15;

+

+				if (T0_max > PIT_MAX)

+				{

+					T0_max = PIT_MAX;

+					T0_min = (T0_max - 15);

+				}

+			} else

+			{                              /* if subframe 2 or 4 */

+				/*--------------------------------------------------------------*

+				 * The pitch range for subframe 2 or 4 is encoded with 6 bits:  *

+				 *   T0_min  to T0_max     resolution 1/4 (frac = 0,1,2 or 3)   *

+				 *--------------------------------------------------------------*/

+				i = (T0 - T0_min);

+				index = (i << 2) + T0_frac;

+				Parm_serial(index, 6, &prms);

+			}

+		}

+

+		/*-----------------------------------------------------------------*

+		 * Gain clipping test to avoid unstable synthesis on frame erasure *

+		 *-----------------------------------------------------------------*/

+

+		clip_gain = 0;

+		if((st->gp_clip[0] < 154) && (st->gp_clip[1] > 14746))

+			clip_gain = 1;

+

+		/*-----------------------------------------------------------------*

+		 * - find unity gain pitch excitation (adaptive codebook entry)    *

+		 *   with fractional interpolation.                                *

+		 * - find filtered pitch exc. y1[]=exc[] convolved with h1[])      *

+		 * - compute pitch gain1                                           *

+		 *-----------------------------------------------------------------*/

+		/* find pitch exitation */

+#ifdef ASM_OPT                  /* asm optimization branch */

+		pred_lt4_asm(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);

+#else

+		Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);

+#endif

+		if (*ser_size > NBBITS_9k)

+		{

+#ifdef ASM_OPT                   /* asm optimization branch */

+			Convolve_asm(&exc[i_subfr], h1, y1, L_SUBFR);

+#else

+			Convolve(&exc[i_subfr], h1, y1, L_SUBFR);

+#endif 

+			gain1 = G_pitch(xn, y1, g_coeff, L_SUBFR);

+			/* clip gain if necessary to avoid problem at decoder */

+			if ((clip_gain != 0) && (gain1 > GP_CLIP))

+			{

+				gain1 = GP_CLIP; 

+			}

+			/* find energy of new target xn2[] */

+			Updt_tar(xn, dn, y1, gain1, L_SUBFR);       /* dn used temporary */

+		} else

+		{

+			gain1 = 0; 

+		}

+		/*-----------------------------------------------------------------*

+		 * - find pitch excitation filtered by 1st order LP filter.        *

+		 * - find filtered pitch exc. y2[]=exc[] convolved with h1[])      *

+		 * - compute pitch gain2                                           *

+		 *-----------------------------------------------------------------*/

+		/* find pitch excitation with lp filter */

+		vo_p0 = exc + i_subfr-1;

+		vo_p1 = code;

+		/* find pitch excitation with lp filter */

+		for (i = 0; i < L_SUBFR/2; i++)

+		{

+			L_tmp = 5898 * *vo_p0++;

+			L_tmp1 = 5898 * *vo_p0;

+			L_tmp += 20972 * *vo_p0++;

+			L_tmp1 += 20972 * *vo_p0++;

+			L_tmp1 += 5898 * *vo_p0--;

+			L_tmp += 5898 * *vo_p0;

+			*vo_p1++ = (L_tmp + 0x4000)>>15;

+			*vo_p1++ = (L_tmp1 + 0x4000)>>15;

+		}

+

+#ifdef ASM_OPT                 /* asm optimization branch */

+		Convolve_asm(code, h1, y2, L_SUBFR);

+#else

+		Convolve(code, h1, y2, L_SUBFR);

+#endif 

+

+		gain2 = G_pitch(xn, y2, g_coeff2, L_SUBFR);

+

+		/* clip gain if necessary to avoid problem at decoder */

+		if ((clip_gain != 0) && (gain2 > GP_CLIP))

+		{

+			gain2 = GP_CLIP;

+		}

+		/* find energy of new target xn2[] */

+		Updt_tar(xn, xn2, y2, gain2, L_SUBFR);

+		/*-----------------------------------------------------------------*

+		 * use the best prediction (minimise quadratic error).             *

+		 *-----------------------------------------------------------------*/

+		select = 0; 

+		if(*ser_size > NBBITS_9k)

+		{

+			L_tmp = 0L;

+			vo_p0 = dn;

+			vo_p1 = xn2;

+			for (i = 0; i < L_SUBFR/2; i++)

+			{

+				L_tmp += *vo_p0 * *vo_p0;

+				vo_p0++;

+				L_tmp -= *vo_p1 * *vo_p1;

+				vo_p1++;

+				L_tmp += *vo_p0 * *vo_p0;

+				vo_p0++;

+				L_tmp -= *vo_p1 * *vo_p1;

+				vo_p1++;

+			}

+

+			if (L_tmp <= 0)

+			{

+				select = 1; 

+			}

+			Parm_serial(select, 1, &prms);

+		}

+		if (select == 0)

+		{

+			/* use the lp filter for pitch excitation prediction */

+			gain_pit = gain2;

+			Copy(code, &exc[i_subfr], L_SUBFR);

+			Copy(y2, y1, L_SUBFR);

+			Copy(g_coeff2, g_coeff, 4);

+		} else

+		{

+			/* no filter used for pitch excitation prediction */

+			gain_pit = gain1;

+			Copy(dn, xn2, L_SUBFR);        /* target vector for codebook search */

+		}

+		/*-----------------------------------------------------------------*

+		 * - update cn[] for codebook search                               *

+		 *-----------------------------------------------------------------*/

+		Updt_tar(cn, cn, &exc[i_subfr], gain_pit, L_SUBFR);

+

+#ifdef  ASM_OPT                           /* asm optimization branch */

+		Scale_sig_opt(cn, L_SUBFR, shift);     /* scaling of cn[] to limit dynamic at 12 bits */

+#else

+		Scale_sig(cn, L_SUBFR, shift);     /* scaling of cn[] to limit dynamic at 12 bits */

+#endif

+		/*-----------------------------------------------------------------*

+		 * - include fixed-gain pitch contribution into impulse resp. h1[] *

+		 *-----------------------------------------------------------------*/

+		tmp = 0;

+		Preemph(h2, st->tilt_code, L_SUBFR, &tmp);

+

+		if (T0_frac > 2)

+			T0 = (T0 + 1);

+		Pit_shrp(h2, T0, PIT_SHARP, L_SUBFR);

+		/*-----------------------------------------------------------------*

+		 * - Correlation between target xn2[] and impulse response h1[]    *

+		 * - Innovative codebook search                                    *

+		 *-----------------------------------------------------------------*/

+		cor_h_x(h2, xn2, dn);

+		if (*ser_size <= NBBITS_7k)

+		{

+			ACELP_2t64_fx(dn, cn, h2, code, y2, indice);

+

+			Parm_serial(indice[0], 12, &prms);

+		} else if(*ser_size <= NBBITS_9k)

+		{

+			ACELP_4t64_fx(dn, cn, h2, code, y2, 20, *ser_size, indice);

+

+			Parm_serial(indice[0], 5, &prms);

+			Parm_serial(indice[1], 5, &prms);

+			Parm_serial(indice[2], 5, &prms);

+			Parm_serial(indice[3], 5, &prms);

+		} else if(*ser_size <= NBBITS_12k)

+		{

+			ACELP_4t64_fx(dn, cn, h2, code, y2, 36, *ser_size, indice);

+

+			Parm_serial(indice[0], 9, &prms);

+			Parm_serial(indice[1], 9, &prms);

+			Parm_serial(indice[2], 9, &prms);

+			Parm_serial(indice[3], 9, &prms);

+		} else if(*ser_size <= NBBITS_14k)

+		{

+			ACELP_4t64_fx(dn, cn, h2, code, y2, 44, *ser_size, indice);

+

+			Parm_serial(indice[0], 13, &prms);

+			Parm_serial(indice[1], 13, &prms);

+			Parm_serial(indice[2], 9, &prms);

+			Parm_serial(indice[3], 9, &prms);

+		} else if(*ser_size <= NBBITS_16k)

+		{

+			ACELP_4t64_fx(dn, cn, h2, code, y2, 52, *ser_size, indice);

+

+			Parm_serial(indice[0], 13, &prms);

+			Parm_serial(indice[1], 13, &prms);

+			Parm_serial(indice[2], 13, &prms);

+			Parm_serial(indice[3], 13, &prms);

+		} else if(*ser_size <= NBBITS_18k)

+		{

+			ACELP_4t64_fx(dn, cn, h2, code, y2, 64, *ser_size, indice);

+

+			Parm_serial(indice[0], 2, &prms);

+			Parm_serial(indice[1], 2, &prms);

+			Parm_serial(indice[2], 2, &prms);

+			Parm_serial(indice[3], 2, &prms);

+			Parm_serial(indice[4], 14, &prms);

+			Parm_serial(indice[5], 14, &prms);

+			Parm_serial(indice[6], 14, &prms);

+			Parm_serial(indice[7], 14, &prms);

+		} else if(*ser_size <= NBBITS_20k)

+		{

+			ACELP_4t64_fx(dn, cn, h2, code, y2, 72, *ser_size, indice);

+

+			Parm_serial(indice[0], 10, &prms);

+			Parm_serial(indice[1], 10, &prms);

+			Parm_serial(indice[2], 2, &prms);

+			Parm_serial(indice[3], 2, &prms);

+			Parm_serial(indice[4], 10, &prms);

+			Parm_serial(indice[5], 10, &prms);

+			Parm_serial(indice[6], 14, &prms);

+			Parm_serial(indice[7], 14, &prms);

+		} else

+		{

+			ACELP_4t64_fx(dn, cn, h2, code, y2, 88, *ser_size, indice);

+

+			Parm_serial(indice[0], 11, &prms);

+			Parm_serial(indice[1], 11, &prms);

+			Parm_serial(indice[2], 11, &prms);

+			Parm_serial(indice[3], 11, &prms);

+			Parm_serial(indice[4], 11, &prms);

+			Parm_serial(indice[5], 11, &prms);

+			Parm_serial(indice[6], 11, &prms);

+			Parm_serial(indice[7], 11, &prms);

+		}

+		/*-------------------------------------------------------*

+		 * - Add the fixed-gain pitch contribution to code[].    *

+		 *-------------------------------------------------------*/

+		tmp = 0; 

+		Preemph(code, st->tilt_code, L_SUBFR, &tmp);

+		Pit_shrp(code, T0, PIT_SHARP, L_SUBFR);

+		/*----------------------------------------------------------*

+		 *  - Compute the fixed codebook gain                       *

+		 *  - quantize fixed codebook gain                          *

+		 *----------------------------------------------------------*/

+		if(*ser_size <= NBBITS_9k)

+		{

+			index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 6,

+					&gain_pit, &L_gain_code, clip_gain, st->qua_gain);

+			Parm_serial(index, 6, &prms);

+		} else

+		{

+			index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 7,

+					&gain_pit, &L_gain_code, clip_gain, st->qua_gain);

+			Parm_serial(index, 7, &prms);

+		}

+		/* test quantized gain of pitch for pitch clipping algorithm */

+		Gp_clip_test_gain_pit(gain_pit, st->gp_clip);

+

+		L_tmp = L_shl(L_gain_code, Q_new); 

+		gain_code = extract_h(L_add(L_tmp, 0x8000));

+

+		/*----------------------------------------------------------*

+		 * Update parameters for the next subframe.                 *

+		 * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced)           *

+		 *----------------------------------------------------------*/

+		/* find voice factor in Q15 (1=voiced, -1=unvoiced) */

+		Copy(&exc[i_subfr], exc2, L_SUBFR);

+

+#ifdef ASM_OPT                           /* asm optimization branch */

+		Scale_sig_opt(exc2, L_SUBFR, shift);

+#else

+		Scale_sig(exc2, L_SUBFR, shift);

+#endif

+		voice_fac = voice_factor(exc2, shift, gain_pit, code, gain_code, L_SUBFR);

+		/* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */

+		st->tilt_code = ((voice_fac >> 2) + 8192);

+		/*------------------------------------------------------*

+		 * - Update filter's memory "mem_w0" for finding the    *

+		 *   target vector in the next subframe.                *

+		 * - Find the total excitation                          *

+		 * - Find synthesis speech to update mem_syn[].         *

+		 *------------------------------------------------------*/

+

+		/* y2 in Q9, gain_pit in Q14 */

+		L_tmp = (gain_code * y2[L_SUBFR - 1])<<1;

+		L_tmp = L_shl(L_tmp, (5 + shift));

+		L_tmp = L_negate(L_tmp);

+		L_tmp += (xn[L_SUBFR - 1] * 16384)<<1;

+		L_tmp -= (y1[L_SUBFR - 1] * gain_pit)<<1;

+		L_tmp = L_shl(L_tmp, (1 - shift));

+		st->mem_w0 = extract_h(L_add(L_tmp, 0x8000));

+

+		if (*ser_size >= NBBITS_24k)

+			Copy(&exc[i_subfr], exc2, L_SUBFR);

+

+		for (i = 0; i < L_SUBFR; i++)

+		{

+			/* code in Q9, gain_pit in Q14 */

+			L_tmp = (gain_code * code[i])<<1;

+			L_tmp = (L_tmp << 5);

+			L_tmp += (exc[i + i_subfr] * gain_pit)<<1;

+			L_tmp = L_shl2(L_tmp, 1); 

+			exc[i + i_subfr] = extract_h(L_add(L_tmp, 0x8000));

+		}

+

+		Syn_filt(p_Aq,&exc[i_subfr], synth, L_SUBFR, st->mem_syn, 1);

+

+		if(*ser_size >= NBBITS_24k)

+		{

+			/*------------------------------------------------------------*

+			 * phase dispersion to enhance noise in low bit rate          *

+			 *------------------------------------------------------------*/

+			/* L_gain_code in Q16 */

+			VO_L_Extract(L_gain_code, &gain_code, &gain_code_lo);

+

+			/*------------------------------------------------------------*

+			 * noise enhancer                                             *

+			 * ~~~~~~~~~~~~~~                                             *

+			 * - Enhance excitation on noise. (modify gain of code)       *

+			 *   If signal is noisy and LPC filter is stable, move gain   *

+			 *   of code 1.5 dB toward gain of code threshold.            *

+			 *   This decrease by 3 dB noise energy variation.            *

+			 *------------------------------------------------------------*/

+			tmp = (16384 - (voice_fac >> 1));        /* 1=unvoiced, 0=voiced */

+			fac = vo_mult(stab_fac, tmp);

+			L_tmp = L_gain_code; 

+			if(L_tmp < st->L_gc_thres)

+			{

+				L_tmp = vo_L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226));

+				if(L_tmp > st->L_gc_thres)

+				{

+					L_tmp = st->L_gc_thres;

+				}

+			} else

+			{

+				L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536);

+				if(L_tmp < st->L_gc_thres)

+				{

+					L_tmp = st->L_gc_thres;

+				}

+			}

+			st->L_gc_thres = L_tmp;

+

+			L_gain_code = Mpy_32_16(gain_code, gain_code_lo, (32767 - fac));

+			VO_L_Extract(L_tmp, &gain_code, &gain_code_lo);

+			L_gain_code = vo_L_add(L_gain_code, Mpy_32_16(gain_code, gain_code_lo, fac));

+

+			/*------------------------------------------------------------*

+			 * pitch enhancer                                             *

+			 * ~~~~~~~~~~~~~~                                             *

+			 * - Enhance excitation on voice. (HP filtering of code)      *

+			 *   On voiced signal, filtering of code by a smooth fir HP   *

+			 *   filter to decrease energy of code in low frequency.      *

+			 *------------------------------------------------------------*/

+

+			tmp = ((voice_fac >> 3) + 4096); /* 0.25=voiced, 0=unvoiced */

+

+			L_tmp = L_deposit_h(code[0]);

+			L_tmp -= (code[1] * tmp)<<1;

+			code2[0] = vo_round(L_tmp); 

+

+			for (i = 1; i < L_SUBFR - 1; i++)

+			{

+				L_tmp = L_deposit_h(code[i]);

+				L_tmp -= (code[i + 1] * tmp)<<1;

+				L_tmp -= (code[i - 1] * tmp)<<1;

+				code2[i] = vo_round(L_tmp); 

+			}

+

+			L_tmp = L_deposit_h(code[L_SUBFR - 1]);

+			L_tmp -= (code[L_SUBFR - 2] * tmp)<<1;

+			code2[L_SUBFR - 1] = vo_round(L_tmp); 

+

+			/* build excitation */

+			gain_code = vo_round(L_shl(L_gain_code, Q_new));

+

+			for (i = 0; i < L_SUBFR; i++)

+			{

+				L_tmp = (code2[i] * gain_code)<<1;

+				L_tmp = (L_tmp << 5);

+				L_tmp += (exc2[i] * gain_pit)<<1;

+				L_tmp = (L_tmp << 1);

+				exc2[i] = vo_round(L_tmp);

+			}

+

+			corr_gain = synthesis(p_Aq, exc2, Q_new, &speech16k[i_subfr * 5 / 4], st);

+			Parm_serial(corr_gain, 4, &prms);

+		}

+		p_A += (M + 1);

+		p_Aq += (M + 1);

+	}                                      /* end of subframe loop */

+

+	/*--------------------------------------------------*

+	 * Update signal for next frame.                    *

+	 * -> save past of speech[], wsp[] and exc[].       *

+	 *--------------------------------------------------*/

+	Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);

+	Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);

+	Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL);

+	return;

+}

+

+/*-----------------------------------------------------*

+* Function synthesis()                                *

+*                                                     *

+* Synthesis of signal at 16kHz with HF extension.     *

+*                                                     *

+*-----------------------------------------------------*/

+

+static Word16 synthesis(

+		Word16 Aq[],                          /* A(z)  : quantized Az               */

+		Word16 exc[],                         /* (i)   : excitation at 12kHz        */

+		Word16 Q_new,                         /* (i)   : scaling performed on exc   */

+		Word16 synth16k[],                    /* (o)   : 16kHz synthesis signal     */

+		Coder_State * st                      /* (i/o) : State structure            */

+		)

+{

+	Word16 fac, tmp, exp;

+	Word16 ener, exp_ener;

+	Word32 L_tmp, i;

+

+	Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR];

+	Word16 synth[L_SUBFR];

+	Word16 HF[L_SUBFR16k];                 /* High Frequency vector      */

+	Word16 Ap[M + 1];

+

+	Word16 HF_SP[L_SUBFR16k];              /* High Frequency vector (from original signal) */

+

+	Word16 HP_est_gain, HP_calc_gain, HP_corr_gain;

+	Word16 dist_min, dist;

+	Word16 HP_gain_ind = 0;

+	Word16 gain1, gain2;

+	Word16 weight1, weight2;

+

+	/*------------------------------------------------------------*

+	 * speech synthesis                                           *

+	 * ~~~~~~~~~~~~~~~~                                           *

+	 * - Find synthesis speech corresponding to exc2[].           *

+	 * - Perform fixed deemphasis and hp 50hz filtering.          *

+	 * - Oversampling from 12.8kHz to 16kHz.                      *

+	 *------------------------------------------------------------*/

+	Copy(st->mem_syn_hi, synth_hi, M);

+	Copy(st->mem_syn_lo, synth_lo, M);

+

+#ifdef ASM_OPT                 /* asm optimization branch */

+	Syn_filt_32_asm(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);

+#else

+	Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);

+#endif

+

+	Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M);

+	Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M);

+

+#ifdef ASM_OPT                 /* asm optimization branch */

+	Deemph_32_asm(synth_hi + M, synth_lo + M, synth, &(st->mem_deemph));

+#else

+	Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph));

+#endif

+

+	HP50_12k8(synth, L_SUBFR, st->mem_sig_out);

+

+	/* Original speech signal as reference for high band gain quantisation */

+	for (i = 0; i < L_SUBFR16k; i++)

+	{

+		HF_SP[i] = synth16k[i]; 

+	}

+

+	/*------------------------------------------------------*

+	 * HF noise synthesis                                   *

+	 * ~~~~~~~~~~~~~~~~~~                                   *

+	 * - Generate HF noise between 5.5 and 7.5 kHz.         *

+	 * - Set energy of noise according to synthesis tilt.   *

+	 *     tilt > 0.8 ==> - 14 dB (voiced)                  *

+	 *     tilt   0.5 ==> - 6 dB  (voiced or noise)         *

+	 *     tilt < 0.0 ==>   0 dB  (noise)                   *

+	 *------------------------------------------------------*/

+	/* generate white noise vector */

+	for (i = 0; i < L_SUBFR16k; i++)

+	{

+		HF[i] = Random(&(st->seed2))>>3;

+	}

+	/* energy of excitation */

+#ifdef ASM_OPT                    /* asm optimization branch */

+	Scale_sig_opt(exc, L_SUBFR, -3);

+	Q_new = Q_new - 3;

+	ener = extract_h(Dot_product12_asm(exc, exc, L_SUBFR, &exp_ener));

+#else

+	Scale_sig(exc, L_SUBFR, -3);

+	Q_new = Q_new - 3;

+	ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener));

+#endif

+

+	exp_ener = exp_ener - (Q_new + Q_new);

+	/* set energy of white noise to energy of excitation */

+#ifdef ASM_OPT              /* asm optimization branch */

+	tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp));

+#else

+	tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));

+#endif

+

+	if(tmp > ener)

+	{

+		tmp = (tmp >> 1);                 /* Be sure tmp < ener */

+		exp = (exp + 1);

+	}

+	L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */

+	exp = (exp - exp_ener);

+	Isqrt_n(&L_tmp, &exp);

+	L_tmp = L_shl(L_tmp, (exp + 1));       /* L_tmp x 2, L_tmp in Q31 */

+	tmp = extract_h(L_tmp);                /* tmp = 2 x sqrt(ener_exc/ener_hf) */

+

+	for (i = 0; i < L_SUBFR16k; i++)

+	{

+		HF[i] = vo_mult(HF[i], tmp);

+	}

+

+	/* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */

+	HP400_12k8(synth, L_SUBFR, st->mem_hp400);

+

+	L_tmp = 1L;

+	for (i = 0; i < L_SUBFR; i++)

+		L_tmp += (synth[i] * synth[i])<<1;

+

+	exp = norm_l(L_tmp);

+	ener = extract_h(L_tmp << exp);   /* ener = r[0] */

+

+	L_tmp = 1L;

+	for (i = 1; i < L_SUBFR; i++)

+		L_tmp +=(synth[i] * synth[i - 1])<<1;

+

+	tmp = extract_h(L_tmp << exp);    /* tmp = r[1] */

+

+	if (tmp > 0)

+	{

+		fac = div_s(tmp, ener);

+	} else

+	{

+		fac = 0; 

+	}

+

+	/* modify energy of white noise according to synthesis tilt */

+	gain1 = 32767 - fac;

+	gain2 = vo_mult(gain1, 20480);

+	gain2 = shl(gain2, 1);

+

+	if (st->vad_hist > 0)

+	{

+		weight1 = 0;

+		weight2 = 32767;

+	} else

+	{

+		weight1 = 32767;

+		weight2 = 0;

+	}

+	tmp = vo_mult(weight1, gain1);

+	tmp = add1(tmp, vo_mult(weight2, gain2));

+

+	if (tmp != 0)

+	{

+		tmp = (tmp + 1);

+	}

+	HP_est_gain = tmp;

+

+	if(HP_est_gain < 3277)

+	{

+		HP_est_gain = 3277;                /* 0.1 in Q15 */

+	}

+	/* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */

+	Weight_a(Aq, Ap, 19661, M);            /* fac=0.6 */

+

+#ifdef ASM_OPT                /* asm optimization branch */

+	Syn_filt_asm(Ap, HF, HF, st->mem_syn_hf);

+	/* noise High Pass filtering (1ms of delay) */

+	Filt_6k_7k_asm(HF, L_SUBFR16k, st->mem_hf);

+	/* filtering of the original signal */

+	Filt_6k_7k_asm(HF_SP, L_SUBFR16k, st->mem_hf2);

+

+	/* check the gain difference */

+	Scale_sig_opt(HF_SP, L_SUBFR16k, -1);

+	ener = extract_h(Dot_product12_asm(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));

+	/* set energy of white noise to energy of excitation */

+	tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp));

+#else

+	Syn_filt(Ap, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1);

+	/* noise High Pass filtering (1ms of delay) */

+	Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf);

+	/* filtering of the original signal */

+	Filt_6k_7k(HF_SP, L_SUBFR16k, st->mem_hf2);

+	/* check the gain difference */

+	Scale_sig(HF_SP, L_SUBFR16k, -1);

+	ener = extract_h(Dot_product12(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));

+	/* set energy of white noise to energy of excitation */

+	tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));

+#endif

+

+	if (tmp > ener)

+	{

+		tmp = (tmp >> 1);                 /* Be sure tmp < ener */

+		exp = (exp + 1);

+	}

+	L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */

+	exp = vo_sub(exp, exp_ener);

+	Isqrt_n(&L_tmp, &exp);

+	L_tmp = L_shl(L_tmp, exp);             /* L_tmp, L_tmp in Q31 */

+	HP_calc_gain = extract_h(L_tmp);       /* tmp = sqrt(ener_input/ener_hf) */

+

+	/* st->gain_alpha *= st->dtx_encSt->dtxHangoverCount/7 */

+	L_tmp = (vo_L_mult(st->dtx_encSt->dtxHangoverCount, 4681) << 15);

+	st->gain_alpha = vo_mult(st->gain_alpha, extract_h(L_tmp));

+

+	if(st->dtx_encSt->dtxHangoverCount > 6)

+		st->gain_alpha = 32767;

+	HP_est_gain = HP_est_gain >> 1;     /* From Q15 to Q14 */

+	HP_corr_gain = add1(vo_mult(HP_calc_gain, st->gain_alpha), vo_mult((32767 - st->gain_alpha), HP_est_gain));

+

+	/* Quantise the correction gain */

+	dist_min = 32767;

+	for (i = 0; i < 16; i++)

+	{

+		dist = vo_mult((HP_corr_gain - HP_gain[i]), (HP_corr_gain - HP_gain[i]));

+		if (dist_min > dist)

+		{

+			dist_min = dist;

+			HP_gain_ind = i;

+		}

+	}

+	HP_corr_gain = HP_gain[HP_gain_ind];

+	/* return the quantised gain index when using the highest mode, otherwise zero */

+	return (HP_gain_ind);

+}

+

+/*************************************************

+*

+* Breif: Codec main function 

+*

+**************************************************/

+

+int AMR_Enc_Encode(HAMRENC hCodec)

+{

+	Word32 i;

+	Coder_State *gData = (Coder_State*)hCodec;

+	Word16 *signal;

+	Word16 packed_size = 0;

+	Word16 prms[NB_BITS_MAX];

+	Word16 coding_mode = 0, nb_bits, allow_dtx, mode, reset_flag;

+	mode = gData->mode;

+	coding_mode = gData->mode;

+	nb_bits = nb_of_bits[mode];

+	signal = (Word16 *)gData->inputStream;

+	allow_dtx = gData->allow_dtx;

+

+	/* check for homing frame */

+	reset_flag = encoder_homing_frame_test(signal);

+

+	for (i = 0; i < L_FRAME16k; i++)   /* Delete the 2 LSBs (14-bit input) */

+	{

+		*(signal + i) = (Word16) (*(signal + i) & 0xfffC);

+	}

+

+	coder(&coding_mode, signal, prms, &nb_bits, gData, allow_dtx);

+	packed_size = PackBits(prms, coding_mode, mode, gData);

+	if (reset_flag != 0)

+	{

+		Reset_encoder(gData, 1);

+	}

+	return packed_size;

+}

+

+/***************************************************************************

+*

+*Brief: Codec API function --- Initialize the codec and return a codec handle

+*

+***************************************************************************/

+

+VO_U32 VO_API voAMRWB_Init(VO_HANDLE * phCodec,                   /* o: the audio codec handle */

+						   VO_AUDIO_CODINGTYPE vType,             /* i: Codec Type ID */

+						   VO_CODEC_INIT_USERDATA * pUserData     /* i: init Parameters */

+						   )

+{

+	Coder_State *st;

+	FrameStream *stream;

+#ifdef USE_DEAULT_MEM

+	VO_MEM_OPERATOR voMemoprator;

+#endif

+	VO_MEM_OPERATOR *pMemOP;

+	int interMem = 0;

+

+	if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )

+	{

+#ifdef USE_DEAULT_MEM

+		voMemoprator.Alloc = cmnMemAlloc;

+		voMemoprator.Copy = cmnMemCopy;

+		voMemoprator.Free = cmnMemFree;

+		voMemoprator.Set = cmnMemSet;

+		voMemoprator.Check = cmnMemCheck;

+		interMem = 1;

+		pMemOP = &voMemoprator;

+#else

+		*phCodec = NULL;

+		return VO_ERR_INVALID_ARG;

+#endif

+	}

+	else

+	{

+		pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;

+	} 

+	/*-------------------------------------------------------------------------*

+	 * Memory allocation for coder state.                                      *

+	 *-------------------------------------------------------------------------*/

+	if ((st = (Coder_State *)mem_malloc(pMemOP, sizeof(Coder_State), 32, VO_INDEX_ENC_AMRWB)) == NULL)

+	{

+		return VO_ERR_OUTOF_MEMORY;

+	}

+

+	st->vadSt = NULL;                      

+	st->dtx_encSt = NULL;                  

+	st->sid_update_counter = 3;

+	st->sid_handover_debt = 0;

+	st->prev_ft = TX_SPEECH;

+	st->inputStream = NULL;

+	st->inputSize = 0;

+

+	/* Default setting */

+	st->mode = VOAMRWB_MD2385;                        /* bit rate 23.85kbps */

+	st->frameType = VOAMRWB_RFC3267;                  /* frame type: RFC3267 */

+	st->allow_dtx = 0;                                /* disable DTX mode */

+

+	st->outputStream = NULL;

+	st->outputSize = 0;

+

+	st->stream = (FrameStream *)mem_malloc(pMemOP, sizeof(FrameStream), 32, VO_INDEX_ENC_AMRWB);

+	if(st->stream == NULL)

+		return VO_ERR_OUTOF_MEMORY;

+

+	st->stream->frame_ptr = (unsigned char *)mem_malloc(pMemOP, Frame_Maxsize, 32, VO_INDEX_ENC_AMRWB);

+	if(st->stream->frame_ptr == NULL)

+		return  VO_ERR_OUTOF_MEMORY;

+

+	stream = st->stream;

+	voAWB_InitFrameBuffer(stream);

+

+	wb_vad_init(&(st->vadSt), pMemOP);

+	dtx_enc_init(&(st->dtx_encSt), isf_init, pMemOP);

+

+	Reset_encoder((void *) st, 1);

+

+	if(interMem)

+	{

+		st->voMemoprator.Alloc = cmnMemAlloc;

+		st->voMemoprator.Copy = cmnMemCopy;

+		st->voMemoprator.Free = cmnMemFree;

+		st->voMemoprator.Set = cmnMemSet;

+		st->voMemoprator.Check = cmnMemCheck;

+		pMemOP = &st->voMemoprator;

+	}

+

+	st->pvoMemop = pMemOP;

+

+	*phCodec = (void *) st;

+

+	return VO_ERR_NONE;

+}

+

+/**********************************************************************************

+*

+* Brief: Codec API function: Input PCM data

+*

+***********************************************************************************/

+

+VO_U32 VO_API voAMRWB_SetInputData(

+		VO_HANDLE hCodec,                   /* i/o: The codec handle which was created by Init function */

+		VO_CODECBUFFER * pInput             /*   i: The input buffer parameter  */

+		)

+{

+	Coder_State  *gData;

+	FrameStream  *stream;

+

+	if(NULL == hCodec)

+	{

+		return VO_ERR_INVALID_ARG;

+	}

+

+	gData = (Coder_State *)hCodec;

+	stream = gData->stream;

+

+	if(NULL == pInput || NULL == pInput->Buffer || 0 > pInput->Length)

+	{

+		return VO_ERR_INVALID_ARG;

+	}

+

+	stream->set_ptr    = pInput->Buffer;

+	stream->set_len    = pInput->Length;

+	stream->frame_ptr  = stream->frame_ptr_bk;

+	stream->used_len   = 0;

+

+	return VO_ERR_NONE;

+}

+

+/**************************************************************************************

+*

+* Brief: Codec API function: Get the compression audio data frame by frame

+*

+***************************************************************************************/

+

+VO_U32 VO_API voAMRWB_GetOutputData(

+		VO_HANDLE hCodec,                    /* i: The Codec Handle which was created by Init function*/

+		VO_CODECBUFFER * pOutput,            /* o: The output audio data */

+		VO_AUDIO_OUTPUTINFO * pAudioFormat   /* o: The encoder module filled audio format and used the input size*/

+		)

+{

+	Coder_State* gData = (Coder_State*)hCodec;

+	VO_MEM_OPERATOR  *pMemOP;

+	FrameStream  *stream = (FrameStream *)gData->stream;

+	pMemOP = (VO_MEM_OPERATOR  *)gData->pvoMemop;

+

+	if(stream->framebuffer_len  < Frame_MaxByte)         /* check the work buffer len */

+	{

+		stream->frame_storelen = stream->framebuffer_len;

+		if(stream->frame_storelen)

+		{

+			pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk , stream->frame_ptr , stream->frame_storelen);

+		}

+		if(stream->set_len > 0)

+		{

+			voAWB_UpdateFrameBuffer(stream, pMemOP);

+		}

+		if(stream->framebuffer_len < Frame_MaxByte)

+		{

+			if(pAudioFormat)

+				pAudioFormat->InputUsed = stream->used_len;

+			return VO_ERR_INPUT_BUFFER_SMALL;

+		}

+	}

+

+	gData->inputStream = stream->frame_ptr;

+	gData->outputStream = (unsigned short*)pOutput->Buffer;

+

+	gData->outputSize = AMR_Enc_Encode(gData);         /* encoder main function */

+

+	pOutput->Length = gData->outputSize;               /* get the output buffer length */

+	stream->frame_ptr += 640;                          /* update the work buffer ptr */

+	stream->framebuffer_len  -= 640;

+

+	if(pAudioFormat)                                   /* return output audio information */

+	{

+		pAudioFormat->Format.Channels = 1;

+		pAudioFormat->Format.SampleRate = 8000;

+		pAudioFormat->Format.SampleBits = 16;	

+		pAudioFormat->InputUsed = stream->used_len;

+	}

+	return VO_ERR_NONE;

+}

+

+/*************************************************************************

+*

+* Brief: Codec API function---set the data by specified parameter ID

+*

+*************************************************************************/

+

+

+VO_U32 VO_API voAMRWB_SetParam(

+		VO_HANDLE hCodec,   /* i/o: The Codec Handle which was created by Init function */

+		VO_S32 uParamID,    /*   i: The param ID */

+		VO_PTR pData        /*   i: The param value depend on the ID */

+		)

+{

+	Coder_State* gData = (Coder_State*)hCodec;

+	FrameStream *stream = (FrameStream *)(gData->stream);

+	int *lValue = (int*)pData;

+

+	switch(uParamID)

+	{

+		/* setting AMR-WB frame type*/

+		case VO_PID_AMRWB_FRAMETYPE:

+			if(*lValue < VOAMRWB_DEFAULT || *lValue > VOAMRWB_RFC3267)

+				return VO_ERR_WRONG_PARAM_ID; 

+			gData->frameType = *lValue;

+			break;

+		/* setting AMR-WB bit rate */

+		case VO_PID_AMRWB_MODE:

+			{

+				if(*lValue < VOAMRWB_MD66 || *lValue > VOAMRWB_MD2385)

+					return VO_ERR_WRONG_PARAM_ID; 

+				gData->mode = *lValue;

+			}

+			break;

+		/* enable or disable DTX mode */

+		case VO_PID_AMRWB_DTX:

+			gData->allow_dtx = (Word16)(*lValue);

+			break;

+

+		case VO_PID_COMMON_HEADDATA:

+			break;

+        /* flush the work buffer */

+		case VO_PID_COMMON_FLUSH:

+			stream->set_ptr = NULL;

+			stream->frame_storelen = 0;

+			stream->framebuffer_len = 0;

+			stream->set_len = 0;

+			break;

+

+		default:

+			return VO_ERR_WRONG_PARAM_ID;

+	}

+	return VO_ERR_NONE;

+}

+

+/**************************************************************************

+*

+*Brief: Codec API function---Get the data by specified parameter ID

+*

+***************************************************************************/

+

+VO_U32 VO_API voAMRWB_GetParam(

+		VO_HANDLE hCodec,      /* i: The Codec Handle which was created by Init function */

+		VO_S32 uParamID,       /* i: The param ID */

+		VO_PTR pData           /* o: The param value depend on the ID */

+		)

+{

+	int    temp;

+	Coder_State* gData = (Coder_State*)hCodec;

+

+	if (gData==NULL) 

+		return VO_ERR_INVALID_ARG;

+	switch(uParamID)

+	{

+		/* output audio format */

+		case VO_PID_AMRWB_FORMAT:

+			{

+				VO_AUDIO_FORMAT* fmt = (VO_AUDIO_FORMAT*)pData;

+				fmt->Channels   = 1;

+				fmt->SampleRate = 16000;

+				fmt->SampleBits = 16;

+				break;

+			}

+        /* output audio channel number */

+		case VO_PID_AMRWB_CHANNELS:

+			temp = 1;

+			pData = (void *)(&temp);

+			break;

+        /* output audio sample rate */

+		case VO_PID_AMRWB_SAMPLERATE:

+			temp = 16000;

+			pData = (void *)(&temp);

+			break;

+		/* output audio frame type */

+		case VO_PID_AMRWB_FRAMETYPE:

+			temp = gData->frameType;

+			pData = (void *)(&temp);

+			break;

+		/* output audio bit rate */

+		case VO_PID_AMRWB_MODE:

+			temp = gData->mode;

+			pData = (void *)(&temp);

+			break;

+		default:

+			return VO_ERR_WRONG_PARAM_ID;

+	}

+

+	return VO_ERR_NONE;

+}

+

+/***********************************************************************************

+*

+* Brief: Codec API function---Release the codec after all encoder operations are done

+*

+*************************************************************************************/

+

+VO_U32 VO_API voAMRWB_Uninit(VO_HANDLE hCodec           /* i/o: Codec handle pointer */

+							 )

+{

+	Coder_State* gData = (Coder_State*)hCodec;

+	VO_MEM_OPERATOR *pMemOP;

+	pMemOP = gData->pvoMemop;

+

+	if(hCodec)

+	{

+		if(gData->stream)

+		{

+			if(gData->stream->frame_ptr_bk)

+			{

+				mem_free(pMemOP, gData->stream->frame_ptr_bk, VO_INDEX_ENC_AMRWB);

+				gData->stream->frame_ptr_bk = NULL;

+			}

+			mem_free(pMemOP, gData->stream, VO_INDEX_ENC_AMRWB);

+			gData->stream = NULL;

+		}

+		wb_vad_exit(&(((Coder_State *) gData)->vadSt), pMemOP);

+		dtx_enc_exit(&(((Coder_State *) gData)->dtx_encSt), pMemOP);

+

+		mem_free(pMemOP, hCodec, VO_INDEX_ENC_AMRWB);

+		hCodec = NULL;

+	}

+

+	return VO_ERR_NONE;

+}

+

+/********************************************************************************

+*

+* Brief: voGetAMRWBEncAPI gets the API handle of the codec

+*

+********************************************************************************/

+

+VO_S32 VO_API voGetAMRWBEncAPI(

+							   VO_AUDIO_CODECAPI * pEncHandle      /* i/o: Codec handle pointer */

+							   )

+{

+	if(NULL == pEncHandle)

+		return VO_ERR_INVALID_ARG;

+	pEncHandle->Init = voAMRWB_Init;

+	pEncHandle->SetInputData = voAMRWB_SetInputData;

+	pEncHandle->GetOutputData = voAMRWB_GetOutputData;

+	pEncHandle->SetParam = voAMRWB_SetParam;

+	pEncHandle->GetParam = voAMRWB_GetParam;

+	pEncHandle->Uninit = voAMRWB_Uninit;

+

+	return VO_ERR_NONE;

+}

+

+#ifdef __cplusplus

+}

+#endif

diff --git a/media/libstagefright/codecs/amrwbenc/src/voicefac.c b/media/libstagefright/codecs/amrwbenc/src/voicefac.c
new file mode 100644
index 0000000..187d774
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/voicefac.c
@@ -0,0 +1,92 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*   File: voicefac.c                                                   *

+*                                                                      *

+*   Description: Find the voicing factors (1 = voice to -1 = unvoiced) *

+*                                                                      *                                                 

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+

+Word16 voice_factor(                                  /* (o) Q15   : factor (-1=unvoiced to 1=voiced) */

+		Word16 exc[],                         /* (i) Q_exc : pitch excitation                 */

+		Word16 Q_exc,                         /* (i)       : exc format                       */

+		Word16 gain_pit,                      /* (i) Q14   : gain of pitch                    */

+		Word16 code[],                        /* (i) Q9    : Fixed codebook excitation        */

+		Word16 gain_code,                     /* (i) Q0    : gain of code                     */

+		Word16 L_subfr                        /* (i)       : subframe length                  */

+		)

+{

+	Word16 tmp, exp, ener1, exp1, ener2, exp2;

+	Word32 i, L_tmp;

+

+#ifdef ASM_OPT               /* asm optimization branch */

+	ener1 = extract_h(Dot_product12_asm(exc, exc, L_subfr, &exp1));

+#else

+	ener1 = extract_h(Dot_product12(exc, exc, L_subfr, &exp1));

+#endif

+	exp1 = exp1 - (Q_exc + Q_exc);

+	L_tmp = vo_L_mult(gain_pit, gain_pit);

+	exp = norm_l(L_tmp);

+	tmp = extract_h(L_tmp << exp);

+	ener1 = vo_mult(ener1, tmp);

+	exp1 = exp1 - exp - 10;        /* 10 -> gain_pit Q14 to Q9 */

+

+#ifdef ASM_OPT                /* asm optimization branch */

+	ener2 = extract_h(Dot_product12_asm(code, code, L_subfr, &exp2));

+#else

+	ener2 = extract_h(Dot_product12(code, code, L_subfr, &exp2));

+#endif

+

+	exp = norm_s(gain_code);

+	tmp = gain_code << exp;

+	tmp = vo_mult(tmp, tmp);

+	ener2 = vo_mult(ener2, tmp);

+	exp2 = exp2 - (exp + exp);

+

+	i = exp1 - exp2;

+

+	if (i >= 0)

+	{

+		ener1 = ener1 >> 1;

+		ener2 = ener2 >> (i + 1);

+	} else

+	{

+		ener1 = ener1 >> (1 - i);

+		ener2 = ener2 >> 1;

+	}

+

+	tmp = vo_sub(ener1, ener2);

+	ener1 = add1(add1(ener1, ener2), 1);

+

+	if (tmp >= 0)

+	{

+		tmp = div_s(tmp, ener1);

+	} else

+	{

+		tmp = vo_negate(div_s(vo_negate(tmp), ener1));

+	}

+

+	return (tmp);

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/wb_vad.c b/media/libstagefright/codecs/amrwbenc/src/wb_vad.c
new file mode 100644
index 0000000..0126853
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/wb_vad.c
@@ -0,0 +1,808 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*      File: wb_vad.c                                                  *

+*                                                                      *

+*      Description: Voice Activity Detection                           *

+*                                                                      *

+************************************************************************/

+

+#include <stdlib.h>

+#include <stdio.h>

+#include "cnst.h"

+#include "wb_vad.h"

+#include "typedef.h"

+#include "basic_op.h"

+#include "math_op.h"

+#include "wb_vad_c.h"

+#include "mem_align.h"

+

+/******************************************************************************

+*  Calculate Log2 and scale the signal:

+*

+*    ilog2(Word32 in) = -1024*log10(in * 2^-31)/log10(2), where in = [1, 2^31-1]

+*

+*  input   output

+*  32768   16384

+*  1       31744

+*

+* When input is in the range of [1,2^16], max error is 0.0380%.

+*********************************************************************************/

+

+static Word16 ilog2(                       /* return: output value of the log2 */

+		Word16 mant                        /* i: value to be converted */

+		)

+{

+	Word16 ex, ex2, res;

+	Word32 i, l_temp;

+

+	if (mant <= 0)

+	{

+		mant = 1;                         

+	}

+	ex = norm_s(mant);

+	mant = mant << ex;

+

+	for (i = 0; i < 3; i++)

+		mant = vo_mult(mant, mant);

+	l_temp = vo_L_mult(mant, mant);

+

+	ex2 = norm_l(l_temp);

+	mant = extract_h(l_temp << ex2);

+

+	res = (ex + 16) << 10;

+	res = add1(res, (ex2 << 6));

+	res = vo_sub(add1(res, 127), (mant >> 8));

+	return (res);

+}

+

+/******************************************************************************

+*

+*     Function     : filter5

+*     Purpose      : Fifth-order half-band lowpass/highpass filter pair with

+*                    decimation.

+*

+*******************************************************************************/

+

+static void filter5(

+		Word16 * in0,                         /* i/o : input values; output low-pass part  */

+		Word16 * in1,                         /* i/o : input values; output high-pass part */

+		Word16 data[]                         /* i/o : filter memory                       */

+		)

+{

+	Word16 temp0, temp1, temp2;

+

+	temp0 = vo_sub(*in0, vo_mult(COEFF5_1, data[0]));

+	temp1 = add1(data[0], vo_mult(COEFF5_1, temp0));

+	data[0] = temp0;                      

+

+	temp0 = vo_sub(*in1, vo_mult(COEFF5_2, data[1]));

+	temp2 = add1(data[1], vo_mult(COEFF5_2, temp0));

+	data[1] = temp0;                       

+

+	*in0 = extract_h((vo_L_add(temp1, temp2) << 15));   

+	*in1 = extract_h((vo_L_sub(temp1, temp2) << 15));  

+}

+

+/******************************************************************************

+*

+*     Function     : filter3

+*     Purpose      : Third-order half-band lowpass/highpass filter pair with

+*                    decimation.

+*

+*******************************************************************************/

+

+static void filter3(

+		Word16 * in0,                         /* i/o : input values; output low-pass part  */

+		Word16 * in1,                         /* i/o : input values; output high-pass part */

+		Word16 * data                         /* i/o : filter memory                       */

+		)

+{

+	Word16 temp1, temp2;

+

+	temp1 = vo_sub(*in1, vo_mult(COEFF3, *data));

+	temp2 = add1(*data, vo_mult(COEFF3, temp1));

+	*data = temp1;                        

+

+	*in1 = extract_h((vo_L_sub(*in0, temp2) << 15));   

+	*in0 = extract_h((vo_L_add(*in0, temp2) << 15));   

+}

+

+/******************************************************************************

+*

+*     Function   : level_calculation

+*     Purpose    : Calculate signal level in a sub-band. Level is calculated

+*                  by summing absolute values of the input data.

+*

+*                  Signal level calculated from of the end of the frame

+*                  (data[count1 - count2]) is stored to (*sub_level)

+*                  and added to the level of the next frame.

+*

+******************************************************************************/

+

+static Word16 level_calculation(                      /* return: signal level */

+		Word16 data[],                        /* i   : signal buffer                                    */

+		Word16 * sub_level,                   /* i   : level calculated at the end of the previous frame*/

+		                                      /* o   : level of signal calculated from the last         */

+		                                      /*       (count2 - count1) samples                        */

+		Word16 count1,                        /* i   : number of samples to be counted                  */

+		Word16 count2,                        /* i   : number of samples to be counted                  */

+		Word16 ind_m,                         /* i   : step size for the index of the data buffer       */

+		Word16 ind_a,                         /* i   : starting index of the data buffer                */

+		Word16 scale                          /* i   : scaling for the level calculation                */

+		)

+{

+	Word32 i, l_temp1, l_temp2;

+	Word16 level;

+

+	l_temp1 = 0L;                          

+	for (i = count1; i < count2; i++)

+	{

+		l_temp1 += (abs_s(data[ind_m * i + ind_a])<<1);

+	}

+

+	l_temp2 = vo_L_add(l_temp1, L_shl(*sub_level, 16 - scale));

+	*sub_level = extract_h(L_shl(l_temp1, scale));      

+

+	for (i = 0; i < count1; i++)

+	{

+		l_temp2 += (abs_s(data[ind_m * i + ind_a])<<1);

+	}

+	level = extract_h(L_shl2(l_temp2, scale));

+

+	return level;

+}

+

+/******************************************************************************

+*

+*     Function     : filter_bank

+*     Purpose      : Divide input signal into bands and calculate level of

+*                    the signal in each band

+*

+*******************************************************************************/

+

+static void filter_bank(

+		VadVars * st,                         /* i/o : State struct               */

+		Word16 in[],                          /* i   : input frame                */

+		Word16 level[]                        /* o   : signal levels at each band */

+		)

+{

+	Word32 i;

+	Word16 tmp_buf[FRAME_LEN];

+

+	/* shift input 1 bit down for safe scaling */

+	for (i = 0; i < FRAME_LEN; i++)

+	{

+		tmp_buf[i] = in[i] >> 1;       

+	}

+

+	/* run the filter bank */

+	for (i = 0; i < 128; i++)

+	{

+		filter5(&tmp_buf[2 * i], &tmp_buf[2 * i + 1], st->a_data5[0]);

+	}

+	for (i = 0; i < 64; i++)

+	{

+		filter5(&tmp_buf[4 * i], &tmp_buf[4 * i + 2], st->a_data5[1]);

+		filter5(&tmp_buf[4 * i + 1], &tmp_buf[4 * i + 3], st->a_data5[2]);

+	}

+	for (i = 0; i < 32; i++)

+	{

+		filter5(&tmp_buf[8 * i], &tmp_buf[8 * i + 4], st->a_data5[3]);

+		filter5(&tmp_buf[8 * i + 2], &tmp_buf[8 * i + 6], st->a_data5[4]);

+		filter3(&tmp_buf[8 * i + 3], &tmp_buf[8 * i + 7], &st->a_data3[0]);

+	}

+	for (i = 0; i < 16; i++)

+	{

+		filter3(&tmp_buf[16 * i + 0], &tmp_buf[16 * i + 8], &st->a_data3[1]);

+		filter3(&tmp_buf[16 * i + 4], &tmp_buf[16 * i + 12], &st->a_data3[2]);

+		filter3(&tmp_buf[16 * i + 6], &tmp_buf[16 * i + 14], &st->a_data3[3]);

+	}

+

+	for (i = 0; i < 8; i++)

+	{

+		filter3(&tmp_buf[32 * i + 0], &tmp_buf[32 * i + 16], &st->a_data3[4]);

+		filter3(&tmp_buf[32 * i + 8], &tmp_buf[32 * i + 24], &st->a_data3[5]);

+	}

+

+	/* calculate levels in each frequency band */

+

+	/* 4800 - 6400 Hz */

+	level[11] = level_calculation(tmp_buf, &st->sub_level[11], 16, 64, 4, 1, 14);   

+	/* 4000 - 4800 Hz */

+	level[10] = level_calculation(tmp_buf, &st->sub_level[10], 8, 32, 8, 7, 15);   

+	/* 3200 - 4000 Hz */

+	level[9] = level_calculation(tmp_buf, &st->sub_level[9],8, 32, 8, 3, 15);   

+	/* 2400 - 3200 Hz */

+	level[8] = level_calculation(tmp_buf, &st->sub_level[8],8, 32, 8, 2, 15);   

+	/* 2000 - 2400 Hz */

+	level[7] = level_calculation(tmp_buf, &st->sub_level[7],4, 16, 16, 14, 16);       

+	/* 1600 - 2000 Hz */

+	level[6] = level_calculation(tmp_buf, &st->sub_level[6],4, 16, 16, 6, 16);        

+	/* 1200 - 1600 Hz */

+	level[5] = level_calculation(tmp_buf, &st->sub_level[5],4, 16, 16, 4, 16);        

+	/* 800 - 1200 Hz */

+	level[4] = level_calculation(tmp_buf, &st->sub_level[4],4, 16, 16, 12, 16);       

+	/* 600 - 800 Hz */

+	level[3] = level_calculation(tmp_buf, &st->sub_level[3],2, 8, 32, 8, 17); 

+	/* 400 - 600 Hz */

+	level[2] = level_calculation(tmp_buf, &st->sub_level[2],2, 8, 32, 24, 17);        

+	/* 200 - 400 Hz */

+	level[1] = level_calculation(tmp_buf, &st->sub_level[1],2, 8, 32, 16, 17);        

+	/* 0 - 200 Hz */

+	level[0] = level_calculation(tmp_buf, &st->sub_level[0],2, 8, 32, 0, 17); 

+}

+

+/******************************************************************************

+*

+*     Function   : update_cntrl

+*     Purpose    : Control update of the background noise estimate.

+*

+*******************************************************************************/

+

+static void update_cntrl(

+		VadVars * st,                         /* i/o : State structure                    */

+		Word16 level[]                        /* i   : sub-band levels of the input frame */

+		)

+{

+	Word32 i;

+	Word16 num, temp, stat_rat, exp, denom;

+	Word16 alpha;

+

+	/* if a tone has been detected for a while, initialize stat_count */

+	if (sub((Word16) (st->tone_flag & 0x7c00), 0x7c00) == 0)

+	{

+		st->stat_count = STAT_COUNT;      

+	} else

+	{

+		/* if 8 last vad-decisions have been "0", reinitialize stat_count */

+		if ((st->vadreg & 0x7f80) == 0)

+		{

+			st->stat_count = STAT_COUNT;   

+		} else

+		{

+			stat_rat = 0;                  

+			for (i = 0; i < COMPLEN; i++)

+			{

+				if(level[i] > st->ave_level[i])

+				{

+					num = level[i];        

+					denom = st->ave_level[i];   

+				} else

+				{

+					num = st->ave_level[i];

+					denom = level[i];      

+				}

+				/* Limit nimimum value of num and denom to STAT_THR_LEVEL */

+				if(num < STAT_THR_LEVEL)

+				{

+					num = STAT_THR_LEVEL;  

+				}

+				if(denom < STAT_THR_LEVEL)

+				{

+					denom = STAT_THR_LEVEL;

+				}

+				exp = norm_s(denom);

+				denom = denom << exp;

+

+				/* stat_rat = num/denom * 64 */

+				temp = div_s(num >> 1, denom);

+				stat_rat = add1(stat_rat, shr(temp, (8 - exp)));

+			}

+

+			/* compare stat_rat with a threshold and update stat_count */

+			if(stat_rat > STAT_THR)

+			{

+				st->stat_count = STAT_COUNT;    

+			} else

+			{

+				if ((st->vadreg & 0x4000) != 0)

+				{

+

+					if (st->stat_count != 0)

+					{

+						st->stat_count = st->stat_count - 1;       

+					}

+				}

+			}

+		}

+	}

+

+	/* Update average amplitude estimate for stationarity estimation */

+	alpha = ALPHA4;                        

+	if(st->stat_count == STAT_COUNT)

+	{

+		alpha = 32767;                    

+	} else if ((st->vadreg & 0x4000) == 0)

+	{

+		alpha = ALPHA5;                   

+	}

+	for (i = 0; i < COMPLEN; i++)

+	{

+		st->ave_level[i] = add1(st->ave_level[i], vo_mult_r(alpha, vo_sub(level[i], st->ave_level[i])));   

+	}

+}

+

+/******************************************************************************

+*

+*     Function     : hangover_addition

+*     Purpose      : Add hangover after speech bursts

+*

+*******************************************************************************/

+

+static Word16 hangover_addition(                      /* return: VAD_flag indicating final VAD decision */

+		VadVars * st,                         /* i/o : State structure                     */

+		Word16 low_power,                     /* i   : flag power of the input frame    */

+		Word16 hang_len,                      /* i   : hangover length */

+		Word16 burst_len                      /* i   : minimum burst length for hangover addition */

+		)

+{

+	/* if the input power (pow_sum) is lower than a threshold, clear counters and set VAD_flag to "0"         */

+	if (low_power != 0)

+	{

+		st->burst_count = 0;               

+		st->hang_count = 0;                

+		return 0;

+	}

+	/* update the counters (hang_count, burst_count) */

+	if ((st->vadreg & 0x4000) != 0)

+	{

+		st->burst_count = st->burst_count + 1;    

+		if(st->burst_count >= burst_len)

+		{

+			st->hang_count = hang_len;     

+		}

+		return 1;

+	} else

+	{

+		st->burst_count = 0;               

+		if (st->hang_count > 0)

+		{

+			st->hang_count = st->hang_count - 1;    

+			return 1;

+		}

+	}

+	return 0;

+}

+

+/******************************************************************************

+*

+*     Function   : noise_estimate_update

+*     Purpose    : Update of background noise estimate

+*

+*******************************************************************************/

+

+static void noise_estimate_update(

+		VadVars * st,                         /* i/o : State structure                       */

+		Word16 level[]                        /* i   : sub-band levels of the input frame */

+		)

+{

+	Word32 i; 

+	Word16 alpha_up, alpha_down, bckr_add = 2;

+

+	/* Control update of bckr_est[] */

+	update_cntrl(st, level);

+

+	/* Choose update speed */

+	if ((0x7800 & st->vadreg) == 0)

+	{

+		alpha_up = ALPHA_UP1;              

+		alpha_down = ALPHA_DOWN1;          

+	} else

+	{

+		if ((st->stat_count == 0))

+		{

+			alpha_up = ALPHA_UP2;          

+			alpha_down = ALPHA_DOWN2;      

+		} else

+		{

+			alpha_up = 0;                  

+			alpha_down = ALPHA3;           

+			bckr_add = 0;                  

+		}

+	}

+

+	/* Update noise estimate (bckr_est) */

+	for (i = 0; i < COMPLEN; i++)

+	{

+		Word16 temp;

+		temp = (st->old_level[i] - st->bckr_est[i]);

+

+		if (temp < 0)

+		{                                  /* update downwards */

+			st->bckr_est[i] = add1(-2, add(st->bckr_est[i],vo_mult_r(alpha_down, temp))); 

+			/* limit minimum value of the noise estimate to NOISE_MIN */

+			if(st->bckr_est[i] < NOISE_MIN)

+			{

+				st->bckr_est[i] = NOISE_MIN;   

+			}

+		} else

+		{                                  /* update upwards */

+			st->bckr_est[i] = add1(bckr_add, add1(st->bckr_est[i],vo_mult_r(alpha_up, temp)));   

+

+			/* limit maximum value of the noise estimate to NOISE_MAX */

+			if(st->bckr_est[i] > NOISE_MAX)

+			{

+				st->bckr_est[i] = NOISE_MAX;    

+			}

+		}

+	}

+

+	/* Update signal levels of the previous frame (old_level) */

+	for (i = 0; i < COMPLEN; i++)

+	{

+		st->old_level[i] = level[i];      

+	}

+}

+

+/******************************************************************************

+*

+*     Function     : vad_decision

+*     Purpose      : Calculates VAD_flag

+*

+*******************************************************************************/

+

+static Word16 vad_decision(                           /* return value : VAD_flag */

+		VadVars * st,                         /* i/o : State structure                       */

+		Word16 level[COMPLEN],                /* i   : sub-band levels of the input frame */

+		Word32 pow_sum                        /* i   : power of the input frame           */

+		)

+{

+	Word32 i;

+	Word32 L_snr_sum;

+	Word32 L_temp;

+	Word16 vad_thr, temp, noise_level;

+	Word16 low_power_flag;

+	Word16 hang_len, burst_len;

+	Word16 ilog2_speech_level, ilog2_noise_level;

+	Word16 temp2;

+

+	/* Calculate squared sum of the input levels (level) divided by the background noise components

+	 * (bckr_est). */

+	L_snr_sum = 0;                        

+	for (i = 0; i < COMPLEN; i++)

+	{

+		Word16 exp;

+

+		exp = norm_s(st->bckr_est[i]);

+		temp = (st->bckr_est[i] << exp);

+		temp = div_s((level[i] >> 1), temp);

+		temp = shl(temp, (exp - (UNIRSHFT - 1)));

+		L_snr_sum = L_mac(L_snr_sum, temp, temp);

+	}

+

+	/* Calculate average level of estimated background noise */

+	L_temp = 0;                           

+	for (i = 1; i < COMPLEN; i++)          /* ignore lowest band */

+	{

+		L_temp = vo_L_add(L_temp, st->bckr_est[i]);

+	}

+

+	noise_level = extract_h((L_temp << 12));

+	/* if SNR is lower than a threshold (MIN_SPEECH_SNR), and increase speech_level */

+	temp = vo_mult(noise_level, MIN_SPEECH_SNR) << 3;

+

+	if(st->speech_level < temp)

+	{

+		st->speech_level = temp;          

+	}

+	ilog2_noise_level = ilog2(noise_level);

+

+	/* If SNR is very poor, speech_level is probably corrupted by noise level. This is correctred by

+	 * subtracting MIN_SPEECH_SNR*noise_level from speech level */

+	ilog2_speech_level = ilog2(st->speech_level - temp);

+

+	temp = add1(vo_mult(NO_SLOPE, (ilog2_noise_level - NO_P1)), THR_HIGH);

+

+	temp2 = add1(SP_CH_MIN, vo_mult(SP_SLOPE, (ilog2_speech_level - SP_P1)));

+	if (temp2 < SP_CH_MIN)

+	{

+		temp2 = SP_CH_MIN;                 

+	}

+	if (temp2 > SP_CH_MAX)

+	{

+		temp2 = SP_CH_MAX;                 

+	}

+	vad_thr = temp + temp2;

+

+	if(vad_thr < THR_MIN)

+	{

+		vad_thr = THR_MIN;                 

+	}

+	/* Shift VAD decision register */

+	st->vadreg = (st->vadreg >> 1);       

+

+	/* Make intermediate VAD decision */

+	if(L_snr_sum > vo_L_mult(vad_thr, (512 * COMPLEN)))

+	{

+		st->vadreg = (Word16) (st->vadreg | 0x4000); 

+	}

+	/* check if the input power (pow_sum) is lower than a threshold" */

+	if(pow_sum < VAD_POW_LOW)

+	{

+		low_power_flag = 1;               

+	} else

+	{

+		low_power_flag = 0;               

+	}

+	/* Update background noise estimates */

+	noise_estimate_update(st, level);

+

+	/* Calculate values for hang_len and burst_len based on vad_thr */

+	hang_len = add1(vo_mult(HANG_SLOPE, (vad_thr - HANG_P1)), HANG_HIGH);

+	if(hang_len < HANG_LOW)

+	{

+		hang_len = HANG_LOW;              

+	}

+	burst_len = add1(vo_mult(BURST_SLOPE, (vad_thr - BURST_P1)), BURST_HIGH);

+

+	return (hangover_addition(st, low_power_flag, hang_len, burst_len));

+}

+

+/******************************************************************************

+*

+*     Function : Estimate_Speech()

+*     Purpose  : Estimate speech level

+*

+* Maximum signal level is searched and stored to the variable sp_max.

+* The speech frames must locate within SP_EST_COUNT number of frames.

+* Thus, noisy frames having occasional VAD = "1" decisions will not

+* affect to the estimated speech_level.

+*

+*******************************************************************************/

+

+static void Estimate_Speech(

+		VadVars * st,                         /* i/o : State structure    */

+		Word16 in_level                       /* level of the input frame */

+		)

+{

+	Word16 alpha;

+

+	/* if the required activity count cannot be achieved, reset counters */

+	if((st->sp_est_cnt - st->sp_max_cnt) > (SP_EST_COUNT - SP_ACTIVITY_COUNT))

+	{

+		st->sp_est_cnt = 0;                

+		st->sp_max = 0;                    

+		st->sp_max_cnt = 0;                

+	}

+	st->sp_est_cnt += 1; 

+

+	if (((st->vadreg & 0x4000)||(in_level > st->speech_level)) && (in_level > MIN_SPEECH_LEVEL1))

+	{

+		/* update sp_max */

+		if(in_level > st->sp_max)

+		{

+			st->sp_max = in_level;         

+		}

+		st->sp_max_cnt += 1;        

+

+		if(st->sp_max_cnt >= SP_ACTIVITY_COUNT)

+		{

+			Word16 tmp;

+			/* update speech estimate */

+			tmp = (st->sp_max >> 1);      /* scale to get "average" speech level */

+

+			/* select update speed */

+			if(tmp > st->speech_level)

+			{

+				alpha = ALPHA_SP_UP;       

+			} else

+			{

+				alpha = ALPHA_SP_DOWN;    

+			}

+			if(tmp > MIN_SPEECH_LEVEL2)

+			{

+				st->speech_level = add1(st->speech_level, vo_mult_r(alpha, vo_sub(tmp, st->speech_level))); 

+			}

+			/* clear all counters used for speech estimation */

+			st->sp_max = 0;                

+			st->sp_max_cnt = 0;            

+			st->sp_est_cnt = 0;            

+		}

+	}

+}

+

+/******************************************************************************

+*

+*  Function:   wb_vad_init

+*  Purpose:    Allocates state memory and initializes state memory

+*

+*******************************************************************************/

+

+Word16 wb_vad_init(                        /* return: non-zero with error, zero for ok. */

+		VadVars ** state,                     /* i/o : State structure    */

+		VO_MEM_OPERATOR *pMemOP

+		)

+{

+	VadVars *s;

+

+	if (state == (VadVars **) NULL)

+	{

+		fprintf(stderr, "vad_init: invalid parameter\n");

+		return -1;

+	}

+	*state = NULL;

+

+	/* allocate memory */

+	if ((s = (VadVars *) mem_malloc(pMemOP, sizeof(VadVars), 32, VO_INDEX_ENC_AMRWB)) == NULL)

+	{

+		fprintf(stderr, "vad_init: can not malloc state structure\n");

+		return -1;

+	}

+	wb_vad_reset(s);

+

+	*state = s;

+

+	return 0;

+}

+

+/******************************************************************************

+*

+*  Function:   wb_vad_reset

+*  Purpose:    Initializes state memory

+*

+*******************************************************************************/

+

+Word16 wb_vad_reset(                       /* return: non-zero with error, zero for ok. */

+		VadVars * state                       /* i/o : State structure    */

+		)

+{

+	Word32 i, j;

+

+	if (state == (VadVars *) NULL)

+	{

+		fprintf(stderr, "vad_reset: invalid parameter\n");

+		return -1;

+	}

+	state->tone_flag = 0;

+	state->vadreg = 0;

+	state->hang_count = 0;

+	state->burst_count = 0;

+	state->hang_count = 0;

+

+	/* initialize memory used by the filter bank */

+	for (i = 0; i < F_5TH_CNT; i++)

+	{

+		for (j = 0; j < 2; j++)

+		{

+			state->a_data5[i][j] = 0;

+		}

+	}

+

+	for (i = 0; i < F_3TH_CNT; i++)

+	{

+		state->a_data3[i] = 0;

+	}

+

+	/* initialize the rest of the memory */

+	for (i = 0; i < COMPLEN; i++)

+	{

+		state->bckr_est[i] = NOISE_INIT;

+		state->old_level[i] = NOISE_INIT;

+		state->ave_level[i] = NOISE_INIT;

+		state->sub_level[i] = 0;

+	}

+

+	state->sp_est_cnt = 0;

+	state->sp_max = 0;

+	state->sp_max_cnt = 0;

+	state->speech_level = SPEECH_LEVEL_INIT;

+	state->prev_pow_sum = 0;

+	return 0;

+}

+

+/******************************************************************************

+*

+*  Function:   wb_vad_exit

+*  Purpose:    The memory used for state memory is freed

+*

+*******************************************************************************/

+

+void wb_vad_exit(

+		VadVars ** state,                      /* i/o : State structure    */

+		VO_MEM_OPERATOR *pMemOP

+		)

+{

+	if (state == NULL || *state == NULL)

+		return;

+	/* deallocate memory */

+	mem_free(pMemOP, *state, VO_INDEX_ENC_AMRWB);

+	*state = NULL;

+	return;

+}

+

+/******************************************************************************

+*

+*     Function     : wb_vad_tone_detection

+*     Purpose      : Search maximum pitch gain from a frame. Set tone flag if

+*                    pitch gain is high. This is used to detect

+*                    signaling tones and other signals with high pitch gain.

+*

+*******************************************************************************/

+

+void wb_vad_tone_detection(

+		VadVars * st,                         /* i/o : State struct            */

+		Word16 p_gain                         /* pitch gain      */

+		)

+{

+	/* update tone flag */

+	st->tone_flag = (st->tone_flag >> 1);

+

+	/* if (pitch_gain > TONE_THR) set tone flag */

+	if (p_gain > TONE_THR)

+	{

+		st->tone_flag = (Word16) (st->tone_flag | 0x4000);

+	}

+}

+

+/******************************************************************************

+*

+*     Function     : wb_vad

+*     Purpose      : Main program for Voice Activity Detection (VAD) for AMR

+*

+*******************************************************************************/

+

+Word16 wb_vad(                                /* Return value : VAD Decision, 1 = speech, 0 = noise */

+		VadVars * st,                         /* i/o : State structure                 */

+		Word16 in_buf[]                       /* i   : samples of the input frame   */

+	     )

+{

+	Word16 level[COMPLEN];

+	Word32 i;

+	Word16 VAD_flag, temp;

+	Word32 L_temp, pow_sum;

+

+	/* Calculate power of the input frame. */

+	L_temp = 0L;                           

+	for (i = 0; i < FRAME_LEN; i++)

+	{

+		L_temp = L_mac(L_temp, in_buf[i], in_buf[i]);

+	}

+

+	/* pow_sum = power of current frame and previous frame */

+	pow_sum = L_add(L_temp, st->prev_pow_sum);  

+

+	/* save power of current frame for next call */

+	st->prev_pow_sum = L_temp;             

+

+	/* If input power is very low, clear tone flag */

+	if (pow_sum < POW_TONE_THR)

+	{

+		st->tone_flag = (Word16) (st->tone_flag & 0x1fff);      

+	}

+	/* Run the filter bank and calculate signal levels at each band */

+	filter_bank(st, in_buf, level);

+

+	/* compute VAD decision */

+	VAD_flag = vad_decision(st, level, pow_sum);

+

+	/* Calculate input level */

+	L_temp = 0;                          

+	for (i = 1; i < COMPLEN; i++)          /* ignore lowest band */

+	{

+		L_temp = vo_L_add(L_temp, level[i]);

+	}

+

+	temp = extract_h(L_temp << 12);

+

+	Estimate_Speech(st, temp);             /* Estimate speech level */

+	return (VAD_flag);

+}

+

+

+

+

diff --git a/media/libstagefright/codecs/amrwbenc/src/weight_a.c b/media/libstagefright/codecs/amrwbenc/src/weight_a.c
new file mode 100644
index 0000000..d47be97
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/weight_a.c
@@ -0,0 +1,48 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+

+/***********************************************************************

+*       File: weight_a.c                                               *

+*                                                                      *

+*       Description:Weighting of LPC coefficients                      *

+*	               ap[i] = a[i] * (gamma ** i)                     *

+*                                                                      * 

+************************************************************************/

+

+#include "typedef.h"

+#include "basic_op.h"

+

+void Weight_a(

+		Word16 a[],                           /* (i) Q12 : a[m+1]  LPC coefficients             */

+		Word16 ap[],                          /* (o) Q12 : Spectral expanded LPC coefficients   */

+		Word16 gamma,                         /* (i) Q15 : Spectral expansion factor.           */

+		Word16 m                              /* (i)     : LPC order.                           */

+	     )

+{

+	Word32 num = m - 1, fac;

+	*ap++ = *a++;

+	fac = gamma;

+	do{

+		*ap++ =(Word16)(((vo_L_mult((*a++), fac)) + 0x8000) >> 16);

+		fac = (vo_L_mult(fac, gamma) + 0x8000) >> 16;

+	}while(--num != 0);

+

+	*ap++ = (Word16)(((vo_L_mult((*a++), fac)) + 0x8000) >> 16);

+	return;

+}

+

+

+

diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index aa2a3d1..050e3da 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -34,6 +34,8 @@
 
 namespace android {
 
+static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 };
+
 static int32_t Malloc(void *userData, int32_t size, int32_t attrs) {
     return reinterpret_cast<int32_t>(malloc(size));
 }
@@ -49,7 +51,9 @@
       mInputBuffer(NULL),
       mAnchorTimeUs(0),
       mNumSamplesOutput(0),
-      mPendingSeekTimeUs(-1) {
+      mPendingSeekTimeUs(-1),
+      mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC),
+      mTargetTimeUs(-1) {
     memset(mHandle, 0, sizeof(tagAVCHandle));
     mHandle->AVCObject = NULL;
     mHandle->userData = this;
@@ -154,22 +158,23 @@
         }
     }
 
-    sp<MetaData> params = new MetaData;
-    params->setInt32(kKeyWantsNALFragments, true);
-    mSource->start(params.get());
+    mSource->start();
 
     mAnchorTimeUs = 0;
     mNumSamplesOutput = 0;
     mPendingSeekTimeUs = -1;
+    mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
+    mTargetTimeUs = -1;
     mStarted = true;
 
     return OK;
 }
 
 void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) {
-    MediaBuffer *buffer = new MediaBuffer(size);
-    memcpy(buffer->data(), data, size);
-    buffer->set_range(0, size);
+    MediaBuffer *buffer = new MediaBuffer(size + 4);
+    memcpy(buffer->data(), kStartCode, 4);
+    memcpy((uint8_t *)buffer->data() + 4, data, size);
+    buffer->set_range(0, size + 4);
 
     mCodecSpecificData.push(buffer);
 }
@@ -200,16 +205,41 @@
     return mFormat;
 }
 
+static void findNALFragment(
+        const MediaBuffer *buffer, const uint8_t **fragPtr, size_t *fragSize) {
+    const uint8_t *data =
+        (const uint8_t *)buffer->data() + buffer->range_offset();
+
+    size_t size = buffer->range_length();
+
+    CHECK(size >= 4);
+    CHECK(!memcmp(kStartCode, data, 4));
+
+    size_t offset = 4;
+    while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) {
+        ++offset;
+    }
+
+    *fragPtr = &data[4];
+    if (offset + 3 >= size) {
+        *fragSize = size - 4;
+    } else {
+        *fragSize = offset - 4;
+    }
+}
+
 status_t AVCDecoder::read(
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         LOGV("seek requested to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
 
         CHECK(seekTimeUs >= 0);
         mPendingSeekTimeUs = seekTimeUs;
+        mPendingSeekMode = mode;
 
         if (mInputBuffer) {
             mInputBuffer->release();
@@ -222,6 +252,8 @@
     if (mInputBuffer == NULL) {
         LOGV("fetching new input buffer.");
 
+        bool seeking = false;
+
         if (!mCodecSpecificData.isEmpty()) {
             mInputBuffer = mCodecSpecificData.editItemAt(0);
             mCodecSpecificData.removeAt(0);
@@ -234,7 +266,9 @@
 
                 ReadOptions seekOptions;
                 if (mPendingSeekTimeUs >= 0) {
-                    seekOptions.setSeekTo(mPendingSeekTimeUs);
+                    seeking = true;
+
+                    seekOptions.setSeekTo(mPendingSeekTimeUs, mPendingSeekMode);
                     mPendingSeekTimeUs = -1;
                 }
                 status_t err = mSource->read(&mInputBuffer, &seekOptions);
@@ -252,39 +286,43 @@
                 mInputBuffer = NULL;
             }
         }
+
+        if (seeking) {
+            int64_t targetTimeUs;
+            if (mInputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
+                    && targetTimeUs >= 0) {
+                mTargetTimeUs = targetTimeUs;
+            } else {
+                mTargetTimeUs = -1;
+            }
+        }
     }
 
-    const uint8_t *inPtr =
-        (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
+    const uint8_t *fragPtr;
+    size_t fragSize;
+    findNALFragment(mInputBuffer, &fragPtr, &fragSize);
+
+    bool releaseFragment = true;
+    status_t err = UNKNOWN_ERROR;
 
     int nalType;
     int nalRefIdc;
     AVCDec_Status res =
         PVAVCDecGetNALType(
-                const_cast<uint8_t *>(inPtr), mInputBuffer->range_length(),
+                const_cast<uint8_t *>(fragPtr), fragSize,
                 &nalType, &nalRefIdc);
 
     if (res != AVCDEC_SUCCESS) {
         LOGE("cannot determine nal type");
-
-        mInputBuffer->release();
-        mInputBuffer = NULL;
-
-        return UNKNOWN_ERROR;
-    }
-
-    switch (nalType) {
+    } else switch (nalType) {
         case AVC_NALTYPE_SPS:
         {
             res = PVAVCDecSeqParamSet(
-                    mHandle, const_cast<uint8_t *>(inPtr),
-                    mInputBuffer->range_length());
+                    mHandle, const_cast<uint8_t *>(fragPtr),
+                    fragSize);
 
             if (res != AVCDEC_SUCCESS) {
-                mInputBuffer->release();
-                mInputBuffer = NULL;
-
-                return UNKNOWN_ERROR;
+                break;
             }
 
             AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
@@ -324,100 +362,128 @@
 
             int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15;
             int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15;
-            mFormat->setInt32(kKeyWidth, aligned_width);
-            mFormat->setInt32(kKeyHeight, aligned_height);
 
-            mInputBuffer->release();
-            mInputBuffer = NULL;
+            int32_t oldWidth, oldHeight;
+            CHECK(mFormat->findInt32(kKeyWidth, &oldWidth));
+            CHECK(mFormat->findInt32(kKeyHeight, &oldHeight));
 
-            return INFO_FORMAT_CHANGED;
+            if (oldWidth != aligned_width || oldHeight != aligned_height) {
+                mFormat->setInt32(kKeyWidth, aligned_width);
+                mFormat->setInt32(kKeyHeight, aligned_height);
+
+                err = INFO_FORMAT_CHANGED;
+            } else {
+                *out = new MediaBuffer(0);
+                err = OK;
+            }
+            break;
         }
 
         case AVC_NALTYPE_PPS:
         {
             res = PVAVCDecPicParamSet(
-                    mHandle, const_cast<uint8_t *>(inPtr),
-                    mInputBuffer->range_length());
-
-            mInputBuffer->release();
-            mInputBuffer = NULL;
+                    mHandle, const_cast<uint8_t *>(fragPtr),
+                    fragSize);
 
             if (res != AVCDEC_SUCCESS) {
-                return UNKNOWN_ERROR;
+                break;
             }
 
             *out = new MediaBuffer(0);
 
-            return OK;
+            err = OK;
+            break;
         }
 
         case AVC_NALTYPE_SLICE:
         case AVC_NALTYPE_IDR:
         {
             res = PVAVCDecodeSlice(
-                    mHandle, const_cast<uint8_t *>(inPtr),
-                    mInputBuffer->range_length());
+                    mHandle, const_cast<uint8_t *>(fragPtr),
+                    fragSize);
 
             if (res == AVCDEC_PICTURE_OUTPUT_READY) {
                 int32_t index;
                 int32_t Release;
                 AVCFrameIO Output;
                 Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
-                CHECK_EQ(PVAVCDecGetOutput(
-                            mHandle, &index, &Release, &Output),
+
+                CHECK_EQ(PVAVCDecGetOutput(mHandle, &index, &Release, &Output),
                          AVCDEC_SUCCESS);
 
                 CHECK(index >= 0);
                 CHECK(index < (int32_t)mFrames.size());
 
-                *out = mFrames.editItemAt(index);
-                (*out)->set_range(0, (*out)->size());
-                (*out)->add_ref();
+                MediaBuffer *mbuf = mFrames.editItemAt(index);
+
+                bool skipFrame = false;
+
+                if (mTargetTimeUs >= 0) {
+                    int64_t timeUs;
+                    CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+                    CHECK(timeUs <= mTargetTimeUs);
+
+                    if (timeUs < mTargetTimeUs) {
+                        // We're still waiting for the frame with the matching
+                        // timestamp and we won't return the current one.
+                        skipFrame = true;
+
+                        LOGV("skipping frame at %lld us", timeUs);
+                    } else {
+                        LOGV("found target frame at %lld us", timeUs);
+
+                        mTargetTimeUs = -1;
+                    }
+                }
+
+                if (!skipFrame) {
+                    *out = mbuf;
+                    (*out)->set_range(0, (*out)->size());
+                    (*out)->add_ref();
+                } else {
+                    *out = new MediaBuffer(0);
+                }
 
                 // Do _not_ release input buffer yet.
 
-                return OK;
+                releaseFragment = false;
+                err = OK;
+                break;
             }
 
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-
             if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) {
                 *out = new MediaBuffer(0);
 
-                return OK;
+                err = OK;
             } else {
                 LOGV("failed to decode frame (res = %d)", res);
-                return UNKNOWN_ERROR;
             }
+            break;
         }
 
         case AVC_NALTYPE_SEI:
         {
             res = PVAVCDecSEI(
-                    mHandle, const_cast<uint8_t *>(inPtr),
-                    mInputBuffer->range_length());
-
-            mInputBuffer->release();
-            mInputBuffer = NULL;
+                    mHandle, const_cast<uint8_t *>(fragPtr),
+                    fragSize);
 
             if (res != AVCDEC_SUCCESS) {
-                return UNKNOWN_ERROR;
+                break;
             }
 
             *out = new MediaBuffer(0);
 
-            return OK;
+            err = OK;
+            break;
         }
 
         case AVC_NALTYPE_AUD:
+        case AVC_NALTYPE_FILL:
         {
-            mInputBuffer->release();
-            mInputBuffer = NULL;
-
             *out = new MediaBuffer(0);
 
-            return OK;
+            err = OK;
+            break;
         }
 
         default:
@@ -428,10 +494,19 @@
         }
     }
 
-    mInputBuffer->release();
-    mInputBuffer = NULL;
+    if (releaseFragment) {
+        size_t offset = mInputBuffer->range_offset();
+        if (fragSize + 4 == mInputBuffer->range_length()) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+        } else {
+            mInputBuffer->set_range(
+                    offset + fragSize + 4,
+                    mInputBuffer->range_length() - fragSize - 4);
+        }
+    }
 
-    return UNKNOWN_ERROR;
+    return err;
 }
 
 // static
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
new file mode 100644
index 0000000..d5eb156
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -0,0 +1,492 @@
+/*
+ * Copyright (C) 2010 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 "AVCEncoder"
+#include <utils/Log.h>
+
+#include "AVCEncoder.h"
+
+#include "avcenc_api.h"
+#include "avcenc_int.h"
+#include "OMX_Video.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+inline static void ConvertYUV420SemiPlanarToYUV420Planar(
+        uint8_t *inyuv, uint8_t* outyuv,
+        int32_t width, int32_t height) {
+
+    int32_t outYsize = width * height;
+    uint32_t *outy =  (uint32_t *) outyuv;
+    uint16_t *outcb = (uint16_t *) (outyuv + outYsize);
+    uint16_t *outcr = (uint16_t *) (outyuv + outYsize + (outYsize >> 2));
+
+    /* Y copying */
+    memcpy(outy, inyuv, outYsize);
+
+    /* U & V copying */
+    uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
+    for (int32_t i = height >> 1; i > 0; --i) {
+        for (int32_t j = width >> 2; j > 0; --j) {
+            uint32_t temp = *inyuv_4++;
+            uint32_t tempU = temp & 0xFF;
+            tempU = tempU | ((temp >> 8) & 0xFF00);
+
+            uint32_t tempV = (temp >> 8) & 0xFF;
+            tempV = tempV | ((temp >> 16) & 0xFF00);
+
+            // Flip U and V
+            *outcb++ = tempV;
+            *outcr++ = tempU;
+        }
+    }
+}
+
+static int32_t MallocWrapper(
+        void *userData, int32_t size, int32_t attrs) {
+    return reinterpret_cast<int32_t>(malloc(size));
+}
+
+static void FreeWrapper(void *userData, int32_t ptr) {
+    free(reinterpret_cast<void *>(ptr));
+}
+
+static int32_t DpbAllocWrapper(void *userData,
+        unsigned int sizeInMbs, unsigned int numBuffers) {
+    AVCEncoder *encoder = static_cast<AVCEncoder *>(userData);
+    CHECK(encoder != NULL);
+    return encoder->allocOutputBuffers(sizeInMbs, numBuffers);
+}
+
+static int32_t BindFrameWrapper(
+        void *userData, int32_t index, uint8_t **yuv) {
+    AVCEncoder *encoder = static_cast<AVCEncoder *>(userData);
+    CHECK(encoder != NULL);
+    return encoder->bindOutputBuffer(index, yuv);
+}
+
+static void UnbindFrameWrapper(void *userData, int32_t index) {
+    AVCEncoder *encoder = static_cast<AVCEncoder *>(userData);
+    CHECK(encoder != NULL);
+    return encoder->unbindOutputBuffer(index);
+}
+
+AVCEncoder::AVCEncoder(
+        const sp<MediaSource>& source,
+        const sp<MetaData>& meta)
+    : mSource(source),
+      mMeta(meta),
+      mNumInputFrames(-1),
+      mStarted(false),
+      mInputBuffer(NULL),
+      mInputFrameData(NULL),
+      mGroup(NULL) {
+
+    LOGV("Construct software AVCEncoder");
+
+    mHandle = new tagAVCHandle;
+    memset(mHandle, 0, sizeof(tagAVCHandle));
+    mHandle->AVCObject = NULL;
+    mHandle->userData = this;
+    mHandle->CBAVC_DPBAlloc = DpbAllocWrapper;
+    mHandle->CBAVC_FrameBind = BindFrameWrapper;
+    mHandle->CBAVC_FrameUnbind = UnbindFrameWrapper;
+    mHandle->CBAVC_Malloc = MallocWrapper;
+    mHandle->CBAVC_Free = FreeWrapper;
+
+    mInitCheck = initCheck(meta);
+}
+
+AVCEncoder::~AVCEncoder() {
+    LOGV("Destruct software AVCEncoder");
+    if (mStarted) {
+        stop();
+    }
+
+    delete mEncParams;
+    delete mHandle;
+}
+
+status_t AVCEncoder::initCheck(const sp<MetaData>& meta) {
+    LOGV("initCheck");
+    CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
+    CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
+    CHECK(meta->findInt32(kKeySampleRate, &mVideoFrameRate));
+    CHECK(meta->findInt32(kKeyBitRate, &mVideoBitRate));
+
+    // XXX: Add more color format support
+    CHECK(meta->findInt32(kKeyColorFormat, &mVideoColorFormat));
+    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+        if (mVideoColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
+            LOGE("Color format %d is not supported", mVideoColorFormat);
+            return BAD_VALUE;
+        }
+        // Allocate spare buffer only when color conversion is needed.
+        // Assume the color format is OMX_COLOR_FormatYUV420SemiPlanar.
+        mInputFrameData =
+            (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+        CHECK(mInputFrameData);
+    }
+
+    // XXX: Remove this restriction
+    if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+        LOGE("Video frame size %dx%d must be a multiple of 16",
+            mVideoWidth, mVideoHeight);
+        return BAD_VALUE;
+    }
+
+    mEncParams = new tagAVCEncParam;
+    memset(mEncParams, 0, sizeof(mEncParams));
+    mEncParams->width = mVideoWidth;
+    mEncParams->height = mVideoHeight;
+    mEncParams->frame_rate = 1000 * mVideoFrameRate;  // In frames/ms!
+    mEncParams->rate_control = AVC_ON;
+    mEncParams->bitrate = mVideoBitRate;
+    mEncParams->initQP = 0;
+    mEncParams->init_CBP_removal_delay = 1600;
+    mEncParams->CPB_size = (uint32_t) (mVideoBitRate >> 1);
+
+    mEncParams->intramb_refresh = 0;
+    mEncParams->auto_scd = AVC_ON;
+    mEncParams->out_of_band_param_set = AVC_ON;
+    mEncParams->poc_type = 2;
+    mEncParams->log2_max_poc_lsb_minus_4 = 12;
+    mEncParams->delta_poc_zero_flag = 0;
+    mEncParams->offset_poc_non_ref = 0;
+    mEncParams->offset_top_bottom = 0;
+    mEncParams->num_ref_in_cycle = 0;
+    mEncParams->offset_poc_ref = NULL;
+
+    mEncParams->num_ref_frame = 1;
+    mEncParams->num_slice_group = 1;
+    mEncParams->fmo_type = 0;
+
+    mEncParams->db_filter = AVC_ON;
+    mEncParams->disable_db_idc = 0;
+
+    mEncParams->alpha_offset = 0;
+    mEncParams->beta_offset = 0;
+    mEncParams->constrained_intra_pred = AVC_OFF;
+
+    mEncParams->data_par = AVC_OFF;
+    mEncParams->fullsearch = AVC_OFF;
+    mEncParams->search_range = 16;
+    mEncParams->sub_pel = AVC_OFF;
+    mEncParams->submb_pred = AVC_OFF;
+    mEncParams->rdopt_mode = AVC_OFF;
+    mEncParams->bidir_pred = AVC_OFF;
+    int32_t nMacroBlocks = ((((mVideoWidth + 15) >> 4) << 4) *
+            (((mVideoHeight + 15) >> 4) << 4)) >> 8;
+    uint32_t *sliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks);
+    for (int ii = 0, idx = 0; ii < nMacroBlocks; ++ii) {
+        sliceGroup[ii] = idx++;
+        if (idx >= mEncParams->num_slice_group) {
+            idx = 0;
+        }
+    }
+    mEncParams->slice_group = sliceGroup;
+
+    mEncParams->use_overrun_buffer = AVC_OFF;
+
+    // Set IDR frame refresh interval
+    int32_t iFramesIntervalSec;
+    CHECK(meta->findInt32(kKeyIFramesInterval, &iFramesIntervalSec));
+    if (iFramesIntervalSec < 0) {
+        mEncParams->idr_period = -1;
+    } else if (iFramesIntervalSec == 0) {
+        mEncParams->idr_period = 1;  // All I frames
+    } else {
+        mEncParams->idr_period =
+            (iFramesIntervalSec * mVideoFrameRate);
+    }
+    LOGV("idr_period: %d, I-frames interval: %d seconds, and frame rate: %d",
+        mEncParams->idr_period, iFramesIntervalSec, mVideoFrameRate);
+
+    // Set profile and level
+    // If profile and level setting is not correct, failure
+    // is reported when the encoder is initialized.
+    mEncParams->profile = AVC_BASELINE;
+    mEncParams->level = AVC_LEVEL3_2;
+    int32_t profile, level;
+    if (meta->findInt32(kKeyVideoProfile, &profile)) {
+        mEncParams->profile = (AVCProfile) profile;
+    }
+    if (meta->findInt32(kKeyVideoLevel, &level)) {
+        mEncParams->level = (AVCLevel) level;
+    }
+
+
+    mFormat = new MetaData;
+    mFormat->setInt32(kKeyWidth, mVideoWidth);
+    mFormat->setInt32(kKeyHeight, mVideoHeight);
+    mFormat->setInt32(kKeyBitRate, mVideoBitRate);
+    mFormat->setInt32(kKeySampleRate, mVideoFrameRate);
+    mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
+    mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+    mFormat->setCString(kKeyDecoderComponent, "AVCEncoder");
+    return OK;
+}
+
+status_t AVCEncoder::start(MetaData *params) {
+    LOGV("start");
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mStarted) {
+        LOGW("Call start() when encoder already started");
+        return OK;
+    }
+
+    AVCEnc_Status err;
+    err = PVAVCEncInitialize(mHandle, mEncParams, NULL, NULL);
+    if (err != AVCENC_SUCCESS) {
+        LOGE("Failed to initialize the encoder: %d", err);
+        return UNKNOWN_ERROR;
+    }
+
+    mGroup = new MediaBufferGroup();
+    int32_t maxSize;
+    if (AVCENC_SUCCESS !=
+        PVAVCEncGetMaxOutputBufferSize(mHandle, &maxSize)) {
+        maxSize = 31584;  // Magic #
+    }
+    mGroup->add_buffer(new MediaBuffer(maxSize));
+
+    mSource->start(params);
+    mNumInputFrames = -2;  // 1st two buffers contain SPS and PPS
+    mStarted = true;
+    mSpsPpsHeaderReceived = false;
+    mReadyForNextFrame = true;
+    mIsIDRFrame = 0;
+
+    return OK;
+}
+
+status_t AVCEncoder::stop() {
+    LOGV("stop");
+    if (!mStarted) {
+        LOGW("Call stop() when encoder has not started");
+        return OK;
+    }
+
+    if (mInputBuffer) {
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    if (mGroup) {
+        delete mGroup;
+        mGroup = NULL;
+    }
+
+    if (mInputFrameData) {
+        delete mInputFrameData;
+        mInputFrameData = NULL;
+    }
+
+    PVAVCCleanUpEncoder(mHandle);
+    mSource->stop();
+    releaseOutputBuffers();
+    mStarted = false;
+
+    return OK;
+}
+
+void AVCEncoder::releaseOutputBuffers() {
+    LOGV("releaseOutputBuffers");
+    for (size_t i = 0; i < mOutputBuffers.size(); ++i) {
+        MediaBuffer *buffer = mOutputBuffers.editItemAt(i);
+        buffer->setObserver(NULL);
+        buffer->release();
+    }
+    mOutputBuffers.clear();
+}
+
+sp<MetaData> AVCEncoder::getFormat() {
+    LOGV("getFormat");
+    return mFormat;
+}
+
+status_t AVCEncoder::read(
+        MediaBuffer **out, const ReadOptions *options) {
+
+    CHECK(!options);
+    *out = NULL;
+
+    MediaBuffer *outputBuffer;
+    CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer));
+    uint8_t *outPtr = (uint8_t *) outputBuffer->data();
+    uint32_t dataLength = outputBuffer->size();
+
+    int32_t type;
+    AVCEnc_Status encoderStatus = AVCENC_SUCCESS;
+
+    // Return SPS and PPS for the first two buffers
+    if (!mSpsPpsHeaderReceived) {
+        encoderStatus = PVAVCEncodeNAL(mHandle, outPtr, &dataLength, &type);
+        if (encoderStatus == AVCENC_WRONG_STATE) {
+            mSpsPpsHeaderReceived = true;
+            CHECK_EQ(0, mNumInputFrames);  // 1st video frame is 0
+        } else {
+            switch (type) {
+                case AVC_NALTYPE_SPS:
+                case AVC_NALTYPE_PPS:
+                    LOGV("%s received",
+                            (type == AVC_NALTYPE_SPS)? "SPS": "PPS");
+                    ++mNumInputFrames;
+                    outputBuffer->set_range(0, dataLength);
+                    *out = outputBuffer;
+                    return OK;
+                default:
+                    LOGE("Nal type (%d) other than SPS/PPS is unexpected", type);
+                    return UNKNOWN_ERROR;
+            }
+        }
+    }
+
+    // Get next input video frame
+    if (mReadyForNextFrame) {
+        if (mInputBuffer) {
+            mInputBuffer->release();
+            mInputBuffer = NULL;
+        }
+        status_t err = mSource->read(&mInputBuffer, options);
+        if (err != OK) {
+            LOGE("Failed to read input video frame: %d", err);
+            outputBuffer->release();
+            return err;
+        }
+        int64_t timeUs;
+        CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+        outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+        AVCFrameIO videoInput;
+        memset(&videoInput, 0, sizeof(videoInput));
+        videoInput.height = ((mVideoHeight  + 15) >> 4) << 4;
+        videoInput.pitch = ((mVideoWidth + 15) >> 4) << 4;
+        videoInput.coding_timestamp = (timeUs + 500) / 1000;  // in ms
+        uint8_t *inputData = (uint8_t *) mInputBuffer->data();
+
+        if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+            CHECK(mInputFrameData);
+            CHECK(mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar);
+            ConvertYUV420SemiPlanarToYUV420Planar(
+                inputData, mInputFrameData, mVideoWidth, mVideoHeight);
+            inputData = mInputFrameData;
+        }
+        CHECK(inputData != NULL);
+        videoInput.YCbCr[0] = inputData;
+        videoInput.YCbCr[1] = videoInput.YCbCr[0] + videoInput.height * videoInput.pitch;
+        videoInput.YCbCr[2] = videoInput.YCbCr[1] +
+            ((videoInput.height * videoInput.pitch) >> 2);
+        videoInput.disp_order = mNumInputFrames;
+
+        encoderStatus = PVAVCEncSetInput(mHandle, &videoInput);
+        if (encoderStatus == AVCENC_SUCCESS ||
+            encoderStatus == AVCENC_NEW_IDR) {
+            mReadyForNextFrame = false;
+            ++mNumInputFrames;
+            if (encoderStatus == AVCENC_NEW_IDR) {
+                mIsIDRFrame = 1;
+            }
+        } else {
+            if (encoderStatus < AVCENC_SUCCESS) {
+                outputBuffer->release();
+                return UNKNOWN_ERROR;
+            } else {
+                outputBuffer->set_range(0, 0);
+                *out = outputBuffer;
+                return OK;
+            }
+        }
+    }
+
+    // Encode an input video frame
+    CHECK(encoderStatus == AVCENC_SUCCESS ||
+          encoderStatus == AVCENC_NEW_IDR);
+    dataLength = outputBuffer->size();  // Reset the output buffer length
+    encoderStatus = PVAVCEncodeNAL(mHandle, outPtr, &dataLength, &type);
+    if (encoderStatus == AVCENC_SUCCESS) {
+        outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, mIsIDRFrame);
+        CHECK_EQ(NULL, PVAVCEncGetOverrunBuffer(mHandle));
+    } else if (encoderStatus == AVCENC_PICTURE_READY) {
+        CHECK_EQ(NULL, PVAVCEncGetOverrunBuffer(mHandle));
+        if (mIsIDRFrame) {
+            outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, mIsIDRFrame);
+            mIsIDRFrame = 0;
+            LOGV("Output an IDR frame");
+        }
+        mReadyForNextFrame = true;
+        AVCFrameIO recon;
+        if (PVAVCEncGetRecon(mHandle, &recon) == AVCENC_SUCCESS) {
+            PVAVCEncReleaseRecon(mHandle, &recon);
+        }
+    } else {
+        dataLength = 0;
+        mReadyForNextFrame = true;
+    }
+    if (encoderStatus < AVCENC_SUCCESS) {
+        outputBuffer->release();
+        return UNKNOWN_ERROR;
+    }
+
+    outputBuffer->set_range(0, dataLength);
+    *out = outputBuffer;
+    return OK;
+}
+
+int32_t AVCEncoder::allocOutputBuffers(
+        unsigned int sizeInMbs, unsigned int numBuffers) {
+    CHECK(mOutputBuffers.isEmpty());
+    size_t frameSize = (sizeInMbs << 7) * 3;
+    for (unsigned int i = 0; i <  numBuffers; ++i) {
+        MediaBuffer *buffer = new MediaBuffer(frameSize);
+        buffer->setObserver(this);
+        mOutputBuffers.push(buffer);
+    }
+
+    return 1;
+}
+
+void AVCEncoder::unbindOutputBuffer(int32_t index) {
+    CHECK(index >= 0);
+}
+
+int32_t AVCEncoder::bindOutputBuffer(int32_t index, uint8_t **yuv) {
+    CHECK(index >= 0);
+    CHECK(index < (int32_t) mOutputBuffers.size());
+    int64_t timeUs;
+    CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+    mOutputBuffers[index]->meta_data()->setInt64(kKeyTime, timeUs);
+
+    *yuv = (uint8_t *) mOutputBuffers[index]->data();
+
+    return 1;
+}
+
+void AVCEncoder::signalBufferReturned(MediaBuffer *buffer) {
+}
+
+}  // namespace android
diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk
new file mode 100644
index 0000000..100f239
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/Android.mk
@@ -0,0 +1,35 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    AVCEncoder.cpp \
+    src/avcenc_api.cpp \
+    src/bitstream_io.cpp \
+    src/block.cpp \
+    src/findhalfpel.cpp \
+    src/header.cpp \
+    src/init.cpp \
+    src/intra_est.cpp \
+    src/motion_comp.cpp \
+    src/motion_est.cpp \
+    src/rate_control.cpp \
+    src/residual.cpp \
+    src/sad.cpp \
+    src/sad_halfpel.cpp \
+    src/slice.cpp \
+    src/vlc_encode.cpp
+
+
+LOCAL_MODULE := libstagefright_avcenc
+
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH)/src \
+    $(LOCAL_PATH)/../common/include \
+    $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+    $(TOP)/frameworks/base/media/libstagefright/include
+
+LOCAL_CFLAGS := \
+    -D__arm__ \
+    -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/avc/enc/src/avcenc_api.cpp b/media/libstagefright/codecs/avc/enc/src/avcenc_api.cpp
new file mode 100644
index 0000000..d39885d
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/avcenc_api.cpp
@@ -0,0 +1,744 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_api.h"
+#include "avcenc_lib.h"
+
+/* ======================================================================== */
+/*  Function : PVAVCGetNALType()                                            */
+/*  Date     : 11/4/2003                                                    */
+/*  Purpose  : Sniff NAL type from the bitstream                            */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS if succeed, AVCENC_FAIL if fail.              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncGetNALType(unsigned char *bitstream, int size,
+        int *nal_type, int *nal_ref_idc)
+{
+    int forbidden_zero_bit;
+    if (size > 0)
+    {
+        forbidden_zero_bit = bitstream[0] >> 7;
+        if (forbidden_zero_bit != 0)
+            return AVCENC_FAIL;
+        *nal_ref_idc = (bitstream[0] & 0x60) >> 5;
+        *nal_type = bitstream[0] & 0x1F;
+        return AVCENC_SUCCESS;
+    }
+
+    return AVCENC_FAIL;
+}
+
+
+/* ======================================================================== */
+/*  Function : PVAVCEncInitialize()                                         */
+/*  Date     : 3/18/2004                                                    */
+/*  Purpose  : Initialize the encoder library, allocate memory and verify   */
+/*              the profile/level support/settings.                         */
+/*  In/out   : Encoding parameters.                                         */
+/*  Return   : AVCENC_SUCCESS for success.                                  */
+/*  Modified :                                                              */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncInitialize(AVCHandle *avcHandle, AVCEncParams *encParam,
+        void* extSPS, void* extPPS)
+{
+    AVCEnc_Status status;
+    AVCEncObject *encvid;
+    AVCCommonObj *video;
+    uint32 *userData = (uint32*) avcHandle->userData;
+    int framesize;
+
+    if (avcHandle->AVCObject != NULL)
+    {
+        return AVCENC_ALREADY_INITIALIZED; /* It's already initialized, need to cleanup first */
+    }
+
+    /* not initialized */
+
+    /* allocate videoObject */
+    avcHandle->AVCObject = (void*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCEncObject), DEFAULT_ATTR);
+    if (avcHandle->AVCObject == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    encvid = (AVCEncObject*) avcHandle->AVCObject;
+    memset(encvid, 0, sizeof(AVCEncObject)); /* reset everything */
+
+    encvid->enc_state = AVCEnc_Initializing;
+
+    encvid->avcHandle = avcHandle;
+
+    encvid->common = (AVCCommonObj*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCCommonObj), DEFAULT_ATTR);
+    if (encvid->common == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    video = encvid->common;
+    memset(video, 0, sizeof(AVCCommonObj));
+
+    /* allocate bitstream structure */
+    encvid->bitstream = (AVCEncBitstream*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCEncBitstream), DEFAULT_ATTR);
+    if (encvid->bitstream == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+    encvid->bitstream->encvid = encvid; /* to point back for reallocation */
+
+    /* allocate sequence parameter set structure */
+    video->currSeqParams = (AVCSeqParamSet*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSeqParamSet), DEFAULT_ATTR);
+    if (video->currSeqParams == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+    memset(video->currSeqParams, 0, sizeof(AVCSeqParamSet));
+
+    /* allocate picture parameter set structure */
+    video->currPicParams = (AVCPicParamSet*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCPicParamSet), DEFAULT_ATTR);
+    if (video->currPicParams == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+    memset(video->currPicParams, 0, sizeof(AVCPicParamSet));
+
+    /* allocate slice header structure */
+    video->sliceHdr = (AVCSliceHeader*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSliceHeader), DEFAULT_ATTR);
+    if (video->sliceHdr == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+    memset(video->sliceHdr, 0, sizeof(AVCSliceHeader));
+
+    /* allocate encoded picture buffer structure*/
+    video->decPicBuf = (AVCDecPicBuffer*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecPicBuffer), DEFAULT_ATTR);
+    if (video->decPicBuf == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+    memset(video->decPicBuf, 0, sizeof(AVCDecPicBuffer));
+
+    /* allocate rate control structure */
+    encvid->rateCtrl = (AVCRateControl*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCRateControl), DEFAULT_ATTR);
+    if (encvid->rateCtrl == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+    memset(encvid->rateCtrl, 0, sizeof(AVCRateControl));
+
+    /* reset frame list, not really needed */
+    video->currPic = NULL;
+    video->currFS = NULL;
+    encvid->currInput = NULL;
+    video->prevRefPic = NULL;
+
+    /* now read encParams, and allocate dimension-dependent variables */
+    /* such as mblock */
+    status = SetEncodeParam(avcHandle, encParam, extSPS, extPPS); /* initialized variables to be used in SPS*/
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    if (encParam->use_overrun_buffer == AVC_ON)
+    {
+        /* allocate overrun buffer */
+        encvid->oBSize = encvid->rateCtrl->cpbSize;
+        if (encvid->oBSize > DEFAULT_OVERRUN_BUFFER_SIZE)
+        {
+            encvid->oBSize = DEFAULT_OVERRUN_BUFFER_SIZE;
+        }
+        encvid->overrunBuffer = (uint8*) avcHandle->CBAVC_Malloc(userData, encvid->oBSize, DEFAULT_ATTR);
+        if (encvid->overrunBuffer == NULL)
+        {
+            return AVCENC_MEMORY_FAIL;
+        }
+    }
+    else
+    {
+        encvid->oBSize = 0;
+        encvid->overrunBuffer = NULL;
+    }
+
+    /* allocate frame size dependent structures */
+    framesize = video->FrameHeightInMbs * video->PicWidthInMbs;
+
+    video->mblock = (AVCMacroblock*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCMacroblock) * framesize, DEFAULT_ATTR);
+    if (video->mblock == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    video->MbToSliceGroupMap = (int*) avcHandle->CBAVC_Malloc(userData, sizeof(uint) * video->PicSizeInMapUnits * 2, DEFAULT_ATTR);
+    if (video->MbToSliceGroupMap == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    encvid->mot16x16 = (AVCMV*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCMV) * framesize, DEFAULT_ATTR);
+    if (encvid->mot16x16 == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+    memset(encvid->mot16x16, 0, sizeof(AVCMV)*framesize);
+
+    encvid->intraSearch = (uint8*) avcHandle->CBAVC_Malloc(userData, sizeof(uint8) * framesize, DEFAULT_ATTR);
+    if (encvid->intraSearch == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    encvid->min_cost = (int*) avcHandle->CBAVC_Malloc(userData, sizeof(int) * framesize, DEFAULT_ATTR);
+    if (encvid->min_cost == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    /* initialize motion search related memory */
+    if (AVCENC_SUCCESS != InitMotionSearchModule(avcHandle))
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    if (AVCENC_SUCCESS != InitRateControlModule(avcHandle))
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    /* intialize function pointers */
+    encvid->functionPointer = (AVCEncFuncPtr*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCEncFuncPtr), DEFAULT_ATTR);
+    if (encvid->functionPointer == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+    encvid->functionPointer->SAD_Macroblock = &AVCSAD_Macroblock_C;
+    encvid->functionPointer->SAD_MB_HalfPel[0] = NULL;
+    encvid->functionPointer->SAD_MB_HalfPel[1] = &AVCSAD_MB_HalfPel_Cxh;
+    encvid->functionPointer->SAD_MB_HalfPel[2] = &AVCSAD_MB_HalfPel_Cyh;
+    encvid->functionPointer->SAD_MB_HalfPel[3] = &AVCSAD_MB_HalfPel_Cxhyh;
+
+    /* initialize timing control */
+    encvid->modTimeRef = 0;     /* ALWAYS ASSUME THAT TIMESTAMP START FROM 0 !!!*/
+    video->prevFrameNum = 0;
+    encvid->prevCodedFrameNum = 0;
+    encvid->dispOrdPOCRef = 0;
+
+    if (encvid->outOfBandParamSet == TRUE)
+    {
+        encvid->enc_state = AVCEnc_Encoding_SPS;
+    }
+    else
+    {
+        encvid->enc_state = AVCEnc_Analyzing_Frame;
+    }
+
+    return AVCENC_SUCCESS;
+}
+
+/* ======================================================================== */
+/*  Function : PVAVCEncGetMaxOutputSize()                                   */
+/*  Date     : 11/29/2008                                                   */
+/*  Purpose  : Return max output buffer size that apps should allocate for  */
+/*              output buffer.                                              */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS for success.                                  */
+/*  Modified :   size                                                       */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncGetMaxOutputBufferSize(AVCHandle *avcHandle, int* size)
+{
+    AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+
+    if (encvid == NULL)
+    {
+        return AVCENC_UNINITIALIZED;
+    }
+
+    *size = encvid->rateCtrl->cpbSize;
+
+    return AVCENC_SUCCESS;
+}
+
+/* ======================================================================== */
+/*  Function : PVAVCEncSetInput()                                           */
+/*  Date     : 4/18/2004                                                    */
+/*  Purpose  : To feed an unencoded original frame to the encoder library.  */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS for success.                                  */
+/*  Modified :                                                              */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncSetInput(AVCHandle *avcHandle, AVCFrameIO *input)
+{
+    AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+    AVCCommonObj *video = encvid->common;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+
+    AVCEnc_Status status;
+    uint frameNum;
+
+    if (encvid == NULL)
+    {
+        return AVCENC_UNINITIALIZED;
+    }
+
+    if (encvid->enc_state == AVCEnc_WaitingForBuffer)
+    {
+        goto RECALL_INITFRAME;
+    }
+    else if (encvid->enc_state != AVCEnc_Analyzing_Frame)
+    {
+        return AVCENC_FAIL;
+    }
+
+    if (input->pitch > 0xFFFF)
+    {
+        return AVCENC_NOT_SUPPORTED; // we use 2-bytes for pitch
+    }
+
+    /***********************************/
+
+    /* Let's rate control decide whether to encode this frame or not */
+    /* Also set video->nal_unit_type, sliceHdr->slice_type, video->slice_type */
+    if (AVCENC_SUCCESS != RCDetermineFrameNum(encvid, rateCtrl, input->coding_timestamp, &frameNum))
+    {
+        return AVCENC_SKIPPED_PICTURE; /* not time to encode, thus skipping */
+    }
+
+    /* we may not need this line */
+    //nextFrmModTime = (uint32)((((frameNum+1)*1000)/rateCtrl->frame_rate) + modTimeRef); /* rec. time */
+    //encvid->nextModTime = nextFrmModTime - (encvid->frameInterval>>1) - 1; /* between current and next frame */
+
+    encvid->currInput = input;
+    encvid->currInput->coding_order = frameNum;
+
+RECALL_INITFRAME:
+    /* initialize and analyze the frame */
+    status = InitFrame(encvid);
+
+    if (status == AVCENC_SUCCESS)
+    {
+        encvid->enc_state = AVCEnc_Encoding_Frame;
+    }
+    else if (status == AVCENC_NEW_IDR)
+    {
+        if (encvid->outOfBandParamSet == TRUE)
+        {
+            encvid->enc_state = AVCEnc_Encoding_Frame;
+        }
+        else // assuming that in-band paramset keeps sending new SPS and PPS.
+        {
+            encvid->enc_state = AVCEnc_Encoding_SPS;
+            //video->currSeqParams->seq_parameter_set_id++;
+            //if(video->currSeqParams->seq_parameter_set_id > 31) // range check
+            {
+                video->currSeqParams->seq_parameter_set_id = 0;  // reset
+            }
+        }
+
+        video->sliceHdr->idr_pic_id++;
+        if (video->sliceHdr->idr_pic_id > 65535) // range check
+        {
+            video->sliceHdr->idr_pic_id = 0;  // reset
+        }
+    }
+    /* the following logics need to be revisited */
+    else if (status == AVCENC_PICTURE_READY) // no buffers returned back to the encoder
+    {
+        encvid->enc_state = AVCEnc_WaitingForBuffer; // Input accepted but can't continue
+        // need to free up some memory before proceeding with Encode
+    }
+
+    return status; // return status, including the AVCENC_FAIL case and all 3 above.
+}
+
+/* ======================================================================== */
+/*  Function : PVAVCEncodeNAL()                                             */
+/*  Date     : 4/29/2004                                                    */
+/*  Purpose  : To encode one NAL/slice.                                     */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS for success.                                  */
+/*  Modified :                                                              */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncodeNAL(AVCHandle *avcHandle, unsigned char *buffer, unsigned int *buf_nal_size, int *nal_type)
+{
+    AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+    AVCCommonObj *video = encvid->common;
+    AVCEncBitstream *bitstream = encvid->bitstream;
+    AVCEnc_Status status;
+
+    if (encvid == NULL)
+    {
+        return AVCENC_UNINITIALIZED;
+    }
+
+    switch (encvid->enc_state)
+    {
+        case AVCEnc_Initializing:
+            return AVCENC_UNINITIALIZED;
+        case AVCEnc_Encoding_SPS:
+            /* initialized the structure */
+            BitstreamEncInit(bitstream, buffer, *buf_nal_size, NULL, 0);
+            BitstreamWriteBits(bitstream, 8, (1 << 5) | AVC_NALTYPE_SPS);
+
+            /* encode SPS */
+            status = EncodeSPS(encvid, bitstream);
+            if (status != AVCENC_SUCCESS)
+            {
+                return status;
+            }
+
+            /* closing the NAL with trailing bits */
+            status = BitstreamTrailingBits(bitstream, buf_nal_size);
+            if (status == AVCENC_SUCCESS)
+            {
+                encvid->enc_state = AVCEnc_Encoding_PPS;
+                video->currPicParams->seq_parameter_set_id = video->currSeqParams->seq_parameter_set_id;
+                video->currPicParams->pic_parameter_set_id++;
+                *nal_type = AVC_NALTYPE_SPS;
+                *buf_nal_size = bitstream->write_pos;
+            }
+            break;
+        case AVCEnc_Encoding_PPS:
+            /* initialized the structure */
+            BitstreamEncInit(bitstream, buffer, *buf_nal_size, NULL, 0);
+            BitstreamWriteBits(bitstream, 8, (1 << 5) | AVC_NALTYPE_PPS);
+
+            /* encode PPS */
+            status = EncodePPS(encvid, bitstream);
+            if (status != AVCENC_SUCCESS)
+            {
+                return status;
+            }
+
+            /* closing the NAL with trailing bits */
+            status = BitstreamTrailingBits(bitstream, buf_nal_size);
+            if (status == AVCENC_SUCCESS)
+            {
+                if (encvid->outOfBandParamSet == TRUE) // already extract PPS, SPS
+                {
+                    encvid->enc_state = AVCEnc_Analyzing_Frame;
+                }
+                else    // SetInput has been called before SPS and PPS.
+                {
+                    encvid->enc_state = AVCEnc_Encoding_Frame;
+                }
+
+                *nal_type = AVC_NALTYPE_PPS;
+                *buf_nal_size = bitstream->write_pos;
+            }
+            break;
+
+        case AVCEnc_Encoding_Frame:
+            /* initialized the structure */
+            BitstreamEncInit(bitstream, buffer, *buf_nal_size, encvid->overrunBuffer, encvid->oBSize);
+            BitstreamWriteBits(bitstream, 8, (video->nal_ref_idc << 5) | (video->nal_unit_type));
+
+            /* Re-order the reference list according to the ref_pic_list_reordering() */
+            /* We don't have to reorder the list for the encoder here. This can only be done
+            after we encode this slice. We can run thru a second-pass to see if new ordering
+            would save more bits. Too much delay !! */
+            /* status = ReOrderList(video);*/
+            status = InitSlice(encvid);
+            if (status != AVCENC_SUCCESS)
+            {
+                return status;
+            }
+
+            /* when we have everything, we encode the slice header */
+            status = EncodeSliceHeader(encvid, bitstream);
+            if (status != AVCENC_SUCCESS)
+            {
+                return status;
+            }
+
+            status = AVCEncodeSlice(encvid);
+
+            video->slice_id++;
+
+            /* closing the NAL with trailing bits */
+            BitstreamTrailingBits(bitstream, buf_nal_size);
+
+            *buf_nal_size = bitstream->write_pos;
+
+            encvid->rateCtrl->numFrameBits += ((*buf_nal_size) << 3);
+
+            *nal_type = video->nal_unit_type;
+
+            if (status == AVCENC_PICTURE_READY)
+            {
+                status = RCUpdateFrame(encvid);
+                if (status == AVCENC_SKIPPED_PICTURE) /* skip current frame */
+                {
+                    DPBReleaseCurrentFrame(avcHandle, video);
+                    encvid->enc_state = AVCEnc_Analyzing_Frame;
+
+                    return status;
+                }
+
+                /* perform loop-filtering on the entire frame */
+                DeblockPicture(video);
+
+                /* update the original frame array */
+                encvid->prevCodedFrameNum = encvid->currInput->coding_order;
+
+                /* store the encoded picture in the DPB buffer */
+                StorePictureInDPB(avcHandle, video);
+
+                if (video->currPic->isReference)
+                {
+                    video->PrevRefFrameNum = video->sliceHdr->frame_num;
+                }
+
+                /* update POC related variables */
+                PostPOC(video);
+
+                encvid->enc_state = AVCEnc_Analyzing_Frame;
+                status = AVCENC_PICTURE_READY;
+
+            }
+            break;
+        default:
+            status = AVCENC_WRONG_STATE;
+    }
+
+    return status;
+}
+
+/* ======================================================================== */
+/*  Function : PVAVCEncGetOverrunBuffer()                                   */
+/*  Purpose  : To retrieve the overrun buffer. Check whether overrun buffer */
+/*              is used or not before returning                             */
+/*  In/out   :                                                              */
+/*  Return   : Pointer to the internal overrun buffer.                      */
+/*  Modified :                                                              */
+/* ======================================================================== */
+OSCL_EXPORT_REF uint8* PVAVCEncGetOverrunBuffer(AVCHandle* avcHandle)
+{
+    AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+    AVCEncBitstream *bitstream = encvid->bitstream;
+
+    if (bitstream->overrunBuffer == bitstream->bitstreamBuffer) /* OB is used */
+    {
+        return encvid->overrunBuffer;
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+
+/* ======================================================================== */
+/*  Function : PVAVCEncGetRecon()                                           */
+/*  Date     : 4/29/2004                                                    */
+/*  Purpose  : To retrieve the most recently encoded frame.                 */
+/*              assume that user will make a copy if they want to hold on   */
+/*              to it. Otherwise, it is not guaranteed to be reserved.      */
+/*              Most applications prefer to see original frame rather than  */
+/*              reconstructed frame. So, we are staying aware from complex  */
+/*              buffering mechanism. If needed, can be added later.         */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS for success.                                  */
+/*  Modified :                                                              */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncGetRecon(AVCHandle *avcHandle, AVCFrameIO *recon)
+{
+    AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+    AVCCommonObj *video = encvid->common;
+    AVCFrameStore *currFS = video->currFS;
+
+    if (encvid == NULL)
+    {
+        return AVCENC_UNINITIALIZED;
+    }
+
+    recon->YCbCr[0] = currFS->frame.Sl;
+    recon->YCbCr[1] = currFS->frame.Scb;
+    recon->YCbCr[2] = currFS->frame.Scr;
+    recon->height = currFS->frame.height;
+    recon->pitch = currFS->frame.pitch;
+    recon->disp_order = currFS->PicOrderCnt;
+    recon->coding_order = currFS->FrameNum;
+    recon->id = (uint32) currFS->base_dpb; /* use the pointer as the id */
+
+    currFS->IsOutputted |= 1;
+
+    return AVCENC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncReleaseRecon(AVCHandle *avcHandle, AVCFrameIO *recon)
+{
+    OSCL_UNUSED_ARG(avcHandle);
+    OSCL_UNUSED_ARG(recon);
+
+    return AVCENC_SUCCESS; //for now
+}
+
+/* ======================================================================== */
+/*  Function : PVAVCCleanUpEncoder()                                        */
+/*  Date     : 4/18/2004                                                    */
+/*  Purpose  : To clean up memories allocated by PVAVCEncInitialize()       */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS for success.                                  */
+/*  Modified :                                                              */
+/* ======================================================================== */
+OSCL_EXPORT_REF void    PVAVCCleanUpEncoder(AVCHandle *avcHandle)
+{
+    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+    AVCCommonObj *video;
+    uint32 *userData = (uint32*) avcHandle->userData;
+
+    if (encvid != NULL)
+    {
+        CleanMotionSearchModule(avcHandle);
+
+        CleanupRateControlModule(avcHandle);
+
+        if (encvid->functionPointer != NULL)
+        {
+            avcHandle->CBAVC_Free(userData, (int)encvid->functionPointer);
+        }
+
+        if (encvid->min_cost)
+        {
+            avcHandle->CBAVC_Free(userData, (int)encvid->min_cost);
+        }
+
+        if (encvid->intraSearch)
+        {
+            avcHandle->CBAVC_Free(userData, (int)encvid->intraSearch);
+        }
+
+        if (encvid->mot16x16)
+        {
+            avcHandle->CBAVC_Free(userData, (int)encvid->mot16x16);
+        }
+
+        if (encvid->rateCtrl)
+        {
+            avcHandle->CBAVC_Free(userData, (int)encvid->rateCtrl);
+        }
+
+        if (encvid->overrunBuffer)
+        {
+            avcHandle->CBAVC_Free(userData, (int)encvid->overrunBuffer);
+        }
+
+        video = encvid->common;
+        if (video != NULL)
+        {
+            if (video->MbToSliceGroupMap)
+            {
+                avcHandle->CBAVC_Free(userData, (int)video->MbToSliceGroupMap);
+            }
+            if (video->mblock != NULL)
+            {
+                avcHandle->CBAVC_Free(userData, (int)video->mblock);
+            }
+            if (video->decPicBuf != NULL)
+            {
+                CleanUpDPB(avcHandle, video);
+                avcHandle->CBAVC_Free(userData, (int)video->decPicBuf);
+            }
+            if (video->sliceHdr != NULL)
+            {
+                avcHandle->CBAVC_Free(userData, (int)video->sliceHdr);
+            }
+            if (video->currPicParams != NULL)
+            {
+                if (video->currPicParams->slice_group_id)
+                {
+                    avcHandle->CBAVC_Free(userData, (int)video->currPicParams->slice_group_id);
+                }
+
+                avcHandle->CBAVC_Free(userData, (int)video->currPicParams);
+            }
+            if (video->currSeqParams != NULL)
+            {
+                avcHandle->CBAVC_Free(userData, (int)video->currSeqParams);
+            }
+            if (encvid->bitstream != NULL)
+            {
+                avcHandle->CBAVC_Free(userData, (int)encvid->bitstream);
+            }
+            if (video != NULL)
+            {
+                avcHandle->CBAVC_Free(userData, (int)video);
+            }
+        }
+
+        avcHandle->CBAVC_Free(userData, (int)encvid);
+
+        avcHandle->AVCObject = NULL;
+    }
+
+    return ;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncUpdateBitRate(AVCHandle *avcHandle, uint32 bitrate)
+{
+    OSCL_UNUSED_ARG(avcHandle);
+    OSCL_UNUSED_ARG(bitrate);
+
+    return AVCENC_FAIL;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncUpdateFrameRate(AVCHandle *avcHandle, uint32 num, uint32 denom)
+{
+    OSCL_UNUSED_ARG(avcHandle);
+    OSCL_UNUSED_ARG(num);
+    OSCL_UNUSED_ARG(denom);
+
+    return AVCENC_FAIL;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncUpdateIDRInterval(AVCHandle *avcHandle, int IDRInterval)
+{
+    OSCL_UNUSED_ARG(avcHandle);
+    OSCL_UNUSED_ARG(IDRInterval);
+
+    return AVCENC_FAIL;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncIDRRequest(AVCHandle *avcHandle)
+{
+    OSCL_UNUSED_ARG(avcHandle);
+
+    return AVCENC_FAIL;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncUpdateIMBRefresh(AVCHandle *avcHandle, int numMB)
+{
+    OSCL_UNUSED_ARG(avcHandle);
+    OSCL_UNUSED_ARG(numMB);
+
+    return AVCENC_FAIL;
+}
+
+void PVAVCEncGetFrameStats(AVCHandle *avcHandle, AVCEncFrameStats *avcStats)
+{
+    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+
+    avcStats->avgFrameQP = GetAvgFrameQP(rateCtrl);
+    avcStats->numIntraMBs = encvid->numIntraMB;
+
+    return ;
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/avcenc_api.h b/media/libstagefright/codecs/avc/enc/src/avcenc_api.h
new file mode 100644
index 0000000..6841ec3
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/avcenc_api.h
@@ -0,0 +1,323 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains application function interfaces to the AVC encoder library
+and necessary type defitionitions and enumerations.
+@publishedAll
+*/
+
+#ifndef AVCENC_API_H_INCLUDED
+#define AVCENC_API_H_INCLUDED
+
+#ifndef AVCAPI_COMMON_H_INCLUDED
+#include "avcapi_common.h"
+#endif
+
+// For memset, etc
+#include <string.h>
+
+/**
+ This enumeration is used for the status returned from the library interface.
+*/
+typedef enum
+{
+    /**
+    Fail information, need to add more error code for more specific info
+    */
+    AVCENC_TRAILINGONES_FAIL = -35,
+    AVCENC_SLICE_EMPTY = -34,
+    AVCENC_POC_FAIL = -33,
+    AVCENC_CONSECUTIVE_NONREF = -32,
+    AVCENC_CABAC_FAIL = -31,
+    AVCENC_PRED_WEIGHT_TAB_FAIL = -30,
+    AVCENC_DEC_REF_PIC_MARK_FAIL = -29,
+    AVCENC_SPS_FAIL = -28,
+    AVCENC_BITSTREAM_BUFFER_FULL    = -27,
+    AVCENC_BITSTREAM_INIT_FAIL = -26,
+    AVCENC_CHROMA_QP_FAIL = -25,
+    AVCENC_INIT_QS_FAIL = -24,
+    AVCENC_INIT_QP_FAIL = -23,
+    AVCENC_WEIGHTED_BIPRED_FAIL = -22,
+    AVCENC_INVALID_INTRA_PERIOD = -21,
+    AVCENC_INVALID_CHANGE_RATE = -20,
+    AVCENC_INVALID_BETA_OFFSET = -19,
+    AVCENC_INVALID_ALPHA_OFFSET = -18,
+    AVCENC_INVALID_DEBLOCK_IDC = -17,
+    AVCENC_INVALID_REDUNDANT_PIC = -16,
+    AVCENC_INVALID_FRAMERATE = -15,
+    AVCENC_INVALID_NUM_SLICEGROUP = -14,
+    AVCENC_INVALID_POC_LSB = -13,
+    AVCENC_INVALID_NUM_REF = -12,
+    AVCENC_INVALID_FMO_TYPE = -11,
+    AVCENC_ENCPARAM_MEM_FAIL = -10,
+    AVCENC_LEVEL_NOT_SUPPORTED = -9,
+    AVCENC_LEVEL_FAIL = -8,
+    AVCENC_PROFILE_NOT_SUPPORTED = -7,
+    AVCENC_TOOLS_NOT_SUPPORTED = -6,
+    AVCENC_WRONG_STATE = -5,
+    AVCENC_UNINITIALIZED = -4,
+    AVCENC_ALREADY_INITIALIZED = -3,
+    AVCENC_NOT_SUPPORTED = -2,
+    AVCENC_MEMORY_FAIL = AVC_MEMORY_FAIL,
+    AVCENC_FAIL = AVC_FAIL,
+    /**
+    Generic success value
+    */
+    AVCENC_SUCCESS = AVC_SUCCESS,
+    AVCENC_PICTURE_READY = 2,
+    AVCENC_NEW_IDR = 3, /* upon getting this, users have to call PVAVCEncodeSPS and PVAVCEncodePPS to get a new SPS and PPS*/
+    AVCENC_SKIPPED_PICTURE = 4 /* continuable error message */
+
+} AVCEnc_Status;
+
+#define MAX_NUM_SLICE_GROUP  8      /* maximum for all the profiles */
+
+/**
+This structure contains the encoding parameters.
+*/
+typedef struct tagAVCEncParam
+{
+    /* if profile/level is set to zero, encoder will choose the closest one for you */
+    AVCProfile profile; /* profile of the bitstream to be compliant with*/
+    AVCLevel   level;   /* level of the bitstream to be compliant with*/
+
+    int width;      /* width of an input frame in pixel */
+    int height;     /* height of an input frame in pixel */
+
+    int poc_type; /* picture order count mode, 0,1 or 2 */
+    /* for poc_type == 0 */
+    uint log2_max_poc_lsb_minus_4; /* specify maximum value of POC Lsb, range 0..12*/
+    /* for poc_type == 1 */
+    uint delta_poc_zero_flag; /* delta POC always zero */
+    int offset_poc_non_ref; /* offset for non-reference pic */
+    int offset_top_bottom; /* offset between top and bottom field */
+    uint num_ref_in_cycle; /* number of reference frame in one cycle */
+    int *offset_poc_ref; /* array of offset for ref pic, dimension [num_ref_in_cycle] */
+
+    int num_ref_frame;  /* number of reference frame used */
+    int num_slice_group;  /* number of slice group */
+    int fmo_type;   /* 0: interleave, 1: dispersed, 2: foreground with left-over
+                    3: box-out, 4:raster scan, 5:wipe, 6:explicit */
+    /* for fmo_type == 0 */
+    uint run_length_minus1[MAX_NUM_SLICE_GROUP];   /* array of size num_slice_group, in round robin fasion */
+    /* fmo_type == 2*/
+    uint top_left[MAX_NUM_SLICE_GROUP-1];           /* array of co-ordinates of each slice_group */
+    uint bottom_right[MAX_NUM_SLICE_GROUP-1];       /* except the last one which is the background. */
+    /* fmo_type == 3,4,5 */
+    AVCFlag change_dir_flag;  /* slice group change direction flag */
+    uint change_rate_minus1;
+    /* fmo_type == 6 */
+    uint *slice_group; /* array of size MBWidth*MBHeight */
+
+    AVCFlag db_filter;  /* enable deblocking loop filter */
+    int disable_db_idc;  /* 0: filter everywhere, 1: no filter, 2: no filter across slice boundary */
+    int alpha_offset;   /* alpha offset range -6,...,6 */
+    int beta_offset;    /* beta offset range -6,...,6 */
+
+    AVCFlag constrained_intra_pred; /* constrained intra prediction flag */
+
+    AVCFlag auto_scd;   /* scene change detection on or off */
+    int idr_period; /* idr frame refresh rate in number of target encoded frame (no concept of actual time).*/
+    int intramb_refresh;    /* minimum number of intra MB per frame */
+    AVCFlag data_par;   /* enable data partitioning */
+
+    AVCFlag fullsearch; /* enable full-pel full-search mode */
+    int search_range;   /* search range for motion vector in (-search_range,+search_range) pixels */
+    AVCFlag sub_pel;    /* enable sub pel prediction */
+    AVCFlag submb_pred; /* enable sub MB partition mode */
+    AVCFlag rdopt_mode; /* RD optimal mode selection */
+    AVCFlag bidir_pred; /* enable bi-directional for B-slice, this flag forces the encoder to encode
+                        any frame with POC less than the previously encoded frame as a B-frame.
+                        If it's off, then such frames will remain P-frame. */
+
+    AVCFlag rate_control; /* rate control enable, on: RC on, off: constant QP */
+    int initQP;     /* initial QP */
+    uint32 bitrate;    /* target encoding bit rate in bits/second */
+    uint32 CPB_size;  /* coded picture buffer in number of bits */
+    uint32 init_CBP_removal_delay; /* initial CBP removal delay in msec */
+
+    uint32 frame_rate;  /* frame rate in the unit of frames per 1000 second */
+    /* note, frame rate is only needed by the rate control, AVC is timestamp agnostic. */
+
+    AVCFlag out_of_band_param_set; /* flag to set whether param sets are to be retrieved up front or not */
+
+    AVCFlag use_overrun_buffer;  /* do not throw away the frame if output buffer is not big enough.
+                                    copy excess bits to the overrun buffer */
+} AVCEncParams;
+
+
+/**
+This structure contains current frame encoding statistics for debugging purpose.
+*/
+typedef struct tagAVCEncFrameStats
+{
+    int avgFrameQP;   /* average frame QP */
+    int numIntraMBs;  /* number of intra MBs */
+    int numFalseAlarm;
+    int numMisDetected;
+    int numDetected;
+
+} AVCEncFrameStats;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    /** THE FOLLOWINGS ARE APIS */
+    /**
+    This function initializes the encoder library. It verifies the validity of the
+    encoding parameters against the specified profile/level and the list of supported
+    tools by this library. It allocates necessary memories required to perform encoding.
+    For re-encoding application, if users want to setup encoder in a more precise way,
+    users can give the external SPS and PPS to the encoder to follow.
+    \param "avcHandle"  "Handle to the AVC encoder library object."
+    \param "encParam"   "Pointer to the encoding parameter structure."
+    \param "extSPS"     "External SPS used for re-encoding purpose. NULL if not present"
+    \param "extPPS"     "External PPS used for re-encoding purpose. NULL if not present"
+    \return "AVCENC_SUCCESS for success,
+             AVCENC_NOT_SUPPORTED for the use of unsupported tools,
+             AVCENC_MEMORY_FAIL for memory allocation failure,
+             AVCENC_FAIL for generic failure."
+    */
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncInitialize(AVCHandle *avcHandle, AVCEncParams *encParam, void* extSPS, void* extPPS);
+
+
+    /**
+    Since the output buffer size is not known prior to encoding a frame, users need to
+    allocate big enough buffer otherwise, that frame will be dropped. This function returns
+    the size of the output buffer to be allocated by the users that guarantees to hold one frame.
+    It follows the CPB spec for a particular level.  However, when the users set use_overrun_buffer
+    flag, this API is useless as excess output bits are saved in the overrun buffer waiting to be
+    copied out in small chunks, i.e. users can allocate any size of output buffer.
+    \param "avcHandle"  "Handle to the AVC encoder library object."
+    \param "size"   "Pointer to the size to be modified."
+    \return "AVCENC_SUCCESS for success, AVCENC_UNINITIALIZED when level is not known.
+    */
+
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncGetMaxOutputBufferSize(AVCHandle *avcHandle, int* size);
+
+    /**
+    Users call this function to provide an input structure to the encoder library which will keep
+    a list of input structures it receives in case the users call this function many time before
+    calling PVAVCEncodeSlice. The encoder library will encode them according to the frame_num order.
+    Users should not modify the content of a particular frame until this frame is encoded and
+    returned thru CBAVCEnc_ReturnInput() callback function.
+    \param "avcHandle"  "Handle to the AVC encoder library object."
+    \param "input"      "Pointer to the input structure."
+    \return "AVCENC_SUCCESS for success,
+            AVCENC_FAIL if the encoder is not in the right state to take a new input frame.
+            AVCENC_NEW_IDR for the detection or determination of a new IDR, with this status,
+            the returned NAL is an SPS NAL,
+            AVCENC_NO_PICTURE if the input frame coding timestamp is too early, users must
+            get next frame or adjust the coding timestamp."
+    */
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncSetInput(AVCHandle *avcHandle, AVCFrameIO *input);
+
+    /**
+    This function is called to encode a NAL unit which can be an SPS NAL, a PPS NAL or
+    a VCL (video coding layer) NAL which contains one slice of data. It could be a
+    fixed number of macroblocks, as specified in the encoder parameters set, or the
+    maximum number of macroblocks fitted into the given input argument "buffer". The
+    input frame is taken from the oldest unencoded input frame retrieved by users by
+    PVAVCEncGetInput API.
+    \param "avcHandle"  "Handle to the AVC encoder library object."
+    \param "buffer"     "Pointer to the output AVC bitstream buffer, the format will be EBSP,
+                         not RBSP."
+    \param "buf_nal_size"   "As input, the size of the buffer in bytes.
+                        This is the physical limitation of the buffer. As output, the size of the EBSP."
+    \param "nal_type"   "Pointer to the NAL type of the returned buffer."
+    \return "AVCENC_SUCCESS for success of encoding one slice,
+             AVCENC_PICTURE_READY for the completion of a frame encoding,
+             AVCENC_FAIL for failure (this should not occur, though)."
+    */
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncodeNAL(AVCHandle *avcHandle, uint8 *buffer, uint *buf_nal_size, int *nal_type);
+
+    /**
+    This function sniffs the nal_unit_type such that users can call corresponding APIs.
+    This function is identical to PVAVCDecGetNALType() in the decoder.
+    \param "bitstream"  "Pointer to the beginning of a NAL unit (start with forbidden_zero_bit, etc.)."
+    \param "size"       "size of the bitstream (NumBytesInNALunit + 1)."
+    \param "nal_unit_type" "Pointer to the return value of nal unit type."
+    \return "AVCENC_SUCCESS if success, AVCENC_FAIL otherwise."
+    */
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncGetNALType(uint8 *bitstream, int size, int *nal_type, int *nal_ref_idc);
+
+    /**
+    This function returns the pointer to internal overrun buffer. Users can call this to query
+    whether the overrun buffer has been used to encode the current NAL.
+    \param "avcHandle"  "Pointer to the handle."
+    \return "Pointer to overrun buffer if it is used, otherwise, NULL."
+    */
+    OSCL_IMPORT_REF uint8* PVAVCEncGetOverrunBuffer(AVCHandle* avcHandle);
+
+    /**
+    This function returns the reconstructed frame of the most recently encoded frame.
+    Note that this frame is not returned to the users yet. Users should only read the
+    content of this frame.
+    \param "avcHandle"  "Handle to the AVC encoder library object."
+    \param "output"     "Pointer to the input structure."
+    \return "AVCENC_SUCCESS for success, AVCENC_NO_PICTURE if no picture to be outputted."
+    */
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncGetRecon(AVCHandle *avcHandle, AVCFrameIO *recon);
+
+    /**
+    This function is used to return the recontructed frame back to the AVC encoder library
+    in order to be re-used for encoding operation. If users want the content of it to remain
+    unchanged for a long time, they should make a copy of it and release the memory back to
+    the encoder. The encoder relies on the id element in the AVCFrameIO structure,
+    thus users should not change the id value.
+    \param "avcHandle"  "Handle to the AVC decoder library object."
+    \param "output"      "Pointer to the AVCFrameIO structure."
+    \return "AVCENC_SUCCESS for success, AVCENC_FAIL for fail for id not found."
+    */
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncReleaseRecon(AVCHandle *avcHandle, AVCFrameIO *recon);
+
+    /**
+    This function performs clean up operation including memory deallocation.
+    The encoder will also clear the list of input structures it has not released.
+    This implies that users must keep track of the number of input structure they have allocated
+    and free them accordingly.
+    \param "avcHandle"  "Handle to the AVC encoder library object."
+    */
+    OSCL_IMPORT_REF void    PVAVCCleanUpEncoder(AVCHandle *avcHandle);
+
+    /**
+    This function extracts statistics of the current frame. If the encoder has not finished
+    with the current frame, the result is not accurate.
+    \param "avcHandle"  "Handle to the AVC encoder library object."
+    \param "avcStats"   "Pointer to AVCEncFrameStats structure."
+    \return "void."
+    */
+    void PVAVCEncGetFrameStats(AVCHandle *avcHandle, AVCEncFrameStats *avcStats);
+
+    /**
+    These functions are used for the modification of encoding parameters.
+    To be polished.
+    */
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncUpdateBitRate(AVCHandle *avcHandle, uint32 bitrate);
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncUpdateFrameRate(AVCHandle *avcHandle, uint32 num, uint32 denom);
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncUpdateIDRInterval(AVCHandle *avcHandle, int IDRInterval);
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncIDRRequest(AVCHandle *avcHandle);
+    OSCL_IMPORT_REF AVCEnc_Status PVAVCEncUpdateIMBRefresh(AVCHandle *avcHandle, int numMB);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif  /* _AVCENC_API_H_ */
+
diff --git a/media/libstagefright/codecs/avc/enc/src/avcenc_int.h b/media/libstagefright/codecs/avc/enc/src/avcenc_int.h
new file mode 100644
index 0000000..3fe08a1
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/avcenc_int.h
@@ -0,0 +1,471 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains application function interfaces to the AVC encoder library
+and necessary type defitionitions and enumerations.
+@publishedAll
+*/
+
+#ifndef AVCENC_INT_H_INCLUDED
+#define AVCENC_INT_H_INCLUDED
+
+#ifndef AVCINT_COMMON_H_INCLUDED
+#include "avcint_common.h"
+#endif
+#ifndef AVCENC_API_H_INCLUDED
+#include "avcenc_api.h"
+#endif
+
+typedef float OsclFloat;
+
+/* Definition for the structures below */
+#define DEFAULT_ATTR    0 /* default memory attribute */
+#define MAX_INPUT_FRAME 30 /* some arbitrary number, it can be much higher than this. */
+#define MAX_REF_FRAME  16 /* max size of the RefPicList0 and RefPicList1 */
+#define MAX_REF_PIC_LIST 33
+
+#define MIN_QP          0
+#define MAX_QP          51
+#define SHIFT_QP        12
+#define  LAMBDA_ACCURACY_BITS         16
+#define  LAMBDA_FACTOR(lambda)        ((int)((double)(1<<LAMBDA_ACCURACY_BITS)*lambda+0.5))
+
+
+#define DISABLE_THRESHOLDING  0
+// for better R-D performance
+#define _LUMA_COEFF_COST_       4 //!< threshold for luma coeffs
+#define _CHROMA_COEFF_COST_     4 //!< threshold for chroma coeffs, used to be 7
+#define _LUMA_MB_COEFF_COST_    5 //!< threshold for luma coeffs of inter Macroblocks
+#define _LUMA_8x8_COEFF_COST_   5 //!< threshold for luma coeffs of 8x8 Inter Partition
+#define MAX_VALUE       999999   //!< used for start value for some variables
+
+#define  WEIGHTED_COST(factor,bits)   (((factor)*(bits))>>LAMBDA_ACCURACY_BITS)
+#define  MV_COST(f,s,cx,cy,px,py)     (WEIGHTED_COST(f,mvbits[((cx)<<(s))-px]+mvbits[((cy)<<(s))-py]))
+#define  MV_COST_S(f,cx,cy,px,py)     (WEIGHTED_COST(f,mvbits[cx-px]+mvbits[cy-py]))
+
+/* for sub-pel search and interpolation */
+#define SUBPEL_PRED_BLK_SIZE 576 // 24x24
+#define REF_CENTER 75
+#define V2Q_H0Q 1
+#define V0Q_H2Q 2
+#define V2Q_H2Q 3
+
+/*
+#define V3Q_H0Q 1
+#define V3Q_H1Q 2
+#define V0Q_H1Q 3
+#define V1Q_H1Q 4
+#define V1Q_H0Q 5
+#define V1Q_H3Q 6
+#define V0Q_H3Q 7
+#define V3Q_H3Q 8
+#define V2Q_H3Q 9
+#define V2Q_H0Q 10
+#define V2Q_H1Q 11
+#define V2Q_H2Q 12
+#define V3Q_H2Q 13
+#define V0Q_H2Q 14
+#define V1Q_H2Q 15
+*/
+
+
+#define DEFAULT_OVERRUN_BUFFER_SIZE 1000
+
+// associated with the above cost model
+const uint8 COEFF_COST[2][16] =
+{
+    {3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+    {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}
+};
+
+
+
+//! convert from H.263 QP to H.264 quant given by: quant=pow(2,QP/6)
+const int QP2QUANT[40] =
+{
+    1, 1, 1, 1, 2, 2, 2, 2,
+    3, 3, 3, 4, 4, 4, 5, 6,
+    6, 7, 8, 9, 10, 11, 13, 14,
+    16, 18, 20, 23, 25, 29, 32, 36,
+    40, 45, 51, 57, 64, 72, 81, 91
+};
+
+
+/**
+This enumeration keeps track of the internal status of the encoder whether it is doing
+something. The encoding flow follows the order in which these states are.
+@publishedAll
+*/
+typedef enum
+{
+    AVCEnc_Initializing = 0,
+    AVCEnc_Encoding_SPS,
+    AVCEnc_Encoding_PPS,
+    AVCEnc_Analyzing_Frame,
+    AVCEnc_WaitingForBuffer,  // pending state
+    AVCEnc_Encoding_Frame,
+} AVCEnc_State ;
+
+/**
+Bitstream structure contains bitstream related parameters such as the pointer
+to the buffer, the current byte position and bit position. The content of the
+bitstreamBuffer will be in EBSP format as the emulation prevention codes are
+automatically inserted as the RBSP is recorded.
+@publishedAll
+*/
+typedef struct tagEncBitstream
+{
+    uint8 *bitstreamBuffer; /* pointer to buffer memory   */
+    int buf_size;       /* size of the buffer memory */
+    int write_pos;      /* next position to write to bitstreamBuffer  */
+    int count_zeros;   /* count number of consecutive zero */
+    uint current_word;  /* byte-swapped (MSB left) current word to write to buffer */
+    int bit_left;      /* number of bit left in current_word */
+    uint8   *overrunBuffer;  /* extra output buffer to prevent current skip due to output buffer overrun*/
+    int     oBSize;     /* size of allocated overrun buffer */
+    void   *encvid; /* pointer to the main object */
+
+} AVCEncBitstream;
+
+/**
+This structure is used for rate control purpose and other performance related control
+variables such as, RD cost, statistics, motion search stuffs, etc.
+should be in this structure.
+@publishedAll
+*/
+
+
+typedef struct tagRDInfo
+{
+    int QP;
+    int actual_bits;
+    OsclFloat mad;
+    OsclFloat R_D;
+} RDInfo;
+
+typedef struct tagMultiPass
+{
+    /* multipass rate control data */
+    int target_bits;    /* target bits for current frame, = rc->T */
+    int actual_bits;    /* actual bits for current frame obtained after encoding, = rc->Rc*/
+    int QP;             /* quantization level for current frame, = rc->Qc*/
+    int prev_QP;        /* quantization level for previous frame */
+    int prev_prev_QP;   /* quantization level for previous frame before last*/
+    OsclFloat mad;          /* mad for current frame, = video->avgMAD*/
+    int bitrate;        /* bitrate for current frame */
+    OsclFloat framerate;    /* framerate for current frame*/
+
+    int nRe_Quantized;  /* control variable for multipass encoding, */
+    /* 0 : first pass */
+    /* 1 : intermediate pass(quantization and VLC loop only) */
+    /* 2 : final pass(de-quantization, idct, etc) */
+    /* 3 : macroblock level rate control */
+
+    int encoded_frames;     /* counter for all encoded frames */
+    int re_encoded_frames;  /* counter for all multipass encoded frames*/
+    int re_encoded_times;   /* counter for all times of multipass frame encoding */
+
+    /* Multiple frame prediction*/
+    RDInfo **pRDSamples;        /* pRDSamples[30][32], 30->30fps, 32 -> 5 bit quantizer, 32 candidates*/
+    int framePos;               /* specific position in previous multiple frames*/
+    int frameRange;             /* number of overall previous multiple frames */
+    int samplesPerFrame[30];    /* number of samples per frame, 30->30fps */
+
+    /* Bit allocation for scene change frames and high motion frames */
+    OsclFloat sum_mad;
+    int counter_BTsrc;  /* BT = Bit Transfer, bit transfer from low motion frames or less complicatedly compressed frames */
+    int counter_BTdst;  /* BT = Bit Transfer, bit transfer to scene change frames or high motion frames or more complicatedly compressed frames */
+    OsclFloat sum_QP;
+    int diff_counter;   /* diff_counter = -diff_counter_BTdst, or diff_counter_BTsrc */
+
+    /* For target bitrate or framerate update */
+    OsclFloat target_bits_per_frame;        /* = C = bitrate/framerate */
+    OsclFloat target_bits_per_frame_prev;   /* previous C */
+    OsclFloat aver_mad;                     /* so-far average mad could replace sum_mad */
+    OsclFloat aver_mad_prev;                /* previous average mad */
+    int   overlapped_win_size;          /* transition period of time */
+    int   encoded_frames_prev;          /* previous encoded_frames */
+} MultiPass;
+
+
+typedef struct tagdataPointArray
+{
+    int Qp;
+    int Rp;
+    OsclFloat Mp;   /* for MB-based RC */
+    struct tagdataPointArray *next;
+    struct tagdataPointArray *prev;
+} dataPointArray;
+
+typedef struct tagAVCRateControl
+{
+
+    /* these parameters are initialized by the users AVCEncParams */
+    /* bitrate-robustness tradeoff */
+    uint scdEnable; /* enable scene change detection */
+    int idrPeriod;  /* IDR period in number of frames */
+    int intraMBRate;   /* intra MB refresh rate per frame */
+    uint dpEnable;  /* enable data partitioning */
+
+    /* quality-complexity tradeoff */
+    uint subPelEnable;  /* enable quarter pel search */
+    int mvRange;    /* motion vector search range in +/- pixel */
+    uint subMBEnable;  /* enable sub MB prediction mode (4x4, 4x8, 8x4) */
+    uint rdOptEnable;  /* enable RD-opt mode selection */
+    uint twoPass; /* flag for 2 pass encoding ( for future )*/
+    uint bidirPred; /* bi-directional prediction for B-frame. */
+
+    uint rcEnable;  /* enable rate control, '1' on, '0' const QP */
+    int initQP; /* initial QP */
+
+    /* note the following 3 params are for HRD, these triplets can be a series
+    of triplets as the generalized HRD allows. SEI message must be generated in this case. */
+    /* We no longer have to differentiate between CBR and VBR. The users to the
+    AVC encoder lib will do the mapping from CBR/VBR to these parameters. */
+    int32 bitRate;  /* target bit rate for the overall clip in bits/second*/
+    int32 cpbSize;  /* coded picture buffer size in bytes */
+    int32 initDelayOffset; /* initial CBP removal delay in bits */
+
+    OsclFloat frame_rate; /* frame rate */
+    int srcInterval; /* source frame rate in msec */
+    int basicUnit;  /* number of macroblocks per BU */
+
+    /* Then internal parameters for the operation */
+    uint first_frame; /* a flag for the first frame */
+    int lambda_mf; /* for example */
+    int totalSAD;    /* SAD of current frame */
+
+    /*******************************************/
+    /* this part comes from MPEG4 rate control */
+    int alpha;  /* weight for I frame */
+    int Rs;     /*bit rate for the sequence (or segment) e.g., 24000 bits/sec */
+    int Rc;     /*bits used for the current frame. It is the bit count obtained after encoding. */
+    int Rp;     /*bits to be removed from the buffer per picture. */
+    /*? is this the average one, or just the bits coded for the previous frame */
+    int Rps;    /*bit to be removed from buffer per src frame */
+    OsclFloat Ts;   /*number of seconds for the sequence  (or segment). e.g., 10 sec */
+    OsclFloat Ep;
+    OsclFloat Ec;   /*mean absolute difference for the current frame after motion compensation.*/
+    /*If the macroblock is intra coded, the original spatial pixel values are summed.*/
+    int Qc;     /*quantization level used for the current frame. */
+    int Nr;     /*number of P frames remaining for encoding.*/
+    int Rr; /*number of bits remaining for encoding this sequence (or segment).*/
+    int Rr_Old;
+    int T;      /*target bit to be used for the current frame.*/
+    int S;      /*number of bits used for encoding the previous frame.*/
+    int Hc; /*header and motion vector bits used in the current frame. It includes all the  information except to the residual information.*/
+    int Hp; /*header and motion vector bits used in the previous frame. It includes all the     information except to the residual information.*/
+    int Ql; /*quantization level used in the previous frame */
+    int Bs; /*buffer size e.g., R/2 */
+    int B;      /*current buffer level e.g., R/4 - start from the middle of the buffer */
+    OsclFloat X1;
+    OsclFloat X2;
+    OsclFloat X11;
+    OsclFloat M;            /*safe margin for the buffer */
+    OsclFloat smTick;    /*ratio of src versus enc frame rate */
+    double remnant;  /*remainder frame of src/enc frame for fine frame skipping */
+    int timeIncRes; /* vol->timeIncrementResolution */
+
+    dataPointArray   *end; /*quantization levels for the past (20) frames */
+
+    int     frameNumber; /* ranging from 0 to 20 nodes*/
+    int     w;
+    int     Nr_Original;
+    int     Nr_Old, Nr_Old2;
+    int     skip_next_frame;
+    int     Qdep;       /* smooth Q adjustment */
+    int     VBR_Enabled;
+
+    int totalFrameNumber; /* total coded frames, for debugging!!*/
+
+    char    oFirstTime;
+
+    int numFrameBits; /* keep track of number of bits of the current frame */
+    int NumberofHeaderBits;
+    int NumberofTextureBits;
+    int numMBHeaderBits;
+    int numMBTextureBits;
+    double *MADofMB;
+    int32 bitsPerFrame;
+
+    /* BX rate control, something like TMN8 rate control*/
+
+    MultiPass *pMP;
+
+    int     TMN_W;
+    int     TMN_TH;
+    int     VBV_fullness;
+    int     max_BitVariance_num; /* the number of the maximum bit variance within the given buffer with the unit of 10% of bitrate/framerate*/
+    int     encoded_frames; /* counter for all encoded frames */
+    int     low_bound;              /* bound for underflow detection, usually low_bound=-Bs/2, but could be changed in H.263 mode */
+    int     VBV_fullness_offset;    /* offset of VBV_fullness, usually is zero, but can be changed in H.263 mode*/
+    /* End BX */
+
+} AVCRateControl;
+
+
+/**
+This structure is for the motion vector information. */
+typedef struct tagMV
+{
+    int x;
+    int y;
+    uint sad;
+} AVCMV;
+
+/**
+This structure contains function pointers for different platform dependent implementation of
+functions. */
+typedef struct tagAVCEncFuncPtr
+{
+
+    int (*SAD_MB_HalfPel[4])(uint8*, uint8*, int, void *);
+    int (*SAD_Macroblock)(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+
+} AVCEncFuncPtr;
+
+/**
+This structure contains information necessary for correct padding.
+*/
+typedef struct tagPadInfo
+{
+    int i;
+    int width;
+    int j;
+    int height;
+} AVCPadInfo;
+
+
+#ifdef HTFM
+typedef struct tagHTFM_Stat
+{
+    int abs_dif_mad_avg;
+    uint countbreak;
+    int offsetArray[16];
+    int offsetRef[16];
+} HTFM_Stat;
+#endif
+
+
+/**
+This structure is the main object for AVC encoder library providing access to all
+global variables. It is allocated at PVAVCInitEncoder and freed at PVAVCCleanUpEncoder.
+@publishedAll
+*/
+typedef struct tagEncObject
+{
+
+    AVCCommonObj *common;
+
+    AVCEncBitstream     *bitstream; /* for current NAL */
+    uint8   *overrunBuffer;  /* extra output buffer to prevent current skip due to output buffer overrun*/
+    int     oBSize;     /* size of allocated overrun buffer */
+
+    /* rate control */
+    AVCRateControl      *rateCtrl; /* pointer to the rate control structure */
+
+    /* encoding operation */
+    AVCEnc_State        enc_state; /* encoding state */
+
+    AVCFrameIO          *currInput; /* pointer to the current input frame */
+
+    int                 currSliceGroup; /* currently encoded slice group id */
+
+    int     level[24][16], run[24][16]; /* scratch memory */
+    int     leveldc[16], rundc[16]; /* for DC component */
+    int     levelcdc[16], runcdc[16]; /* for chroma DC component */
+    int     numcoefcdc[2]; /* number of coefficient for chroma DC */
+    int     numcoefdc;      /* number of coefficients for DC component */
+
+    int     qp_const;
+    int     qp_const_c;
+    /********* intra prediction scratch memory **********************/
+    uint8   pred_i16[AVCNumI16PredMode][256]; /* save prediction for MB */
+    uint8   pred_i4[AVCNumI4PredMode][16];  /* save prediction for blk */
+    uint8   pred_ic[AVCNumIChromaMode][128];  /* for 2 chroma */
+
+    int     mostProbableI4Mode[16]; /* in raster scan order */
+    /********* motion compensation related variables ****************/
+    AVCMV   *mot16x16;          /* Saved motion vectors for 16x16 block*/
+    AVCMV(*mot16x8)[2];     /* Saved motion vectors for 16x8 block*/
+    AVCMV(*mot8x16)[2];     /* Saved motion vectors for 8x16 block*/
+    AVCMV(*mot8x8)[4];      /* Saved motion vectors for 8x8 block*/
+
+    /********* subpel position **************************************/
+    uint32  subpel_pred[SUBPEL_PRED_BLK_SIZE/*<<2*/]; /* all 16 sub-pel positions  */
+    uint8   *hpel_cand[9];      /* pointer to half-pel position */
+    int     best_hpel_pos;          /* best position */
+    uint8   qpel_cand[8][24*16];        /* pointer to quarter-pel position */
+    int     best_qpel_pos;
+    uint8   *bilin_base[9][4];    /* pointer to 4 position at top left of bilinear quarter-pel */
+
+    /* need for intra refresh rate */
+    uint8   *intraSearch;       /* Intra Array for MBs to be intra searched */
+    uint    firstIntraRefreshMBIndx; /* keep track for intra refresh */
+
+    int     i4_sad;             /* temporary for i4 mode SAD */
+    int     *min_cost;          /* Minimum cost for the all MBs */
+    int     lambda_mode;        /* Lagrange parameter for mode selection */
+    int     lambda_motion;      /* Lagrange parameter for MV selection */
+
+    uint8   *mvbits_array;      /* Table for bits spent in the cost funciton */
+    uint8   *mvbits;            /* An offset to the above array. */
+
+    /* to speedup the SAD calculation */
+    void *sad_extra_info;
+    uint8 currYMB[256];     /* interleaved current macroblock in HTFM order */
+
+#ifdef HTFM
+    int nrmlz_th[48];       /* Threshold for fast SAD calculation using HTFM */
+    HTFM_Stat htfm_stat;    /* For statistics collection */
+#endif
+
+    /* statistics */
+    int numIntraMB;         /* keep track of number of intra MB */
+
+    /* encoding complexity control */
+    uint fullsearch_enable; /* flag to enable full-pel full-search */
+
+    /* misc.*/
+    bool outOfBandParamSet; /* flag to enable out-of-band param set */
+
+    AVCSeqParamSet extSPS; /* for external SPS */
+    AVCPicParamSet extPPS; /* for external PPS */
+
+    /* time control */
+    uint32  prevFrameNum;   /* previous frame number starting from modTimeRef */
+    uint32  modTimeRef;     /* Reference modTime update every I-Vop*/
+    uint32  wrapModTime;    /* Offset to modTime Ref, rarely used */
+
+    uint    prevProcFrameNum;  /* previously processed frame number, could be skipped */
+    uint    prevCodedFrameNum;  /* previously encoded frame number */
+    /* POC related variables */
+    uint32  dispOrdPOCRef;      /* reference POC is displayer order unit. */
+
+    /* Function pointers */
+    AVCEncFuncPtr *functionPointer; /* store pointers to platform specific functions */
+
+    /* Application control data */
+    AVCHandle *avcHandle;
+
+
+} AVCEncObject;
+
+
+#endif /*AVCENC_INT_H_INCLUDED*/
+
diff --git a/media/libstagefright/codecs/avc/enc/src/avcenc_lib.h b/media/libstagefright/codecs/avc/enc/src/avcenc_lib.h
new file mode 100644
index 0000000..17e28ef
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/avcenc_lib.h
@@ -0,0 +1,1020 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains declarations of internal functions for AVC decoder library.
+@publishedAll
+*/
+#ifndef AVCENC_LIB_H_INCLUDED
+#define AVCENC_LIB_H_INCLUDED
+
+#ifndef AVCLIB_COMMON_H_INCLUDED
+#include "avclib_common.h"
+#endif
+#ifndef AVCENC_INT_H_INCLUDED
+#include "avcenc_int.h"
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    /*------------- block.c -------------------------*/
+
+    /**
+    This function perform residue calculation, transform, quantize, inverse quantize,
+    inverse transform and residue compensation on a 4x4 block.
+    \param "encvid" "Pointer to AVCEncObject."
+    \param "blkidx"  "raster scan block index of the current 4x4 block."
+    \param "cur"    "Pointer to the reconstructed block."
+    \param "org"    "Pointer to the original block."
+    \param "coef_cost"  "Pointer to the coefficient cost to be filled in and returned."
+    \return "Number of non-zero coefficients."
+    */
+    int dct_luma(AVCEncObject *encvid, int blkidx, uint8 *cur, uint8 *org, int *coef_cost);
+
+    /**
+    This function performs IDCT on an INTER macroblock.
+    \param "video"  "Pointer to AVCCommonObj."
+    \param "curL"   "Pointer to the origin of the macroblock on the current frame."
+    \param "currMB" "Pointer to the AVCMacroblock structure."
+    \param "picPitch" "Pitch of the current frame."
+    \return "void".
+    */
+    void MBInterIdct(AVCCommonObj *video, uint8 *curL, AVCMacroblock *currMB, int picPitch);
+
+    /**
+    This function perform residue calculation, transform, quantize, inverse quantize,
+    inverse transform and residue compensation on a macroblock.
+    \param "encvid" "Pointer to AVCEncObject."
+    \param "curL"   "Pointer to the reconstructed MB."
+    \param "orgL"    "Pointer to the original MB."
+    \return "void"
+    */
+    void dct_luma_16x16(AVCEncObject *encvid, uint8 *curL, uint8 *orgL);
+
+    /**
+    This function perform residue calculation, transform, quantize, inverse quantize,
+    inverse transform and residue compensation for chroma components of an MB.
+    \param "encvid" "Pointer to AVCEncObject."
+    \param "curC"   "Pointer to the reconstructed MB."
+    \param "orgC"    "Pointer to the original MB."
+    \param "cr"     "Flag whether it is Cr or not."
+    \return "void"
+    */
+    void dct_chroma(AVCEncObject *encvid, uint8 *curC, uint8 *orgC, int cr);
+
+    /*----------- init.c ------------------*/
+    /**
+    This function interprets the encoding parameters provided by users in encParam.
+    The results are kept in AVCEncObject, AVCSeqParamSet, AVCPicParamSet and AVCSliceHeader.
+    \param "encvid"     "Pointer to AVCEncObject."
+    \param "encParam"   "Pointer to AVCEncParam."
+    \param "extSPS"     "External SPS template to be followed. NULL if not present."
+    \param "extPPS"     "External PPS template to be followed. NULL if not present."
+    \return "see AVCEnc_Status."
+    */
+    AVCEnc_Status  SetEncodeParam(AVCHandle *avcHandle, AVCEncParams *encParam,
+                                  void *extSPS, void *extPPS);
+
+    /**
+    This function verifies the encoding parameters whether they meet the set of supported
+    tool by a specific profile. If the profile is not set, it will just find the closest
+    profile instead of verifying it.
+    \param "video"  "Pointer to AVCEncObject."
+    \param "seqParam"   "Pointer to AVCSeqParamSet."
+    \param "picParam"   "Pointer to AVCPicParamSet."
+    \return "AVCENC_SUCCESS if success,
+            AVCENC_PROFILE_NOT_SUPPORTED if the specified profile
+                is not supported by this version of the library,
+            AVCENC_TOOLS_NOT_SUPPORTED if any of the specified encoding tools are
+            not supported by the user-selected profile."
+    */
+    AVCEnc_Status VerifyProfile(AVCEncObject *video, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam);
+
+    /**
+    This function verifies the encoding parameters whether they meet the requirement
+    for a specific level. If the level is not set, it will just find the closest
+    level instead of verifying it.
+    \param "video"  "Pointer to AVCEncObject."
+    \param "seqParam"   "Pointer to AVCSeqParamSet."
+    \param "picParam"   "Pointer to AVCPicParamSet."
+    \return "AVCENC_SUCCESS if success,
+            AVCENC_LEVEL_NOT_SUPPORTED if the specified level
+                is not supported by this version of the library,
+            AVCENC_LEVEL_FAIL if any of the encoding parameters exceed
+            the range of the user-selected level."
+    */
+    AVCEnc_Status VerifyLevel(AVCEncObject *video, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam);
+
+    /**
+    This funciton initializes the frame encoding by setting poc/frame_num related parameters. it
+    also performs motion estimation.
+    \param "encvid" "Pointer to the AVCEncObject."
+    \return "AVCENC_SUCCESS if success, AVCENC_NO_PICTURE if there is no input picture
+            in the queue to encode, AVCENC_POC_FAIL or AVCENC_CONSECUTIVE_NONREF for POC
+            related errors, AVCENC_NEW_IDR if new IDR is detected."
+    */
+    AVCEnc_Status InitFrame(AVCEncObject *encvid);
+
+    /**
+    This function initializes slice header related variables and other variables necessary
+    for decoding one slice.
+    \param "encvid" "Pointer to the AVCEncObject."
+    \return "AVCENC_SUCCESS if success."
+    */
+    AVCEnc_Status InitSlice(AVCEncObject *encvid);
+
+    /*----------- header.c ----------------*/
+    /**
+    This function performs bitstream encoding of the sequence parameter set NAL.
+    \param "encvid" "Pointer to the AVCEncObject."
+    \param "stream" "Pointer to AVCEncBitstream."
+    \return "AVCENC_SUCCESS if success or AVCENC_SPS_FAIL or others for unexpected failure which
+    should not occur. The SPS parameters should all be verified before this function is called."
+    */
+    AVCEnc_Status EncodeSPS(AVCEncObject *encvid, AVCEncBitstream *stream);
+
+    /**
+    This function encodes the VUI parameters into the sequence parameter set bitstream.
+    \param "stream" "Pointer to AVCEncBitstream."
+    \param "vui"    "Pointer to AVCVUIParams."
+    \return "nothing."
+    */
+    void EncodeVUI(AVCEncBitstream* stream, AVCVUIParams* vui);
+
+    /**
+    This function encodes HRD parameters into the sequence parameter set bitstream
+    \param "stream" "Pointer to AVCEncBitstream."
+    \param "hrd"    "Pointer to AVCHRDParams."
+    \return "nothing."
+    */
+    void EncodeHRD(AVCEncBitstream* stream, AVCHRDParams* hrd);
+
+
+    /**
+    This function performs bitstream encoding of the picture parameter set NAL.
+    \param "encvid" "Pointer to the AVCEncObject."
+    \param "stream" "Pointer to AVCEncBitstream."
+    \return "AVCENC_SUCCESS if success or AVCENC_PPS_FAIL or others for unexpected failure which
+    should not occur. The SPS parameters should all be verified before this function is called."
+    */
+    AVCEnc_Status EncodePPS(AVCEncObject *encvid, AVCEncBitstream *stream);
+
+    /**
+    This function encodes slice header information which has been initialized or fabricated
+    prior to entering this funciton.
+    \param "encvid" "Pointer to the AVCEncObject."
+    \param "stream" "Pointer to AVCEncBitstream."
+    \return "AVCENC_SUCCESS if success or bitstream fail statuses."
+    */
+    AVCEnc_Status EncodeSliceHeader(AVCEncObject *encvid, AVCEncBitstream *stream);
+
+    /**
+    This function encodes reference picture list reordering relted syntax.
+    \param "video" "Pointer to AVCCommonObj."
+    \param "stream" "Pointer to AVCEncBitstream."
+    \param "sliceHdr" "Pointer to AVCSliceHdr."
+    \param "slice_type" "Value of slice_type - 5 if greater than 5."
+    \return "AVCENC_SUCCESS for success and AVCENC_FAIL otherwise."
+    */
+    AVCEnc_Status ref_pic_list_reordering(AVCCommonObj *video, AVCEncBitstream *stream, AVCSliceHeader *sliceHdr, int slice_type);
+
+    /**
+    This function encodes dec_ref_pic_marking related syntax.
+    \param "video" "Pointer to AVCCommonObj."
+    \param "stream" "Pointer to AVCEncBitstream."
+    \param "sliceHdr" "Pointer to AVCSliceHdr."
+    \return "AVCENC_SUCCESS for success and AVCENC_FAIL otherwise."
+    */
+    AVCEnc_Status dec_ref_pic_marking(AVCCommonObj *video, AVCEncBitstream *stream, AVCSliceHeader *sliceHdr);
+
+    /**
+    This function initializes the POC related variables and the POC syntax to be encoded
+    to the slice header derived from the disp_order and is_reference flag of the original
+    input frame to be encoded.
+    \param "video"  "Pointer to the AVCEncObject."
+    \return "AVCENC_SUCCESS if success,
+            AVCENC_POC_FAIL if the poc type is undefined or
+            AVCENC_CONSECUTIVE_NONREF if there are consecutive non-reference frame for POC type 2."
+    */
+    AVCEnc_Status InitPOC(AVCEncObject *video);
+
+    /**
+    This function performs POC related operation after a picture is decoded.
+    \param "video" "Pointer to AVCCommonObj."
+    \return "AVCENC_SUCCESS"
+    */
+    AVCEnc_Status PostPOC(AVCCommonObj *video);
+
+    /*----------- bitstream_io.c ----------------*/
+    /**
+    This function initializes the bitstream structure with the information given by
+    the users.
+    \param "bitstream"  "Pointer to the AVCEncBitstream structure."
+    \param "buffer"     "Pointer to the unsigned char buffer for output."
+    \param "buf_size"   "The size of the buffer in bytes."
+    \param "overrunBuffer"  "Pointer to extra overrun buffer."
+    \param "oBSize"     "Size of overrun buffer in bytes."
+    \return "AVCENC_SUCCESS if success, AVCENC_BITSTREAM_INIT_FAIL if fail"
+    */
+    AVCEnc_Status BitstreamEncInit(AVCEncBitstream *bitstream, uint8 *buffer, int buf_size,
+                                   uint8 *overrunBuffer, int oBSize);
+
+    /**
+    This function writes the data from the cache into the bitstream buffer. It also adds the
+    emulation prevention code if necessary.
+    \param "stream"     "Pointer to the AVCEncBitstream structure."
+    \return "AVCENC_SUCCESS if success or AVCENC_BITSTREAM_BUFFER_FULL if fail."
+    */
+    AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream);
+
+    /**
+    This function writes the codeword into the cache which will eventually be written to
+    the bitstream buffer.
+    \param "stream"     "Pointer to the AVCEncBitstream structure."
+    \param "nBits"      "Number of bits in the codeword."
+    \param "code"       "The codeword."
+    \return "AVCENC_SUCCESS if success or AVCENC_BITSTREAM_BUFFER_FULL if fail."
+    */
+    AVCEnc_Status BitstreamWriteBits(AVCEncBitstream *stream, int nBits, uint code);
+
+    /**
+    This function writes one bit of data into the cache which will eventually be written
+    to the bitstream buffer.
+    \param "stream"     "Pointer to the AVCEncBitstream structure."
+    \param "code"       "The codeword."
+    \return "AVCENC_SUCCESS if success or AVCENC_BITSTREAM_BUFFER_FULL if fail."
+    */
+    AVCEnc_Status BitstreamWrite1Bit(AVCEncBitstream *stream, uint code);
+
+    /**
+    This function adds trailing bits to the bitstream and reports back the final EBSP size.
+    \param "stream"     "Pointer to the AVCEncBitstream structure."
+    \param "nal_size"   "Output the final NAL size."
+    \return "AVCENC_SUCCESS if success or AVCENC_BITSTREAM_BUFFER_FULL if fail."
+    */
+    AVCEnc_Status BitstreamTrailingBits(AVCEncBitstream *bitstream, uint *nal_size);
+
+    /**
+    This function checks whether the current bit position is byte-aligned or not.
+    \param "stream" "Pointer to the bitstream structure."
+    \return "true if byte-aligned, false otherwise."
+    */
+    bool byte_aligned(AVCEncBitstream *stream);
+
+
+    /**
+    This function checks the availability of overrun buffer and switches to use it when
+    normal bufffer is not big enough.
+    \param "stream" "Pointer to the bitstream structure."
+    \param "numExtraBytes" "Number of extra byte needed."
+    \return "AVCENC_SUCCESS or AVCENC_FAIL."
+    */
+    AVCEnc_Status AVCBitstreamUseOverrunBuffer(AVCEncBitstream* stream, int numExtraBytes);
+
+
+    /*-------------- intra_est.c ---------------*/
+
+    /** This function performs intra/inter decision based on ABE.
+    \param "encvid" "Pointer to AVCEncObject."
+    \param "min_cost"   "Best inter cost."
+    \param "curL"   "Pointer to the current MB origin in reconstructed frame."
+    \param "picPitch" "Pitch of the reconstructed frame."
+    \return "Boolean for intra mode."
+    */
+
+//bool IntraDecisionABE(AVCEncObject *encvid, int min_cost, uint8 *curL, int picPitch);
+    bool IntraDecision(int *min_cost, uint8 *cur, int pitch, bool ave);
+
+    /**
+    This function performs intra prediction mode search.
+    \param "encvid" "Pointer to AVCEncObject."
+    \param "mbnum"  "Current MB number."
+    \param "curL"   "Pointer to the current MB origin in reconstructed frame."
+    \param "picPitch" "Pitch of the reconstructed frame."
+    \return "void."
+    */
+    void MBIntraSearch(AVCEncObject *encvid, int mbnum, uint8 *curL, int picPitch);
+
+    /**
+    This function generates all the I16 prediction modes for an MB and keep it in
+    encvid->pred_i16.
+    \param "encvid" "Pointer to AVCEncObject."
+    \return "void"
+    */
+    void intrapred_luma_16x16(AVCEncObject *encvid);
+
+    /**
+    This function calculate the cost of all I16 modes and compare them to get the minimum.
+    \param "encvid" "Pointer to AVCEncObject."
+    \param "orgY"   "Pointer to the original luma MB."
+    \param "min_cost" "Pointer to the minimal cost so-far."
+    \return "void"
+    */
+    void find_cost_16x16(AVCEncObject *encvid, uint8 *orgY, int *min_cost);
+
+    /**
+    This function calculates the cost of each I16 mode.
+    \param "org"    "Pointer to the original luma MB."
+    \param "org_pitch" "Stride size of the original frame."
+    \param "pred"   "Pointer to the prediction values."
+    \param "min_cost" "Minimal cost so-far."
+    \return "Cost"
+    */
+
+    int cost_i16(uint8 *org, int org_pitch, uint8 *pred, int min_cost);
+
+    /**
+    This function generates all the I4 prediction modes and select the best one
+    for all the blocks inside a macroblock.It also calls dct_luma to generate the reconstructed
+    MB, and transform coefficients to be encoded.
+    \param "encvid" "Pointer to AVCEncObject."
+    \param "min_cost" "Pointer to the minimal cost so-far."
+    \return "void"
+    */
+    void mb_intra4x4_search(AVCEncObject *encvid, int *min_cost);
+
+    /**
+    This function calculates the most probable I4 mode of a given 4x4 block
+    from neighboring informationaccording to AVC/H.264 standard.
+    \param "video"  "Pointer to AVCCommonObj."
+    \param "blkidx" "The current block index."
+    \return "Most probable mode."
+    */
+    int FindMostProbableI4Mode(AVCCommonObj *video, int blkidx);
+
+    /**
+    This function is where a lot of actions take place in the 4x4 block level inside
+    mb_intra4x4_search.
+    \param "encvid" "Pointer to AVCEncObject."
+    \param "blkidx" "The current 4x4 block index."
+    \param "cur"    "Pointer to the reconstructed block."
+    \param "org"    "Pointer to the original block."
+    \return "Minimal cost, also set currMB->i4Mode"
+    */
+    int blk_intra4x4_search(AVCEncObject *encvid, int blkidx, uint8 *cur, uint8 *org);
+
+    /**
+    This function calculates the cost of a given I4 prediction mode.
+    \param "org"    "Pointer to the original block."
+    \param "org_pitch"  "Stride size of the original frame."
+    \param "pred"   "Pointer to the prediction block. (encvid->pred_i4)"
+    \param "cost"   "Pointer to the minimal cost (to be updated)."
+    \return "void"
+    */
+    void cost_i4(uint8 *org, int org_pitch, uint8 *pred, uint16 *cost);
+
+    /**
+    This function performs chroma intra search. Each mode is saved in encvid->pred_ic.
+    \param "encvid" "Pointer to AVCEncObject."
+    \return "void"
+    */
+    void chroma_intra_search(AVCEncObject *encvid);
+
+    /**
+    This function calculates the cost of a chroma prediction mode.
+    \param "orgCb"  "Pointer to the original Cb block."
+    \param "orgCr"  "Pointer to the original Cr block."
+    \param "org_pitch"  "Stride size of the original frame."
+    \param "pred"   "Pointer to the prediction block (encvid->pred_ic)"
+    \param "mincost"    "Minimal cost so far."
+    \return "Cost."
+    */
+
+    int SATDChroma(uint8 *orgCb, uint8 *orgCr, int org_pitch, uint8 *pred, int mincost);
+
+    /*-------------- motion_comp.c ---------------*/
+
+    /**
+    This is a main function to peform inter prediction.
+    \param "encvid"     "Pointer to AVCEncObject."
+    \param "video"      "Pointer to AVCCommonObj."
+    \return "void".
+    */
+    void AVCMBMotionComp(AVCEncObject *encvid, AVCCommonObj *video);
+
+
+    /**
+    This function is called for luma motion compensation.
+    \param "ref"    "Pointer to the origin of a reference luma."
+    \param "picwidth"   "Width of the picture."
+    \param "picheight"  "Height of the picture."
+    \param "x_pos"  "X-coordinate of the predicted block in quarter pel resolution."
+    \param "y_pos"  "Y-coordinate of the predicted block in quarter pel resolution."
+    \param "pred"   "Pointer to the output predicted block."
+    \param "pred_pitch" "Width of pred."
+    \param "blkwidth"   "Width of the current partition."
+    \param "blkheight"  "Height of the current partition."
+    \return "void"
+    */
+    void eLumaMotionComp(uint8 *ref, int picwidth, int picheight,
+                         int x_pos, int y_pos,
+                         uint8 *pred, int pred_pitch,
+                         int blkwidth, int blkheight);
+
+    void eFullPelMC(uint8 *in, int inwidth, uint8 *out, int outpitch,
+                    int blkwidth, int blkheight);
+
+    void eHorzInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+                        int blkwidth, int blkheight, int dx);
+
+    void eHorzInterp2MC(int *in, int inpitch, uint8 *out, int outpitch,
+                        int blkwidth, int blkheight, int dx);
+
+    void eHorzInterp3MC(uint8 *in, int inpitch, int *out, int outpitch,
+                        int blkwidth, int blkheight);
+
+    void eVertInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+                        int blkwidth, int blkheight, int dy);
+
+    void eVertInterp2MC(uint8 *in, int inpitch, int *out, int outpitch,
+                        int blkwidth, int blkheight);
+
+    void eVertInterp3MC(int *in, int inpitch, uint8 *out, int outpitch,
+                        int blkwidth, int blkheight, int dy);
+
+    void eDiagonalInterpMC(uint8 *in1, uint8 *in2, int inpitch,
+                           uint8 *out, int outpitch,
+                           int blkwidth, int blkheight);
+
+    void eChromaMotionComp(uint8 *ref, int picwidth, int picheight,
+                           int x_pos, int y_pos, uint8 *pred, int pred_pitch,
+                           int blkwidth, int blkheight);
+
+    void eChromaDiagonalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                                uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+    void eChromaHorizontalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                                  uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+    void eChromaVerticalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                                uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+    void eChromaFullMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                            uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+    void eChromaVerticalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                                 uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+    void eChromaHorizontalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                                   uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+    void eChromaDiagonalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                                 uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+
+    /*-------------- motion_est.c ---------------*/
+
+    /**
+    Allocate and initialize arrays necessary for motion search algorithm.
+    \param "envid" "Pointer to AVCEncObject."
+    \return "AVC_SUCCESS or AVC_MEMORY_FAIL."
+    */
+    AVCEnc_Status InitMotionSearchModule(AVCHandle *avcHandle);
+
+    /**
+    Clean up memory allocated in InitMotionSearchModule.
+    \param "envid" "Pointer to AVCEncObject."
+    \return "void."
+    */
+    void CleanMotionSearchModule(AVCHandle *avcHandle);
+
+
+    /**
+    This function performs motion estimation of all macroblocks in a frame during the InitFrame.
+    The goal is to find the best MB partition for inter and find out if intra search is needed for
+    any MBs. This intra MB tendency can be used for scene change detection.
+    \param "encvid" "Pointer to AVCEncObject."
+    \return "void"
+    */
+    void AVCMotionEstimation(AVCEncObject *encvid);
+
+    /**
+    This function performs repetitive edge padding to the reference picture by adding 16 pixels
+    around the luma and 8 pixels around the chromas.
+    \param "refPic" "Pointer to the reference picture."
+    \return "void"
+    */
+    void  AVCPaddingEdge(AVCPictureData *refPic);
+
+    /**
+    This function keeps track of intra refresh macroblock locations.
+    \param "encvid" "Pointer to the global array structure AVCEncObject."
+    \param "mblock" "Pointer to the array of AVCMacroblock structures."
+    \param "totalMB" "Total number of MBs in a frame."
+    \param "numRefresh" "Number of MB to be intra refresh in a single frame."
+    \return "void"
+    */
+    void AVCRasterIntraUpdate(AVCEncObject *encvid, AVCMacroblock *mblock, int totalMB, int numRefresh);
+
+#ifdef HTFM
+    void InitHTFM(VideoEncData *encvid, HTFM_Stat *htfm_stat, double *newvar, int *collect);
+    void UpdateHTFM(AVCEncObject *encvid, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat);
+    void CalcThreshold(double pf, double exp_lamda[], int nrmlz_th[]);
+    void    HTFMPrepareCurMB_AVC(AVCEncObject *encvid, HTFM_Stat *htfm_stat, uint8 *cur, int pitch);
+#endif
+
+    /**
+    This function reads the input MB into a smaller faster memory space to minimize the cache miss.
+    \param "encvid" "Pointer to the global AVCEncObject."
+    \param "cur"    "Pointer to the original input macroblock."
+    \param "pitch"  "Stride size of the input frame (luma)."
+    \return "void"
+    */
+    void    AVCPrepareCurMB(AVCEncObject *encvid, uint8 *cur, int pitch);
+
+    /**
+    Performs motion vector search for a macroblock.
+    \param "encvid" "Pointer to AVCEncObject structure."
+    \param "cur"    "Pointer to the current macroblock in the input frame."
+    \param "best_cand" "Array of best candidates (to be filled in and returned)."
+    \param "i0"     "X-coordinate of the macroblock."
+    \param "j0"     "Y-coordinate of the macroblock."
+    \param "type_pred" "Indicates the type of operations."
+    \param "FS_en"      "Flag for fullsearch enable."
+    \param "hp_guess"   "Guess for half-pel search."
+    \return "void"
+    */
+    void AVCMBMotionSearch(AVCEncObject *encvid, uint8 *cur, uint8 *best_cand[],
+                           int i0, int j0, int type_pred, int FS_en, int *hp_guess);
+
+//AVCEnc_Status AVCMBMotionSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum,
+//                           int num_pass);
+
+    /**
+    Perform full-pel exhaustive search around the predicted MV.
+    \param "encvid" "Pointer to AVCEncObject structure."
+    \param "prev"   "Pointer to the reference frame."
+    \param "cur"    "Pointer to the input macroblock."
+    \param "imin"   "Pointer to minimal mv (x)."
+    \param "jmin"   "Pointer to minimal mv (y)."
+    \param "ilow, ihigh, jlow, jhigh"   "Lower bound on search range."
+    \param "cmvx, cmvy" "Predicted MV value."
+
+    \return "The cost function of the best candidate."
+    */
+    int AVCFullSearch(AVCEncObject *encvid, uint8 *prev, uint8 *cur,
+                      int *imin, int *jmin, int ilow, int ihigh, int jlow, int jhigh,
+                      int cmvx, int cmvy);
+
+    /**
+    Select candidates from neighboring blocks according to the type of the
+    prediction selection.
+    \param "mvx"    "Pointer to the candidate, x-coordinate."
+    \param "mvy"    "Pointer to the candidate, y-coordinate."
+    \param "num_can"    "Pointer to the number of candidates returned."
+    \param "imb"    "The MB index x-coordinate."
+    \param "jmb"    "The MB index y-coordinate."
+    \param "type_pred"  "Type of the prediction."
+    \param "cmvx, cmvy" "Pointer to predicted MV (modified version)."
+    \return "void."
+    */
+    void AVCCandidateSelection(int *mvx, int *mvy, int *num_can, int imb, int jmb,
+                               AVCEncObject *encvid, int type_pred, int *cmvx, int *cmvy);
+
+    /**
+    Utility function to move the values in the array dn according to the new
+    location to avoid redundant calculation.
+    \param "dn" "Array of integer of size 9."
+    \param "new_loc"    "New location index."
+    \return "void."
+    */
+    void AVCMoveNeighborSAD(int dn[], int new_loc);
+
+    /**
+    Find minimum index of dn.
+    \param "dn" "Array of integer of size 9."
+    \return "The index of dn with the smallest dn[] value."
+    */
+    int AVCFindMin(int dn[]);
+
+
+    /*------------- findhalfpel.c -------------------*/
+
+    /**
+    Search for the best half-pel resolution MV around the full-pel MV.
+    \param "encvid" "Pointer to the global AVCEncObject structure."
+    \param "cur"    "Pointer to the current macroblock."
+    \param "mot"    "Pointer to the AVCMV array of the frame."
+    \param "ncand"  "Pointer to the origin of the fullsearch result."
+    \param "xpos"   "The current MB position in x."
+    \param "ypos"   "The current MB position in y."
+    \param "hp_guess"   "Input to help speedup the search."
+    \param "cmvx, cmvy" "Predicted motion vector use for mvcost."
+    \return "Minimal cost (SATD) without MV cost. (for rate control purpose)"
+    */
+    int AVCFindHalfPelMB(AVCEncObject *encvid, uint8 *cur, AVCMV *mot, uint8 *ncand,
+                         int xpos, int ypos, int hp_guess, int cmvx, int cmvy);
+
+    /**
+    This function generates sub-pel pixels required to do subpel MV search.
+    \param "subpel_pred" "Pointer to 2-D array, each array for each position."
+    \param "ncand" "Pointer to the full-pel center position in ref frame."
+    \param "lx" "Pitch of the ref frame."
+    \return "void"
+     */
+    void GenerateHalfPelPred(uint8 *subpel_pred, uint8 *ncand, int lx);
+
+    /**
+    This function calculate vertical interpolation at half-point of size 4x17.
+    \param "dst" "Pointer to destination."
+    \param "ref" "Pointer to the starting reference pixel."
+    \return "void."
+    */
+    void VertInterpWClip(uint8 *dst, uint8 *ref);
+
+    /**
+    This function generates quarter-pel pixels around the best half-pel result
+    during the sub-pel MV search.
+    \param "bilin_base"  "Array of pointers to be used as basis for q-pel interp."
+    \param "qpel_pred"  "Array of pointers pointing to quarter-pel candidates."
+    \param "hpel_pos" "Best half-pel position at the center."
+    \return "void"
+    */
+    void GenerateQuartPelPred(uint8 **bilin_base, uint8 *qpel_pred, int hpel_pos);
+
+    /**
+    This function calculates the SATD of a subpel candidate.
+    \param "cand"   "Pointer to a candidate."
+    \param "cur"    "Pointer to the current block."
+    \param "dmin"   "Min-so-far SATD."
+    \return "Sum of Absolute Transformed Difference."
+    */
+    int SATD_MB(uint8 *cand, uint8 *cur, int dmin);
+
+    /*------------- rate_control.c -------------------*/
+
+    /** This function is a utility function. It returns average QP of the previously encoded frame.
+    \param "rateCtrl" "Pointer to AVCRateControl structure."
+    \return "Average QP."
+    */
+    int GetAvgFrameQP(AVCRateControl *rateCtrl);
+
+    /**
+    This function takes the timestamp of the input and determine whether it should be encoded
+    or skipped.
+    \param "encvid" "Pointer to the AVCEncObject structure."
+    \param "rateCtrl"   "Pointer to the AVCRateControl structure."
+    \param "modTime"    "The 32 bit timestamp of the input frame."
+    \param "frameNum"   "Pointer to the frame number if to be encoded."
+    \return "AVC_SUCCESS or else."
+    */
+    AVCEnc_Status RCDetermineFrameNum(AVCEncObject *encvid, AVCRateControl *rateCtrl, uint32 modTime, uint *frameNum);
+
+    /**
+    This function updates the buffer fullness when frames are dropped either by the
+    rate control algorithm or by the users to make sure that target bit rate is still met.
+    \param "video" "Pointer to the common object structure."
+    \param "rateCtrl" "Pointer to rate control structure."
+    \param "frameInc" "Difference of the current frame number and previous frame number."
+    \return "void."
+    */
+    void RCUpdateBuffer(AVCCommonObj *video, AVCRateControl *rateCtrl, int frameInc);
+
+    /**
+    This function initializes rate control module and allocates necessary bufferes to do the job.
+    \param "avcHandle" "Pointer to the encoder handle."
+    \return "AVCENC_SUCCESS or AVCENC_MEMORY_FAIL."
+    */
+    AVCEnc_Status InitRateControlModule(AVCHandle *avcHandle);
+
+    /**
+    This function frees buffers allocated in InitRateControlModule.
+    \param "avcHandle" "Pointer to the encoder handle."
+    \return "void."
+    */
+    void CleanupRateControlModule(AVCHandle *avcHandle);
+
+    /**
+    This function is called at the beginning of each GOP or the first IDR frame. It calculates
+    target bits for a GOP.
+    \param "encvid" "Pointer to the encoder object."
+    \return "void."
+    */
+    void RCInitGOP(AVCEncObject *encvid);
+
+    /**
+    This function calculates target bits for a particular frame.
+    \param "video"  "Pointer to the AVCEncObject structure."
+    \return "void"
+    */
+    void RCInitFrameQP(AVCEncObject *video);
+
+    /**
+    This function calculates QP for the upcoming frame or basic unit.
+    \param "encvid" "Pointer to the encoder object."
+    \param "rateCtrl" "Pointer to the rate control object."
+    \return "QP value ranging from 0-51."
+    */
+    int  RCCalculateQP(AVCEncObject *encvid, AVCRateControl *rateCtrl);
+
+    /**
+    This function translates the luma QP to chroma QP and calculates lambda based on QP.
+    \param "video"  "Pointer to the AVCEncObject structure."
+    \return "void"
+    */
+    void RCInitChromaQP(AVCEncObject *encvid);
+
+    /**
+    This function is called before encoding each macroblock.
+    \param "encvid" "Pointer to the encoder object."
+    \return "void."
+    */
+    void RCInitMBQP(AVCEncObject *encvid);
+
+    /**
+    This function updates bits usage stats after encoding an macroblock.
+    \param "video" "Pointer to AVCCommonObj."
+    \param "rateCtrl" "Pointer to AVCRateControl."
+    \param "num_header_bits" "Number of bits used for MB header."
+    \param "num_texture_bits" "Number of bits used for MB texture."
+    \return "void"
+    */
+    void RCPostMB(AVCCommonObj *video, AVCRateControl *rateCtrl, int num_header_bits, int num_texture_bits);
+
+    /**
+    This function calculates the difference between prediction and original MB.
+    \param "encvid" "Pointer to the encoder object."
+    \param "currMB" "Pointer to the current macroblock structure."
+    \param "orgL" "Pointer to the original MB."
+    \param "orgPitch" "Pointer to the original picture pitch."
+    \return "void."
+    */
+    void RCCalculateMAD(AVCEncObject *encvid, AVCMacroblock *currMB, uint8 *orgL, int orgPitch);
+
+    /**
+    Restore QP related parameters of previous MB when current MB is skipped.
+    \param "currMB" "Pointer to the current macroblock."
+    \param "video"  "Pointer to the common video structure."
+    \param "encvid" "Pointer to the global encoding structure."
+    \return "void"
+    */
+    void RCRestoreQP(AVCMacroblock *currMB, AVCCommonObj *video, AVCEncObject *encvid);
+
+    /**
+    This function is called after done with a frame.
+    \param "encvid" "Pointer to the encoder object."
+    \return "AVCENC_SUCCESS or AVCENC_SKIPPED_PICTURE when bufer overflow (need to discard current frame)."
+    */
+    AVCEnc_Status RCUpdateFrame(AVCEncObject *encvid);
+
+    /*--------- residual.c -------------------*/
+
+    /**
+    This function encodes the intra pcm data and fill it in the corresponding location
+    on the current picture.
+    \param "video"  "Pointer to AVCEncObject."
+    \return "AVCENC_SUCCESS if success, or else for bitstream errors."
+    */
+    AVCEnc_Status EncodeIntraPCM(AVCEncObject *video);
+
+    /**
+    This function performs CAVLC syntax encoding on the run and level information of the coefficients.
+    The level and run arrays are elements in AVCEncObject structure, populated by TransQuantZZ,
+    TransQuantIntraDC and TransQuantChromaDC functions.
+    \param "video"  "Pointer to AVCEncObject."
+    \param "type"   "One of AVCResidualType for a particular 4x4 block."
+    \param "bindx"  "Block index or number of nonzero coefficients for AVC_Intra16DC and AVC_ChromaDC mode."
+    \param "currMB" "Pointer to the current macroblock structure."
+    \return "AVCENC_SUCCESS for success."
+    \Note   "This function has 32-bit machine specific instruction!!!!"
+    */
+    AVCEnc_Status enc_residual_block(AVCEncObject *encvid, AVCResidualType type, int bindx, AVCMacroblock *currMB);
+
+
+    /*------------- sad.c ---------------------------*/
+
+
+    int AVCSAD_MB_HalfPel_Cxhyh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+    int AVCSAD_MB_HalfPel_Cyh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+    int AVCSAD_MB_HalfPel_Cxh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+    int AVCSAD_Macroblock_C(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+
+#ifdef HTFM /*  3/2/1, Hypothesis Testing Fast Matching */
+    int AVCSAD_MB_HP_HTFM_Collectxhyh(uint8 *ref, uint8 *blk, int dmin_x, void *extra_info);
+    int AVCSAD_MB_HP_HTFM_Collectyh(uint8 *ref, uint8 *blk, int dmin_x, void *extra_info);
+    int AVCSAD_MB_HP_HTFM_Collectxh(uint8 *ref, uint8 *blk, int dmin_x, void *extra_info);
+    int AVCSAD_MB_HP_HTFMxhyh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+    int AVCSAD_MB_HP_HTFMyh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+    int AVCSAD_MB_HP_HTFMxh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+    int AVCSAD_MB_HTFM_Collect(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+    int AVCSAD_MB_HTFM(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+#endif
+
+
+    /*------------- slice.c -------------------------*/
+
+    /**
+    This function performs the main encoding loop for a slice.
+    \param "encvid" "Pointer to AVCEncObject."
+    \return "AVCENC_SUCCESS for success, AVCENC_PICTURE_READY for end-of-picture and
+             AVCENC_FAIL or AVCENC_SLICE_EMPTY otherwise."
+    */
+    AVCEnc_Status AVCEncodeSlice(AVCEncObject *encvid);
+
+    /**
+    This function performs the main encoding operation for one macroblock.
+    \param "video" "pointer to AVCEncObject."
+    \return "AVCENC_SUCCESS for success, or other bitstream related failure status."
+    */
+    AVCEnc_Status EncodeMB(AVCEncObject *video);
+
+    /**
+    This function calls prediction INTRA/INTER functions, transform,
+    quantization and zigzag scanning to get the run-level symbols.
+    \param "encvid" "pointer to AVCEncObject."
+    \param "curL"   "pointer to Luma component of the current frame.
+    \param "curCb"  "pointer to Cb component of the current frame.
+    \param "curCr"  "pointer to Cr component of the current frame.
+    \return "void for now."
+     */
+    void MBPredTransQuantZZ(AVCEncObject *encvid, uint8 *curL, uint8 *curCb, uint8 *curCr);
+
+    /**
+    This function copies the content of the prediction MB into the reconstructed YUV
+    frame directly.
+    \param "curL"   "Pointer to the destination Y component."
+    \param "curCb"  "Pointer to the destination Cb component."
+    \param "curCr"  "Pointer to the destination Cr component."
+    \param "predBlock"  "Pointer to the prediction MB."
+    \param "picWidth"   "The width of the frame."
+    \return "None."
+    */
+    void Copy_MB(uint8 *curL, uint8 *curCb, uint8 *curCr, uint8 *predBlock, int picWidth);
+
+    /**
+    This function encodes the mb_type, CBP, prediction mode, ref idx and MV.
+    \param "currMB" "Pointer to the current macroblock structure."
+    \param "video" "Pointer to the AVCEncObject structure."
+    \return "AVCENC_SUCCESS for success or else for fail."
+    */
+    AVCEnc_Status EncodeMBHeader(AVCMacroblock *currMB, AVCEncObject *video);
+
+    /**
+    This function finds the right mb_type for a macroblock given the mbMode, CBP,
+    NumPart, PredPartMode.
+    \param "currMB" "Pointer to the current macroblock structure."
+    \param "slice_type" "Value of the slice_type."
+    \return "mb_type."
+    */
+    uint InterpretMBType(AVCMacroblock *currMB, int slice_type);
+
+    /**
+    This function encodes the mb_pred part of the macroblock data.
+    \param "video"  "Pointer to the AVCCommonObj structure."
+    \param "currMB" "Pointer to the current macroblock structure."
+    \param "stream" "Pointer to the AVCEncBitstream structure."
+    \return "AVCENC_SUCCESS for success or bitstream fail status."
+    */
+    AVCEnc_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream);
+
+    /**
+    This function encodes the sub_mb_pred part of the macroblock data.
+    \param "video"  "Pointer to the AVCCommonObj structure."
+    \param "currMB" "Pointer to the current macroblock structure."
+    \param "stream" "Pointer to the AVCEncBitstream structure."
+    \return "AVCENC_SUCCESS for success or bitstream fail status."
+    */
+    AVCEnc_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream);
+
+    /**
+    This function interprets the sub_mb_type and sets necessary information
+    when the slice type is AVC_P_SLICE.
+    in the macroblock structure.
+    \param "mblock" "Pointer to current AVCMacroblock."
+    \param "sub_mb_type" "From the syntax bitstream."
+    \return "void"
+    */
+    void InterpretSubMBTypeP(AVCMacroblock *mblock, uint *sub_mb_type);
+
+    /**
+    This function interprets the sub_mb_type and sets necessary information
+    when the slice type is AVC_B_SLICE.
+    in the macroblock structure.
+    \param "mblock" "Pointer to current AVCMacroblock."
+    \param "sub_mb_type" "From the syntax bitstream."
+    \return "void"
+    */
+    void InterpretSubMBTypeB(AVCMacroblock *mblock, uint *sub_mb_type);
+
+    /**
+    This function encodes intra 4x4 mode. It calculates the predicted I4x4 mode and the
+    remnant to be encoded.
+    \param "video"  "Pointer to AVCEncObject structure."
+    \param "currMB" "Pointer to the AVCMacroblock structure."
+    \param "stream" "Pointer to AVCEncBitstream sructure."
+    \return "AVCENC_SUCCESS for success."
+    */
+    AVCEnc_Status EncodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream);
+
+    /*------------- vlc_encode.c -----------------------*/
+    /**
+    This function encodes and writes a value into an Exp-Golomb codeword.
+    \param "bitstream" "Pointer to AVCEncBitstream."
+    \param "codeNum" "Pointer to the value of the codeNum."
+    \return "AVCENC_SUCCESS for success or bitstream error messages for fail."
+    */
+    AVCEnc_Status ue_v(AVCEncBitstream *bitstream, uint codeNum);
+
+    /**
+    This function maps and encodes signed Exp-Golomb codes.
+    \param "bitstream" "Pointer to AVCEncBitstream."
+    \param "value"  "Pointer to syntax element value."
+    \return "AVCENC_SUCCESS or AVCENC_FAIL."
+    */
+    AVCEnc_Status  se_v(AVCEncBitstream *bitstream, int value);
+
+    /**
+    This function maps and encodes truncated Exp-Golomb codes.
+    \param "bitstream" "Pointer to AVCEncBitstream."
+    \param "value"  "Pointer to syntax element value."
+    \param "range"  "Range of the value as input to determine the algorithm."
+    \return "AVCENC_SUCCESS or AVCENC_FAIL."
+    */
+    AVCEnc_Status te_v(AVCEncBitstream *bitstream, uint value, uint range);
+
+    /**
+    This function creates Exp-Golomb codeword from codeNum.
+    \param "bitstream" "Pointer to AVCEncBitstream."
+    \param "codeNum" "Pointer to the codeNum value."
+    \return "AVCENC_SUCCESS for success or bitstream error messages for fail."
+    */
+    AVCEnc_Status SetEGBitstring(AVCEncBitstream *bitstream, uint codeNum);
+
+    /**
+    This function performs CAVLC encoding of the CBP (coded block pattern) of a macroblock
+    by calling ue_v() and then mapping the CBP to the corresponding VLC codeNum.
+    \param "currMB"  "Pointer to the current AVCMacroblock structure."
+    \param "stream"  "Pointer to the AVCEncBitstream."
+    \return "void"
+    */
+    AVCEnc_Status EncodeCBP(AVCMacroblock *currMB, AVCEncBitstream *stream);
+
+    /**
+    This function encodes trailing ones and total coefficient.
+    \param "stream" "Pointer to the AVCEncBitstream."
+    \param "TrailingOnes"   "The trailing one variable output."
+    \param "TotalCoeff" "The total coefficient variable output."
+    \param "nC" "Context for number of nonzero coefficient (prediction context)."
+    \return "AVCENC_SUCCESS for success or else for bitstream failure."
+    */
+    AVCEnc_Status ce_TotalCoeffTrailingOnes(AVCEncBitstream *stream, int TrailingOnes, int TotalCoeff, int nC);
+
+    /**
+    This function encodes trailing ones and total coefficient for chroma DC block.
+    \param "stream" "Pointer to the AVCEncBitstream."
+    \param "TrailingOnes"   "The trailing one variable output."
+    \param "TotalCoeff" "The total coefficient variable output."
+    \return "AVCENC_SUCCESS for success or else for bitstream failure."
+    */
+    AVCEnc_Status ce_TotalCoeffTrailingOnesChromaDC(AVCEncBitstream *stream, int TrailingOnes, int TotalCoeff);
+
+    /**
+    This function encodes total_zeros value as in Table 9-7 and 9-8.
+    \param "stream" "Pointer to the AVCEncBitstream."
+    \param "TotalZeros" "The total_zeros value."
+    \param "TotalCoeff" "The total coefficient variable output."
+    \return "AVCENC_SUCCESS for success or else for bitstream failure."
+    */
+    AVCEnc_Status ce_TotalZeros(AVCEncBitstream *stream, int total_zeros, int TotalCoeff);
+
+    /**
+    This function encodes total_zeros VLC syntax for chroma DC as in Table 9-9.
+    \param "stream" "Pointer to the AVCEncBitstream."
+    \param "TotalZeros" "The total_zeros value."
+    \param "TotalCoeff" "The total coefficient variable output."
+    \return "AVCENC_SUCCESS for success or else for bitstream failure."
+    */
+    AVCEnc_Status ce_TotalZerosChromaDC(AVCEncBitstream *stream, int total_zeros, int TotalCoeff);
+
+    /**
+    This function encodes run_before VLC syntax as in Table 9-10.
+    \param "stream" "Pointer to the AVCEncBitstream."
+    \param "run_before" "The run_before value."
+    \param "zerosLeft"  "The context for number of zeros left."
+    \return "AVCENC_SUCCESS for success or else for bitstream failure."
+    */
+    AVCEnc_Status ce_RunBefore(AVCEncBitstream *stream, int run_before, int zerosLeft);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _AVCENC_LIB_H_ */
+
diff --git a/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp
new file mode 100644
index 0000000..75ab514
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp
@@ -0,0 +1,336 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+#define WORD_SIZE 32
+
+/* array for trailing bit pattern as function of number of bits */
+/* the first one is unused. */
+const static uint8 trailing_bits[9] = {0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
+
+/* ======================================================================== */
+/*  Function : BitstreamInit()                                              */
+/*  Date     : 11/4/2003                                                    */
+/*  Purpose  : Populate bitstream structure with bitstream buffer and size  */
+/*             it also initializes internal data                            */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS if successed, AVCENC_FAIL if failed.              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+/* |--------|--------|----~~~~~-----|---------|---------|---------|
+   ^                                          ^write_pos          ^buf_size
+   bitstreamBuffer                  <--------->
+                                    current_word
+
+   |-----xxxxxxxxxxxxx|  = current_word 32 or 16 bits
+    <---->
+     bit_left
+ ======================================================================== */
+
+AVCEnc_Status BitstreamEncInit(AVCEncBitstream *stream, uint8 *buffer, int buf_size,
+                               uint8 *overrunBuffer, int oBSize)
+{
+    if (stream == NULL || buffer == NULL || buf_size <= 0)
+    {
+        return AVCENC_BITSTREAM_INIT_FAIL;
+    }
+
+    stream->bitstreamBuffer = buffer;
+
+    stream->buf_size = buf_size;
+
+    stream->write_pos = 0;
+
+    stream->count_zeros = 0;
+
+    stream->current_word = 0;
+
+    stream->bit_left = WORD_SIZE;
+
+    stream->overrunBuffer = overrunBuffer;
+
+    stream->oBSize = oBSize;
+
+    return AVCENC_SUCCESS;
+}
+
+/* ======================================================================== */
+/*  Function : AVCBitstreamSaveWord()                                           */
+/*  Date     : 3/29/2004                                                    */
+/*  Purpose  : Save the current_word into the buffer, byte-swap, and        */
+/*              add emulation prevention insertion.                         */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS if successed, AVCENC_WRITE_FAIL if buffer is  */
+/*              full.                                                       */
+/*  Modified :                                                              */
+/* ======================================================================== */
+AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream)
+{
+    int num_bits;
+    uint8 *write_pnt, byte;
+    uint current_word;
+
+    /* check number of bytes in current_word, must always be byte-aligned!!!! */
+    num_bits = WORD_SIZE - stream->bit_left; /* must be multiple of 8 !!*/
+
+    if (stream->buf_size - stream->write_pos <= (num_bits >> 3) + 2) /* 2 more bytes for possible EPBS */
+    {
+        if (AVCENC_SUCCESS != AVCBitstreamUseOverrunBuffer(stream, (num_bits >> 3) + 2))
+        {
+            return AVCENC_BITSTREAM_BUFFER_FULL;
+        }
+    }
+
+    /* write word, byte-by-byte */
+    write_pnt = stream->bitstreamBuffer + stream->write_pos;
+    current_word = stream->current_word;
+    while (num_bits) /* no need to check stream->buf_size and stream->write_pos, taken care already */
+    {
+        num_bits -= 8;
+        byte = (current_word >> num_bits) & 0xFF;
+        if (byte != 0)
+        {
+            *write_pnt++ = byte;
+            stream->write_pos++;
+            stream->count_zeros = 0;
+        }
+        else
+        {
+            stream->count_zeros++;
+            *write_pnt++ = byte;
+            stream->write_pos++;
+            if (stream->count_zeros == 2)
+            {   /* for num_bits = 32, this can add 2 more bytes extra for EPBS */
+                *write_pnt++ = 0x3;
+                stream->write_pos++;
+                stream->count_zeros = 0;
+            }
+        }
+    }
+
+    /* reset current_word and bit_left */
+    stream->current_word = 0;
+    stream->bit_left = WORD_SIZE;
+
+    return AVCENC_SUCCESS;
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamWriteBits()                                         */
+/*  Date     : 3/29/2004                                                    */
+/*  Purpose  : Write up to machine word.                                    */
+/*  In/out   : Unused bits in 'code' must be all zeros.                     */
+/*  Return   : AVCENC_SUCCESS if successed, AVCENC_WRITE_FAIL if buffer is  */
+/*              full.                                                       */
+/*  Modified :                                                              */
+/* ======================================================================== */
+AVCEnc_Status BitstreamWriteBits(AVCEncBitstream *stream, int nBits, uint code)
+{
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    int bit_left = stream->bit_left;
+    uint current_word = stream->current_word;
+
+    //DEBUG_LOG(userData,AVC_LOGTYPE_INFO,"BitstreamWriteBits",nBits,-1);
+
+    if (nBits > WORD_SIZE) /* has to be taken care of specially */
+    {
+        return AVCENC_FAIL; /* for now */
+        /* otherwise, break it down to 2 write of less than 16 bits at a time. */
+    }
+
+    if (nBits <= bit_left) /* more bits left in current_word */
+    {
+        stream->current_word = (current_word << nBits) | code;
+        stream->bit_left -= nBits;
+        if (stream->bit_left == 0) /* prepare for the next word */
+        {
+            status = AVCBitstreamSaveWord(stream);
+            return status;
+        }
+    }
+    else
+    {
+        stream->current_word = (current_word << bit_left) | (code >> (nBits - bit_left));
+
+        nBits -= bit_left;
+
+        stream->bit_left = 0;
+
+        status = AVCBitstreamSaveWord(stream); /* save current word */
+
+        stream->bit_left = WORD_SIZE - nBits;
+
+        stream->current_word = code; /* no extra masking for code, must be handled before saving */
+    }
+
+    return status;
+}
+
+
+/* ======================================================================== */
+/*  Function : BitstreamWrite1Bit()                                         */
+/*  Date     : 3/30/2004                                                    */
+/*  Purpose  : Write 1 bit                                                  */
+/*  In/out   : Unused bits in 'code' must be all zeros.                     */
+/*  Return   : AVCENC_SUCCESS if successed, AVCENC_WRITE_FAIL if buffer is  */
+/*              full.                                                       */
+/*  Modified :                                                              */
+/* ======================================================================== */
+AVCEnc_Status BitstreamWrite1Bit(AVCEncBitstream *stream, uint code)
+{
+    AVCEnc_Status status;
+    uint current_word = stream->current_word;
+
+    //DEBUG_LOG(userData,AVC_LOGTYPE_INFO,"BitstreamWrite1Bit",code,-1);
+
+    //if(1 <= bit_left) /* more bits left in current_word */
+    /* we can assume that there always be positive bit_left in the current word */
+    stream->current_word = (current_word << 1) | code;
+    stream->bit_left--;
+    if (stream->bit_left == 0) /* prepare for the next word */
+    {
+        status = AVCBitstreamSaveWord(stream);
+        return status;
+    }
+
+    return AVCENC_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/*  Function : BitstreamTrailingBits()                                      */
+/*  Date     : 3/31/2004                                                    */
+/*  Purpose  : Add trailing bits and report the final EBSP size.            */
+/*  In/out   :                                                              */
+/*  Return   : AVCENC_SUCCESS if successed, AVCENC_WRITE_FAIL if buffer is  */
+/*              full.                                                       */
+/*  Modified :                                                              */
+/* ======================================================================== */
+AVCEnc_Status BitstreamTrailingBits(AVCEncBitstream *bitstream, uint *nal_size)
+{
+    (void)(nal_size);
+
+    AVCEnc_Status status;
+    int bit_left = bitstream->bit_left;
+
+    bit_left &= 0x7; /* modulo by 8 */
+    if (bit_left == 0) bit_left = 8;
+    /* bitstream->bit_left == 0 cannot happen here since it would have been Saved already */
+
+    status = BitstreamWriteBits(bitstream, bit_left, trailing_bits[bit_left]);
+
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    /* if it's not saved, save it. */
+    //if(bitstream->bit_left<(WORD_SIZE<<3)) /* in fact, no need to check */
+    {
+        status = AVCBitstreamSaveWord(bitstream);
+    }
+
+    return status;
+}
+
+/* check whether it's byte-aligned */
+bool byte_aligned(AVCEncBitstream *stream)
+{
+    if (stream->bit_left % 8)
+        return false;
+    else
+        return true;
+}
+
+
+/* determine whether overrun buffer can be used or not */
+AVCEnc_Status AVCBitstreamUseOverrunBuffer(AVCEncBitstream* stream, int numExtraBytes)
+{
+    AVCEncObject *encvid = (AVCEncObject*)stream->encvid;
+
+    if (stream->overrunBuffer != NULL) // overrunBuffer is set
+    {
+        if (stream->bitstreamBuffer != stream->overrunBuffer) // not already used
+        {
+            if (stream->write_pos + numExtraBytes >= stream->oBSize)
+            {
+                stream->oBSize = stream->write_pos + numExtraBytes + 100;
+                stream->oBSize &= (~0x3); // make it multiple of 4
+
+                // allocate new overrun Buffer
+                if (encvid->overrunBuffer)
+                {
+                    encvid->avcHandle->CBAVC_Free((uint32*)encvid->avcHandle->userData,
+                                                  (int)encvid->overrunBuffer);
+                }
+
+                encvid->oBSize = stream->oBSize;
+                encvid->overrunBuffer = (uint8*) encvid->avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
+                                        stream->oBSize, DEFAULT_ATTR);
+
+                stream->overrunBuffer = encvid->overrunBuffer;
+                if (stream->overrunBuffer == NULL)
+                {
+                    return AVCENC_FAIL;
+                }
+            }
+
+            // copy everything to overrun buffer and start using it.
+            memcpy(stream->overrunBuffer, stream->bitstreamBuffer, stream->write_pos);
+            stream->bitstreamBuffer = stream->overrunBuffer;
+            stream->buf_size = stream->oBSize;
+        }
+        else // overrun buffer is already used
+        {
+            stream->oBSize = stream->write_pos + numExtraBytes + 100;
+            stream->oBSize &= (~0x3); // make it multiple of 4
+
+            // allocate new overrun buffer
+            encvid->oBSize = stream->oBSize;
+            encvid->overrunBuffer = (uint8*) encvid->avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
+                                    stream->oBSize, DEFAULT_ATTR);
+
+            if (encvid->overrunBuffer == NULL)
+            {
+                return AVCENC_FAIL;
+            }
+
+
+            // copy from the old buffer to new buffer
+            memcpy(encvid->overrunBuffer, stream->overrunBuffer, stream->write_pos);
+            // free old buffer
+            encvid->avcHandle->CBAVC_Free((uint32*)encvid->avcHandle->userData,
+                                          (int)stream->overrunBuffer);
+
+            // assign pointer to new buffer
+            stream->overrunBuffer = encvid->overrunBuffer;
+            stream->bitstreamBuffer = stream->overrunBuffer;
+            stream->buf_size = stream->oBSize;
+        }
+
+        return AVCENC_SUCCESS;
+    }
+    else // overrunBuffer is not enable.
+    {
+        return AVCENC_FAIL;
+    }
+
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/block.cpp b/media/libstagefright/codecs/avc/enc/src/block.cpp
new file mode 100644
index 0000000..01e26a6
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/block.cpp
@@ -0,0 +1,1283 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+/* subtract with the prediction and do transformation */
+void trans(uint8 *cur, int pitch, uint8 *predBlock, int16 *dataBlock)
+{
+    int16 *ptr = dataBlock;
+    int r0, r1, r2, r3, j;
+    int curpitch = (uint)pitch >> 16;
+    int predpitch = (pitch & 0xFFFF);
+
+    /* horizontal */
+    j = 4;
+    while (j > 0)
+    {
+        /* calculate the residue first */
+        r0 = cur[0] - predBlock[0];
+        r1 = cur[1] - predBlock[1];
+        r2 = cur[2] - predBlock[2];
+        r3 = cur[3] - predBlock[3];
+
+        r0 += r3;           //ptr[0] + ptr[3];
+        r3 = r0 - (r3 << 1);    //ptr[0] - ptr[3];
+        r1 += r2;           //ptr[1] + ptr[2];
+        r2 = r1 - (r2 << 1);    //ptr[1] - ptr[2];
+
+        ptr[0] = r0 + r1;
+        ptr[2] = r0 - r1;
+        ptr[1] = (r3 << 1) + r2;
+        ptr[3] = r3 - (r2 << 1);
+
+        ptr += 16;
+        predBlock += predpitch;
+        cur += curpitch;
+        j--;
+    }
+    /* vertical */
+    ptr = dataBlock;
+    j = 4;
+    while (j > 0)
+    {
+        r0 = ptr[0] + ptr[48];
+        r3 = ptr[0] - ptr[48];
+        r1 = ptr[16] + ptr[32];
+        r2 = ptr[16] - ptr[32];
+
+        ptr[0] = r0 + r1;
+        ptr[32] = r0 - r1;
+        ptr[16] = (r3 << 1) + r2;
+        ptr[48] = r3 - (r2 << 1);
+
+        ptr++;
+        j--;
+    }
+
+    return ;
+}
+
+
+/* do residue transform quant invquant, invtrans and write output out */
+int dct_luma(AVCEncObject *encvid, int blkidx, uint8 *cur, uint8 *org, int *coef_cost)
+{
+    AVCCommonObj *video = encvid->common;
+    int org_pitch = encvid->currInput->pitch;
+    int pitch = video->currPic->pitch;
+    int16 *coef = video->block;
+    uint8 *pred = video->pred_block; // size 16 for a 4x4 block
+    int pred_pitch = video->pred_pitch;
+    int r0, r1, r2, r3, j, k, idx;
+    int *level, *run;
+    int Qq, Rq, q_bits, qp_const, quant;
+    int data, lev, zero_run;
+    int numcoeff;
+
+    coef += ((blkidx & 0x3) << 2) + ((blkidx >> 2) << 6); /* point to the 4x4 block */
+
+    /* first take a 4x4 transform */
+    /* horizontal */
+    j = 4;
+    while (j > 0)
+    {
+        /* calculate the residue first */
+        r0 = org[0] - pred[0];   /* OPTIMIZEABLE */
+        r1 = org[1] - pred[1];
+        r2 = org[2] - pred[2];
+        r3 = org[3] - pred[3];
+
+        r0 += r3;           //ptr[0] + ptr[3];
+        r3 = r0 - (r3 << 1);    //ptr[0] - ptr[3];
+        r1 += r2;           //ptr[1] + ptr[2];
+        r2 = r1 - (r2 << 1);    //ptr[1] - ptr[2];
+
+        coef[0] = r0 + r1;
+        coef[2] = r0 - r1;
+        coef[1] = (r3 << 1) + r2;
+        coef[3] = r3 - (r2 << 1);
+
+        coef += 16;
+        org += org_pitch;
+        pred += pred_pitch;
+        j--;
+    }
+    /* vertical */
+    coef -= 64;
+    pred -= (pred_pitch << 2);
+    j = 4;
+    while (j > 0)   /* OPTIMIZABLE */
+    {
+        r0 = coef[0] + coef[48];
+        r3 = coef[0] - coef[48];
+        r1 = coef[16] + coef[32];
+        r2 = coef[16] - coef[32];
+
+        coef[0] = r0 + r1;
+        coef[32] = r0 - r1;
+        coef[16] = (r3 << 1) + r2;
+        coef[48] = r3 - (r2 << 1);
+
+        coef++;
+        j--;
+    }
+
+    coef -= 4;
+
+    /* quant */
+    level = encvid->level[ras2dec[blkidx]];
+    run = encvid->run[ras2dec[blkidx]];
+
+    Rq = video->QPy_mod_6;
+    Qq = video->QPy_div_6;
+    qp_const = encvid->qp_const;
+    q_bits = 15 + Qq;
+
+    zero_run = 0;
+    numcoeff = 0;
+    for (k = 0; k < 16; k++)
+    {
+        idx = ZZ_SCAN_BLOCK[k]; /* map back to raster scan order */
+        data = coef[idx];
+        quant = quant_coef[Rq][k];
+        if (data > 0)
+        {
+            lev = data * quant + qp_const;
+        }
+        else
+        {
+            lev = -data * quant + qp_const;
+        }
+        lev >>= q_bits;
+        if (lev)
+        {
+            *coef_cost += ((lev > 1) ? MAX_VALUE : COEFF_COST[DISABLE_THRESHOLDING][zero_run]);
+
+            /* dequant */
+            quant = dequant_coefres[Rq][k];
+            if (data > 0)
+            {
+                level[numcoeff] = lev;
+                coef[idx] = (lev * quant) << Qq;
+            }
+            else
+            {
+                level[numcoeff] = -lev;
+                coef[idx] = (-lev * quant) << Qq;
+            }
+            run[numcoeff++] = zero_run;
+            zero_run = 0;
+        }
+        else
+        {
+            zero_run++;
+            coef[idx] = 0;
+        }
+    }
+
+    if (video->currMB->mb_intra) // only do inverse transform with intra block
+    {
+        if (numcoeff) /* then do inverse transform */
+        {
+            for (j = 4; j > 0; j--) /* horizontal */
+            {
+                r0 = coef[0] + coef[2];
+                r1 = coef[0] - coef[2];
+                r2 = (coef[1] >> 1) - coef[3];
+                r3 = coef[1] + (coef[3] >> 1);
+
+                coef[0] = r0 + r3;
+                coef[1] = r1 + r2;
+                coef[2] = r1 - r2;
+                coef[3] = r0 - r3;
+
+                coef += 16;
+            }
+
+            coef -= 64;
+            for (j = 4; j > 0; j--) /* vertical, has to be done after horizontal */
+            {
+                r0 = coef[0] + coef[32];
+                r1 = coef[0] - coef[32];
+                r2 = (coef[16] >> 1) - coef[48];
+                r3 = coef[16] + (coef[48] >> 1);
+                r0 += r3;
+                r3 = (r0 - (r3 << 1)); /* r0-r3 */
+                r1 += r2;
+                r2 = (r1 - (r2 << 1)); /* r1-r2 */
+                r0 += 32;
+                r1 += 32;
+                r2 += 32;
+                r3 += 32;
+
+                r0 = pred[0] + (r0 >> 6);
+                if ((uint)r0 > 0xFF)   r0 = 0xFF & (~(r0 >> 31));  /* clip */
+                r1 = *(pred += pred_pitch) + (r1 >> 6);
+                if ((uint)r1 > 0xFF)   r1 = 0xFF & (~(r1 >> 31));  /* clip */
+                r2 = *(pred += pred_pitch) + (r2 >> 6);
+                if ((uint)r2 > 0xFF)   r2 = 0xFF & (~(r2 >> 31));  /* clip */
+                r3 = pred[pred_pitch] + (r3 >> 6);
+                if ((uint)r3 > 0xFF)   r3 = 0xFF & (~(r3 >> 31));  /* clip */
+
+                *cur = r0;
+                *(cur += pitch) = r1;
+                *(cur += pitch) = r2;
+                cur[pitch] = r3;
+                cur -= (pitch << 1);
+                cur++;
+                pred -= (pred_pitch << 1);
+                pred++;
+                coef++;
+            }
+        }
+        else  // copy from pred to cur
+        {
+            *((uint32*)cur) = *((uint32*)pred);
+            *((uint32*)(cur += pitch)) = *((uint32*)(pred += pred_pitch));
+            *((uint32*)(cur += pitch)) = *((uint32*)(pred += pred_pitch));
+            *((uint32*)(cur += pitch)) = *((uint32*)(pred += pred_pitch));
+        }
+    }
+
+    return numcoeff;
+}
+
+
+void MBInterIdct(AVCCommonObj *video, uint8 *curL, AVCMacroblock *currMB, int picPitch)
+{
+    int16 *coef, *coef8 = video->block;
+    uint8 *cur;  // the same as curL
+    int b8, b4;
+    int r0, r1, r2, r3, j, blkidx;
+
+    for (b8 = 0; b8 < 4; b8++)
+    {
+        cur = curL;
+        coef = coef8;
+
+        if (currMB->CBP&(1 << b8))
+        {
+            for (b4 = 0; b4 < 4; b4++)
+            {
+                blkidx = blkIdx2blkXY[b8][b4];
+                /* do IDCT */
+                if (currMB->nz_coeff[blkidx])
+                {
+                    for (j = 4; j > 0; j--) /* horizontal */
+                    {
+                        r0 = coef[0] + coef[2];
+                        r1 = coef[0] - coef[2];
+                        r2 = (coef[1] >> 1) - coef[3];
+                        r3 = coef[1] + (coef[3] >> 1);
+
+                        coef[0] = r0 + r3;
+                        coef[1] = r1 + r2;
+                        coef[2] = r1 - r2;
+                        coef[3] = r0 - r3;
+
+                        coef += 16;
+                    }
+
+                    coef -= 64;
+                    for (j = 4; j > 0; j--) /* vertical, has to be done after horizontal */
+                    {
+                        r0 = coef[0] + coef[32];
+                        r1 = coef[0] - coef[32];
+                        r2 = (coef[16] >> 1) - coef[48];
+                        r3 = coef[16] + (coef[48] >> 1);
+                        r0 += r3;
+                        r3 = (r0 - (r3 << 1)); /* r0-r3 */
+                        r1 += r2;
+                        r2 = (r1 - (r2 << 1)); /* r1-r2 */
+                        r0 += 32;
+                        r1 += 32;
+                        r2 += 32;
+                        r3 += 32;
+
+                        r0 = cur[0] + (r0 >> 6);
+                        if ((uint)r0 > 0xFF)   r0 = 0xFF & (~(r0 >> 31));  /* clip */
+                        *cur = r0;
+                        r1 = *(cur += picPitch) + (r1 >> 6);
+                        if ((uint)r1 > 0xFF)   r1 = 0xFF & (~(r1 >> 31));  /* clip */
+                        *cur = r1;
+                        r2 = *(cur += picPitch) + (r2 >> 6);
+                        if ((uint)r2 > 0xFF)   r2 = 0xFF & (~(r2 >> 31));  /* clip */
+                        *cur = r2;
+                        r3 = cur[picPitch] + (r3 >> 6);
+                        if ((uint)r3 > 0xFF)   r3 = 0xFF & (~(r3 >> 31));  /* clip */
+                        cur[picPitch] = r3;
+
+                        cur -= (picPitch << 1);
+                        cur++;
+                        coef++;
+                    }
+                    cur -= 4;
+                    coef -= 4;
+                }
+                if (b4&1)
+                {
+                    cur += ((picPitch << 2) - 4);
+                    coef += 60;
+                }
+                else
+                {
+                    cur += 4;
+                    coef += 4;
+                }
+            }
+        }
+
+        if (b8&1)
+        {
+            curL += ((picPitch << 3) - 8);
+            coef8 += 120;
+        }
+        else
+        {
+            curL += 8;
+            coef8 += 8;
+        }
+    }
+
+    return ;
+}
+
+/* performa dct, quant, iquant, idct for the entire MB */
+void dct_luma_16x16(AVCEncObject *encvid, uint8 *curL, uint8 *orgL)
+{
+    AVCCommonObj *video = encvid->common;
+    int pitch = video->currPic->pitch;
+    int org_pitch = encvid->currInput->pitch;
+    AVCMacroblock *currMB = video->currMB;
+    int16 *coef = video->block;
+    uint8 *pred = encvid->pred_i16[currMB->i16Mode];
+    int blk_x, blk_y, j, k, idx, b8, b4;
+    int r0, r1, r2, r3, m0, m1, m2 , m3;
+    int data, lev;
+    int *level, *run, zero_run, ncoeff;
+    int Rq, Qq, quant, q_bits, qp_const;
+    int offset_cur[4], offset_pred[4], offset;
+
+    /* horizontal */
+    for (j = 16; j > 0; j--)
+    {
+        for (blk_x = 4; blk_x > 0; blk_x--)
+        {
+            /* calculate the residue first */
+            r0 = *orgL++ - *pred++;
+            r1 = *orgL++ - *pred++;
+            r2 = *orgL++ - *pred++;
+            r3 = *orgL++ - *pred++;
+
+            r0 += r3;           //ptr[0] + ptr[3];
+            r3 = r0 - (r3 << 1);    //ptr[0] - ptr[3];
+            r1 += r2;           //ptr[1] + ptr[2];
+            r2 = r1 - (r2 << 1);    //ptr[1] - ptr[2];
+
+            *coef++ = r0 + r1;
+            *coef++ = (r3 << 1) + r2;
+            *coef++ = r0 - r1;
+            *coef++ = r3 - (r2 << 1);
+        }
+        orgL += (org_pitch - 16);
+    }
+    pred -= 256;
+    coef -= 256;
+    /* vertical */
+    for (blk_y = 4; blk_y > 0; blk_y--)
+    {
+        for (j = 16; j > 0; j--)
+        {
+            r0 = coef[0] + coef[48];
+            r3 = coef[0] - coef[48];
+            r1 = coef[16] + coef[32];
+            r2 = coef[16] - coef[32];
+
+            coef[0] = r0 + r1;
+            coef[32] = r0 - r1;
+            coef[16] = (r3 << 1) + r2;
+            coef[48] = r3 - (r2 << 1);
+
+            coef++;
+        }
+        coef += 48;
+    }
+
+    /* then perform DC transform */
+    coef -= 256;
+    for (j = 4; j > 0; j--)
+    {
+        r0 = coef[0] + coef[12];
+        r3 = coef[0] - coef[12];
+        r1 = coef[4] + coef[8];
+        r2 = coef[4] - coef[8];
+
+        coef[0] = r0 + r1;
+        coef[8] = r0 - r1;
+        coef[4] = r3 + r2;
+        coef[12] = r3 - r2;
+        coef += 64;
+    }
+    coef -= 256;
+    for (j = 4; j > 0; j--)
+    {
+        r0 = coef[0] + coef[192];
+        r3 = coef[0] - coef[192];
+        r1 = coef[64] + coef[128];
+        r2 = coef[64] - coef[128];
+
+        coef[0] = (r0 + r1) >> 1;
+        coef[128] = (r0 - r1) >> 1;
+        coef[64] = (r3 + r2) >> 1;
+        coef[192] = (r3 - r2) >> 1;
+        coef += 4;
+    }
+
+    coef -= 16;
+    // then quantize DC
+    level = encvid->leveldc;
+    run = encvid->rundc;
+
+    Rq = video->QPy_mod_6;
+    Qq = video->QPy_div_6;
+    quant = quant_coef[Rq][0];
+    q_bits = 15 + Qq;
+    qp_const = encvid->qp_const;
+
+    zero_run = 0;
+    ncoeff = 0;
+    for (k = 0; k < 16; k++) /* in zigzag scan order */
+    {
+        idx = ZIGZAG2RASTERDC[k];
+        data = coef[idx];
+        if (data > 0)   // quant
+        {
+            lev = data * quant + (qp_const << 1);
+        }
+        else
+        {
+            lev = -data * quant + (qp_const << 1);
+        }
+        lev >>= (q_bits + 1);
+        if (lev) // dequant
+        {
+            if (data > 0)
+            {
+                level[ncoeff] = lev;
+                coef[idx] = lev;
+            }
+            else
+            {
+                level[ncoeff] = -lev;
+                coef[idx] = -lev;
+            }
+            run[ncoeff++] = zero_run;
+            zero_run = 0;
+        }
+        else
+        {
+            zero_run++;
+            coef[idx] = 0;
+        }
+    }
+
+    /* inverse transform DC */
+    encvid->numcoefdc = ncoeff;
+    if (ncoeff)
+    {
+        quant = dequant_coefres[Rq][0];
+
+        for (j = 0; j < 4; j++)
+        {
+            m0 = coef[0] + coef[4];
+            m1 = coef[0] - coef[4];
+            m2 = coef[8] + coef[12];
+            m3 = coef[8] - coef[12];
+
+
+            coef[0] = m0 + m2;
+            coef[4] = m0 - m2;
+            coef[8] = m1 - m3;
+            coef[12] = m1 + m3;
+            coef += 64;
+        }
+
+        coef -= 256;
+
+        if (Qq >= 2)  /* this way should be faster than JM */
+        {           /* they use (((m4*scale)<<(QPy/6))+2)>>2 for both cases. */
+            Qq -= 2;
+            for (j = 0; j < 4; j++)
+            {
+                m0 = coef[0] + coef[64];
+                m1 = coef[0] - coef[64];
+                m2 = coef[128] + coef[192];
+                m3 = coef[128] - coef[192];
+
+                coef[0] = ((m0 + m2) * quant) << Qq;
+                coef[64] = ((m0 - m2) * quant) << Qq;
+                coef[128] = ((m1 - m3) * quant) << Qq;
+                coef[192] = ((m1 + m3) * quant) << Qq;
+                coef += 4;
+            }
+            Qq += 2; /* restore the value */
+        }
+        else
+        {
+            Qq = 2 - Qq;
+            offset = 1 << (Qq - 1);
+
+            for (j = 0; j < 4; j++)
+            {
+                m0 = coef[0] + coef[64];
+                m1 = coef[0] - coef[64];
+                m2 = coef[128] + coef[192];
+                m3 = coef[128] - coef[192];
+
+                coef[0] = (((m0 + m2) * quant + offset) >> Qq);
+                coef[64] = (((m0 - m2) * quant + offset) >> Qq);
+                coef[128] = (((m1 - m3) * quant + offset) >> Qq);
+                coef[192] = (((m1 + m3) * quant + offset) >> Qq);
+                coef += 4;
+            }
+            Qq = 2 - Qq; /* restore the value */
+        }
+        coef -= 16; /* back to the origin */
+    }
+
+    /* now zigzag scan ac coefs, quant, iquant and itrans */
+    run = encvid->run[0];
+    level = encvid->level[0];
+
+    /* offset btw 4x4 block */
+    offset_cur[0] = 0;
+    offset_cur[1] = (pitch << 2) - 8;
+
+    /* offset btw 8x8 block */
+    offset_cur[2] = 8 - (pitch << 3);
+    offset_cur[3] = -8;
+
+    /* similarly for pred */
+    offset_pred[0] = 0;
+    offset_pred[1] = 56;
+    offset_pred[2] = -120;
+    offset_pred[3] = -8;
+
+    currMB->CBP = 0;
+
+    for (b8 = 0; b8 < 4; b8++)
+    {
+        for (b4 = 0; b4 < 4; b4++)
+        {
+
+            zero_run = 0;
+            ncoeff = 0;
+
+            for (k = 1; k < 16; k++)
+            {
+                idx = ZZ_SCAN_BLOCK[k]; /* map back to raster scan order */
+                data = coef[idx];
+                quant = quant_coef[Rq][k];
+                if (data > 0)
+                {
+                    lev = data * quant + qp_const;
+                }
+                else
+                {
+                    lev = -data * quant + qp_const;
+                }
+                lev >>= q_bits;
+                if (lev)
+                {   /* dequant */
+                    quant = dequant_coefres[Rq][k];
+                    if (data > 0)
+                    {
+                        level[ncoeff] = lev;
+                        coef[idx] = (lev * quant) << Qq;
+                    }
+                    else
+                    {
+                        level[ncoeff] = -lev;
+                        coef[idx] = (-lev * quant) << Qq;
+                    }
+                    run[ncoeff++] = zero_run;
+                    zero_run = 0;
+                }
+                else
+                {
+                    zero_run++;
+                    coef[idx] = 0;
+                }
+            }
+
+            currMB->nz_coeff[blkIdx2blkXY[b8][b4]] = ncoeff; /* in raster scan !!! */
+            if (ncoeff)
+            {
+                currMB->CBP |= (1 << b8);
+
+                // do inverse transform here
+                for (j = 4; j > 0; j--)
+                {
+                    r0 = coef[0] + coef[2];
+                    r1 = coef[0] - coef[2];
+                    r2 = (coef[1] >> 1) - coef[3];
+                    r3 = coef[1] + (coef[3] >> 1);
+
+                    coef[0] = r0 + r3;
+                    coef[1] = r1 + r2;
+                    coef[2] = r1 - r2;
+                    coef[3] = r0 - r3;
+
+                    coef += 16;
+                }
+                coef -= 64;
+                for (j = 4; j > 0; j--)
+                {
+                    r0 = coef[0] + coef[32];
+                    r1 = coef[0] - coef[32];
+                    r2 = (coef[16] >> 1) - coef[48];
+                    r3 = coef[16] + (coef[48] >> 1);
+
+                    r0 += r3;
+                    r3 = (r0 - (r3 << 1)); /* r0-r3 */
+                    r1 += r2;
+                    r2 = (r1 - (r2 << 1)); /* r1-r2 */
+                    r0 += 32;
+                    r1 += 32;
+                    r2 += 32;
+                    r3 += 32;
+                    r0 = pred[0] + (r0 >> 6);
+                    if ((uint)r0 > 0xFF)   r0 = 0xFF & (~(r0 >> 31));  /* clip */
+                    r1 = pred[16] + (r1 >> 6);
+                    if ((uint)r1 > 0xFF)   r1 = 0xFF & (~(r1 >> 31));  /* clip */
+                    r2 = pred[32] + (r2 >> 6);
+                    if ((uint)r2 > 0xFF)   r2 = 0xFF & (~(r2 >> 31));  /* clip */
+                    r3 = pred[48] + (r3 >> 6);
+                    if ((uint)r3 > 0xFF)   r3 = 0xFF & (~(r3 >> 31));  /* clip */
+                    *curL = r0;
+                    *(curL += pitch) = r1;
+                    *(curL += pitch) = r2;
+                    curL[pitch] = r3;
+                    curL -= (pitch << 1);
+                    curL++;
+                    pred++;
+                    coef++;
+                }
+            }
+            else  // do DC-only inverse
+            {
+                m0 = coef[0] + 32;
+
+                for (j = 4; j > 0; j--)
+                {
+                    r0 = pred[0] + (m0 >> 6);
+                    if ((uint)r0 > 0xFF)   r0 = 0xFF & (~(r0 >> 31));  /* clip */
+                    r1 = pred[16] + (m0 >> 6);
+                    if ((uint)r1 > 0xFF)   r1 = 0xFF & (~(r1 >> 31));  /* clip */
+                    r2 = pred[32] + (m0 >> 6);
+                    if ((uint)r2 > 0xFF)   r2 = 0xFF & (~(r2 >> 31));  /* clip */
+                    r3 = pred[48] + (m0 >> 6);
+                    if ((uint)r3 > 0xFF)   r3 = 0xFF & (~(r3 >> 31));  /* clip */
+                    *curL = r0;
+                    *(curL += pitch) = r1;
+                    *(curL += pitch) = r2;
+                    curL[pitch] = r3;
+                    curL -= (pitch << 1);
+                    curL++;
+                    pred++;
+                }
+                coef += 4;
+            }
+
+            run += 16;  // follow coding order
+            level += 16;
+            curL += offset_cur[b4&1];
+            pred += offset_pred[b4&1];
+            coef += offset_pred[b4&1];
+        }
+
+        curL += offset_cur[2 + (b8&1)];
+        pred += offset_pred[2 + (b8&1)];
+        coef += offset_pred[2 + (b8&1)];
+    }
+
+    return ;
+}
+
+
+void dct_chroma(AVCEncObject *encvid, uint8 *curC, uint8 *orgC, int cr)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCMacroblock *currMB = video->currMB;
+    int org_pitch = (encvid->currInput->pitch) >> 1;
+    int pitch = (video->currPic->pitch) >> 1;
+    int pred_pitch = 16;
+    int16 *coef = video->block + 256;
+    uint8 *pred = video->pred_block;
+    int j, blk_x, blk_y, k, idx, b4;
+    int r0, r1, r2, r3, m0;
+    int Qq, Rq, qp_const, q_bits, quant;
+    int *level, *run, zero_run, ncoeff;
+    int data, lev;
+    int offset_cur[2], offset_pred[2], offset_coef[2];
+    uint8 nz_temp[4];
+    int  coeff_cost;
+
+    if (cr)
+    {
+        coef += 8;
+        pred += 8;
+    }
+
+    if (currMB->mb_intra == 0) // inter mode
+    {
+        pred = curC;
+        pred_pitch = pitch;
+    }
+
+    /* do 4x4 transform */
+    /* horizontal */
+    for (j = 8; j > 0; j--)
+    {
+        for (blk_x = 2; blk_x > 0; blk_x--)
+        {
+            /* calculate the residue first */
+            r0 = *orgC++ - *pred++;
+            r1 = *orgC++ - *pred++;
+            r2 = *orgC++ - *pred++;
+            r3 = *orgC++ - *pred++;
+
+            r0 += r3;           //ptr[0] + ptr[3];
+            r3 = r0 - (r3 << 1);    //ptr[0] - ptr[3];
+            r1 += r2;           //ptr[1] + ptr[2];
+            r2 = r1 - (r2 << 1);    //ptr[1] - ptr[2];
+
+            *coef++ = r0 + r1;
+            *coef++ = (r3 << 1) + r2;
+            *coef++ = r0 - r1;
+            *coef++ = r3 - (r2 << 1);
+
+        }
+        coef += 8; // coef pitch is 16
+        pred += (pred_pitch - 8); // pred_pitch is 16
+        orgC += (org_pitch - 8);
+    }
+    pred -= (pred_pitch << 3);
+    coef -= 128;
+    /* vertical */
+    for (blk_y = 2; blk_y > 0; blk_y--)
+    {
+        for (j = 8; j > 0; j--)
+        {
+            r0 = coef[0] + coef[48];
+            r3 = coef[0] - coef[48];
+            r1 = coef[16] + coef[32];
+            r2 = coef[16] - coef[32];
+
+            coef[0] = r0 + r1;
+            coef[32] = r0 - r1;
+            coef[16] = (r3 << 1) + r2;
+            coef[48] = r3 - (r2 << 1);
+
+            coef++;
+        }
+        coef += 56;
+    }
+    /* then perform DC transform */
+    coef -= 128;
+
+    /* 2x2 transform of DC components*/
+    r0 = coef[0];
+    r1 = coef[4];
+    r2 = coef[64];
+    r3 = coef[68];
+
+    coef[0] = r0 + r1 + r2 + r3;
+    coef[4] = r0 - r1 + r2 - r3;
+    coef[64] = r0 + r1 - r2 - r3;
+    coef[68] = r0 - r1 - r2 + r3;
+
+    Qq    = video->QPc_div_6;
+    Rq    = video->QPc_mod_6;
+    quant = quant_coef[Rq][0];
+    q_bits    = 15 + Qq;
+    qp_const = encvid->qp_const_c;
+
+    zero_run = 0;
+    ncoeff = 0;
+    run = encvid->runcdc + (cr << 2);
+    level = encvid->levelcdc + (cr << 2);
+
+    /* in zigzag scan order */
+    for (k = 0; k < 4; k++)
+    {
+        idx = ((k >> 1) << 6) + ((k & 1) << 2);
+        data = coef[idx];
+        if (data > 0)
+        {
+            lev = data * quant + (qp_const << 1);
+        }
+        else
+        {
+            lev = -data * quant + (qp_const << 1);
+        }
+        lev >>= (q_bits + 1);
+        if (lev)
+        {
+            if (data > 0)
+            {
+                level[ncoeff] = lev;
+                coef[idx] = lev;
+            }
+            else
+            {
+                level[ncoeff] = -lev;
+                coef[idx] = -lev;
+            }
+            run[ncoeff++] = zero_run;
+            zero_run = 0;
+        }
+        else
+        {
+            zero_run++;
+            coef[idx] = 0;
+        }
+    }
+
+    encvid->numcoefcdc[cr] = ncoeff;
+
+    if (ncoeff)
+    {
+        currMB->CBP |= (1 << 4); // DC present
+        // do inverse transform
+        quant = dequant_coefres[Rq][0];
+
+        r0 = coef[0] + coef[4];
+        r1 = coef[0] - coef[4];
+        r2 = coef[64] + coef[68];
+        r3 = coef[64] - coef[68];
+
+        r0 += r2;
+        r2 = r0 - (r2 << 1);
+        r1 += r3;
+        r3 = r1 - (r3 << 1);
+
+        if (Qq >= 1)
+        {
+            Qq -= 1;
+            coef[0] = (r0 * quant) << Qq;
+            coef[4] = (r1 * quant) << Qq;
+            coef[64] = (r2 * quant) << Qq;
+            coef[68] = (r3 * quant) << Qq;
+            Qq++;
+        }
+        else
+        {
+            coef[0] = (r0 * quant) >> 1;
+            coef[4] = (r1 * quant) >> 1;
+            coef[64] = (r2 * quant) >> 1;
+            coef[68] = (r3 * quant) >> 1;
+        }
+    }
+
+    /* now do AC zigzag scan, quant, iquant and itrans */
+    if (cr)
+    {
+        run = encvid->run[20];
+        level = encvid->level[20];
+    }
+    else
+    {
+        run = encvid->run[16];
+        level = encvid->level[16];
+    }
+
+    /* offset btw 4x4 block */
+    offset_cur[0] = 0;
+    offset_cur[1] = (pitch << 2) - 8;
+    offset_pred[0] = 0;
+    offset_pred[1] = (pred_pitch << 2) - 8;
+    offset_coef[0] = 0;
+    offset_coef[1] = 56;
+
+    coeff_cost = 0;
+
+    for (b4 = 0; b4 < 4; b4++)
+    {
+        zero_run = 0;
+        ncoeff = 0;
+        for (k = 1; k < 16; k++) /* in zigzag scan order */
+        {
+            idx = ZZ_SCAN_BLOCK[k]; /* map back to raster scan order */
+            data = coef[idx];
+            quant = quant_coef[Rq][k];
+            if (data > 0)
+            {
+                lev = data * quant + qp_const;
+            }
+            else
+            {
+                lev = -data * quant + qp_const;
+            }
+            lev >>= q_bits;
+            if (lev)
+            {
+                /* for RD performance*/
+                if (lev > 1)
+                    coeff_cost += MAX_VALUE;                // set high cost, shall not be discarded
+                else
+                    coeff_cost += COEFF_COST[DISABLE_THRESHOLDING][zero_run];
+
+                /* dequant */
+                quant = dequant_coefres[Rq][k];
+                if (data > 0)
+                {
+                    level[ncoeff] = lev;
+                    coef[idx] = (lev * quant) << Qq;
+                }
+                else
+                {
+                    level[ncoeff] = -lev;
+                    coef[idx] = (-lev * quant) << Qq;
+                }
+                run[ncoeff++] = zero_run;
+                zero_run = 0;
+            }
+            else
+            {
+                zero_run++;
+                coef[idx] = 0;
+            }
+        }
+
+        nz_temp[b4] = ncoeff; // raster scan
+
+        // just advance the pointers for now, do IDCT later
+        coef += 4;
+        run += 16;
+        level += 16;
+        coef += offset_coef[b4&1];
+    }
+
+    /* rewind the pointers */
+    coef -= 128;
+
+    if (coeff_cost < _CHROMA_COEFF_COST_)
+    {
+        /* if it's not efficient to encode any blocks.
+        Just do DC only */
+        /* We can reset level and run also, but setting nz to zero should be enough. */
+        currMB->nz_coeff[16+(cr<<1)] = 0;
+        currMB->nz_coeff[17+(cr<<1)] = 0;
+        currMB->nz_coeff[20+(cr<<1)] = 0;
+        currMB->nz_coeff[21+(cr<<1)] = 0;
+
+        for (b4 = 0; b4 < 4; b4++)
+        {
+            // do DC-only inverse
+            m0 = coef[0] + 32;
+
+            for (j = 4; j > 0; j--)
+            {
+                r0 = pred[0] + (m0 >> 6);
+                if ((uint)r0 > 0xFF)   r0 = 0xFF & (~(r0 >> 31));  /* clip */
+                r1 = *(pred += pred_pitch) + (m0 >> 6);
+                if ((uint)r1 > 0xFF)   r1 = 0xFF & (~(r1 >> 31));  /* clip */
+                r2 = pred[pred_pitch] + (m0 >> 6);
+                if ((uint)r2 > 0xFF)   r2 = 0xFF & (~(r2 >> 31));  /* clip */
+                r3 = pred[pred_pitch<<1] + (m0 >> 6);
+                if ((uint)r3 > 0xFF)   r3 = 0xFF & (~(r3 >> 31));  /* clip */
+                *curC = r0;
+                *(curC += pitch) = r1;
+                *(curC += pitch) = r2;
+                curC[pitch] = r3;
+                curC -= (pitch << 1);
+                curC++;
+                pred += (1 - pred_pitch);
+            }
+            coef += 4;
+            curC += offset_cur[b4&1];
+            pred += offset_pred[b4&1];
+            coef += offset_coef[b4&1];
+        }
+    }
+    else // not dropping anything, continue with the IDCT
+    {
+        for (b4 = 0; b4 < 4; b4++)
+        {
+            ncoeff = nz_temp[b4] ; // in raster scan
+            currMB->nz_coeff[16+(b4&1)+(cr<<1)+((b4>>1)<<2)] = ncoeff; // in raster scan
+
+            if (ncoeff) // do a check on the nonzero-coeff
+            {
+                currMB->CBP |= (2 << 4);
+
+                // do inverse transform here
+                for (j = 4; j > 0; j--)
+                {
+                    r0 = coef[0] + coef[2];
+                    r1 = coef[0] - coef[2];
+                    r2 = (coef[1] >> 1) - coef[3];
+                    r3 = coef[1] + (coef[3] >> 1);
+
+                    coef[0] = r0 + r3;
+                    coef[1] = r1 + r2;
+                    coef[2] = r1 - r2;
+                    coef[3] = r0 - r3;
+
+                    coef += 16;
+                }
+                coef -= 64;
+                for (j = 4; j > 0; j--)
+                {
+                    r0 = coef[0] + coef[32];
+                    r1 = coef[0] - coef[32];
+                    r2 = (coef[16] >> 1) - coef[48];
+                    r3 = coef[16] + (coef[48] >> 1);
+
+                    r0 += r3;
+                    r3 = (r0 - (r3 << 1)); /* r0-r3 */
+                    r1 += r2;
+                    r2 = (r1 - (r2 << 1)); /* r1-r2 */
+                    r0 += 32;
+                    r1 += 32;
+                    r2 += 32;
+                    r3 += 32;
+                    r0 = pred[0] + (r0 >> 6);
+                    if ((uint)r0 > 0xFF)   r0 = 0xFF & (~(r0 >> 31));  /* clip */
+                    r1 = *(pred += pred_pitch) + (r1 >> 6);
+                    if ((uint)r1 > 0xFF)   r1 = 0xFF & (~(r1 >> 31));  /* clip */
+                    r2 = pred[pred_pitch] + (r2 >> 6);
+                    if ((uint)r2 > 0xFF)   r2 = 0xFF & (~(r2 >> 31));  /* clip */
+                    r3 = pred[pred_pitch<<1] + (r3 >> 6);
+                    if ((uint)r3 > 0xFF)   r3 = 0xFF & (~(r3 >> 31));  /* clip */
+                    *curC = r0;
+                    *(curC += pitch) = r1;
+                    *(curC += pitch) = r2;
+                    curC[pitch] = r3;
+                    curC -= (pitch << 1);
+                    curC++;
+                    pred += (1 - pred_pitch);
+                    coef++;
+                }
+            }
+            else
+            {
+                // do DC-only inverse
+                m0 = coef[0] + 32;
+
+                for (j = 4; j > 0; j--)
+                {
+                    r0 = pred[0] + (m0 >> 6);
+                    if ((uint)r0 > 0xFF)   r0 = 0xFF & (~(r0 >> 31));  /* clip */
+                    r1 = *(pred += pred_pitch) + (m0 >> 6);
+                    if ((uint)r1 > 0xFF)   r1 = 0xFF & (~(r1 >> 31));  /* clip */
+                    r2 = pred[pred_pitch] + (m0 >> 6);
+                    if ((uint)r2 > 0xFF)   r2 = 0xFF & (~(r2 >> 31));  /* clip */
+                    r3 = pred[pred_pitch<<1] + (m0 >> 6);
+                    if ((uint)r3 > 0xFF)   r3 = 0xFF & (~(r3 >> 31));  /* clip */
+                    *curC = r0;
+                    *(curC += pitch) = r1;
+                    *(curC += pitch) = r2;
+                    curC[pitch] = r3;
+                    curC -= (pitch << 1);
+                    curC++;
+                    pred += (1 - pred_pitch);
+                }
+                coef += 4;
+            }
+            curC += offset_cur[b4&1];
+            pred += offset_pred[b4&1];
+            coef += offset_coef[b4&1];
+        }
+    }
+
+    return ;
+}
+
+
+/* only DC transform */
+int TransQuantIntra16DC(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    int16 *block = video->block;
+    int *level = encvid->leveldc;
+    int *run = encvid->rundc;
+    int16 *ptr = block;
+    int r0, r1, r2, r3, j;
+    int Qq = video->QPy_div_6;
+    int Rq = video->QPy_mod_6;
+    int q_bits, qp_const, quant;
+    int data, lev, zero_run;
+    int k, ncoeff, idx;
+
+    /* DC transform */
+    /* horizontal */
+    j = 4;
+    while (j)
+    {
+        r0 = ptr[0] + ptr[12];
+        r3 = ptr[0] - ptr[12];
+        r1 = ptr[4] + ptr[8];
+        r2 = ptr[4] - ptr[8];
+
+        ptr[0] = r0 + r1;
+        ptr[8] = r0 - r1;
+        ptr[4] = r3 + r2;
+        ptr[12] = r3 - r2;
+        ptr += 64;
+        j--;
+    }
+    /* vertical */
+    ptr = block;
+    j = 4;
+    while (j)
+    {
+        r0 = ptr[0] + ptr[192];
+        r3 = ptr[0] - ptr[192];
+        r1 = ptr[64] + ptr[128];
+        r2 = ptr[64] - ptr[128];
+
+        ptr[0] = (r0 + r1) >> 1;
+        ptr[128] = (r0 - r1) >> 1;
+        ptr[64] = (r3 + r2) >> 1;
+        ptr[192] = (r3 - r2) >> 1;
+        ptr += 4;
+        j--;
+    }
+
+    quant = quant_coef[Rq][0];
+    q_bits    = 15 + Qq;
+    qp_const = (1 << q_bits) / 3;    // intra
+
+    zero_run = 0;
+    ncoeff = 0;
+
+    for (k = 0; k < 16; k++) /* in zigzag scan order */
+    {
+        idx = ZIGZAG2RASTERDC[k];
+        data = block[idx];
+        if (data > 0)
+        {
+            lev = data * quant + (qp_const << 1);
+        }
+        else
+        {
+            lev = -data * quant + (qp_const << 1);
+        }
+        lev >>= (q_bits + 1);
+        if (lev)
+        {
+            if (data > 0)
+            {
+                level[ncoeff] = lev;
+                block[idx] = lev;
+            }
+            else
+            {
+                level[ncoeff] = -lev;
+                block[idx] = -lev;
+            }
+            run[ncoeff++] = zero_run;
+            zero_run = 0;
+        }
+        else
+        {
+            zero_run++;
+            block[idx] = 0;
+        }
+    }
+    return ncoeff;
+}
+
+int TransQuantChromaDC(AVCEncObject *encvid, int16 *block, int slice_type, int cr)
+{
+    AVCCommonObj *video = encvid->common;
+    int *level, *run;
+    int r0, r1, r2, r3;
+    int Qq, Rq, q_bits, qp_const, quant;
+    int data, lev, zero_run;
+    int k, ncoeff, idx;
+
+    level = encvid->levelcdc + (cr << 2); /* cb or cr */
+    run = encvid->runcdc + (cr << 2);
+
+    /* 2x2 transform of DC components*/
+    r0 = block[0];
+    r1 = block[4];
+    r2 = block[64];
+    r3 = block[68];
+
+    block[0] = r0 + r1 + r2 + r3;
+    block[4] = r0 - r1 + r2 - r3;
+    block[64] = r0 + r1 - r2 - r3;
+    block[68] = r0 - r1 - r2 + r3;
+
+    Qq    = video->QPc_div_6;
+    Rq    = video->QPc_mod_6;
+    quant = quant_coef[Rq][0];
+    q_bits    = 15 + Qq;
+    if (slice_type == AVC_I_SLICE)
+    {
+        qp_const = (1 << q_bits) / 3;
+    }
+    else
+    {
+        qp_const = (1 << q_bits) / 6;
+    }
+
+    zero_run = 0;
+    ncoeff = 0;
+
+    for (k = 0; k < 4; k++) /* in zigzag scan order */
+    {
+        idx = ((k >> 1) << 6) + ((k & 1) << 2);
+        data = block[idx];
+        if (data > 0)
+        {
+            lev = data * quant + (qp_const << 1);
+        }
+        else
+        {
+            lev = -data * quant + (qp_const << 1);
+        }
+        lev >>= (q_bits + 1);
+        if (lev)
+        {
+            if (data > 0)
+            {
+                level[ncoeff] = lev;
+                block[idx] = lev;
+            }
+            else
+            {
+                level[ncoeff] = -lev;
+                block[idx] = -lev;
+            }
+            run[ncoeff++] = zero_run;
+            zero_run = 0;
+        }
+        else
+        {
+            zero_run++;
+            block[idx] = 0;
+        }
+    }
+    return ncoeff;
+}
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp b/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
new file mode 100644
index 0000000..38a2a15
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
@@ -0,0 +1,622 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+/* 3/29/01 fast half-pel search based on neighboring guess */
+/* value ranging from 0 to 4, high complexity (more accurate) to
+   low complexity (less accurate) */
+#define HP_DISTANCE_TH      5 // 2  /* half-pel distance threshold */
+
+#define PREF_16_VEC 129     /* 1MV bias versus 4MVs*/
+
+const static int distance_tab[9][9] =   /* [hp_guess][k] */
+{
+    {0, 1, 1, 1, 1, 1, 1, 1, 1},
+    {1, 0, 1, 2, 3, 4, 3, 2, 1},
+    {1, 0, 0, 0, 1, 2, 3, 2, 1},
+    {1, 2, 1, 0, 1, 2, 3, 4, 3},
+    {1, 2, 1, 0, 0, 0, 1, 2, 3},
+    {1, 4, 3, 2, 1, 0, 1, 2, 3},
+    {1, 2, 3, 2, 1, 0, 0, 0, 1},
+    {1, 2, 3, 4, 3, 2, 1, 0, 1},
+    {1, 0, 1, 2, 3, 2, 1, 0, 0}
+};
+
+#define CLIP_RESULT(x)      if((uint)x > 0xFF){ \
+                 x = 0xFF & (~(x>>31));}
+
+#define CLIP_UPPER16(x)     if((uint)x >= 0x20000000){ \
+        x = 0xFF0000 & (~(x>>31));} \
+        else { \
+        x = (x>>5)&0xFF0000; \
+        }
+
+/*=====================================================================
+    Function:   AVCFindHalfPelMB
+    Date:       10/31/2007
+    Purpose:    Find half pel resolution MV surrounding the full-pel MV
+=====================================================================*/
+
+int AVCFindHalfPelMB(AVCEncObject *encvid, uint8 *cur, AVCMV *mot, uint8 *ncand,
+                     int xpos, int ypos, int hp_guess, int cmvx, int cmvy)
+{
+    AVCPictureData *currPic = encvid->common->currPic;
+    int lx = currPic->pitch;
+    int d, dmin, satd_min;
+    uint8* cand;
+    int lambda_motion = encvid->lambda_motion;
+    uint8 *mvbits = encvid->mvbits;
+    int mvcost;
+    /* list of candidate to go through for half-pel search*/
+    uint8 *subpel_pred = (uint8*) encvid->subpel_pred; // all 16 sub-pel positions
+    uint8 **hpel_cand = (uint8**) encvid->hpel_cand; /* half-pel position */
+
+    int xh[9] = {0, 0, 2, 2, 2, 0, -2, -2, -2};
+    int yh[9] = {0, -2, -2, 0, 2, 2, 2, 0, -2};
+    int xq[8] = {0, 1, 1, 1, 0, -1, -1, -1};
+    int yq[8] = { -1, -1, 0, 1, 1, 1, 0, -1};
+    int h, hmin, q, qmin;
+
+    OSCL_UNUSED_ARG(xpos);
+    OSCL_UNUSED_ARG(ypos);
+    OSCL_UNUSED_ARG(hp_guess);
+
+    GenerateHalfPelPred(subpel_pred, ncand, lx);
+
+    cur = encvid->currYMB; // pre-load current original MB
+
+    cand = hpel_cand[0];
+
+    // find cost for the current full-pel position
+    dmin = SATD_MB(cand, cur, 65535); // get Hadamaard transform SAD
+    mvcost = MV_COST_S(lambda_motion, mot->x, mot->y, cmvx, cmvy);
+    satd_min = dmin;
+    dmin += mvcost;
+    hmin = 0;
+
+    /* find half-pel */
+    for (h = 1; h < 9; h++)
+    {
+        d = SATD_MB(hpel_cand[h], cur, dmin);
+        mvcost = MV_COST_S(lambda_motion, mot->x + xh[h], mot->y + yh[h], cmvx, cmvy);
+        d += mvcost;
+
+        if (d < dmin)
+        {
+            dmin = d;
+            hmin = h;
+            satd_min = d - mvcost;
+        }
+    }
+
+    mot->sad = dmin;
+    mot->x += xh[hmin];
+    mot->y += yh[hmin];
+    encvid->best_hpel_pos = hmin;
+
+    /*** search for quarter-pel ****/
+    GenerateQuartPelPred(encvid->bilin_base[hmin], &(encvid->qpel_cand[0][0]), hmin);
+
+    encvid->best_qpel_pos = qmin = -1;
+
+    for (q = 0; q < 8; q++)
+    {
+        d = SATD_MB(encvid->qpel_cand[q], cur, dmin);
+        mvcost = MV_COST_S(lambda_motion, mot->x + xq[q], mot->y + yq[q], cmvx, cmvy);
+        d += mvcost;
+        if (d < dmin)
+        {
+            dmin = d;
+            qmin = q;
+            satd_min = d - mvcost;
+        }
+    }
+
+    if (qmin != -1)
+    {
+        mot->sad = dmin;
+        mot->x += xq[qmin];
+        mot->y += yq[qmin];
+        encvid->best_qpel_pos = qmin;
+    }
+
+    return satd_min;
+}
+
+
+
+/** This function generates sub-pel prediction around the full-pel candidate.
+Each sub-pel position array is 20 pixel wide (for word-alignment) and 17 pixel tall. */
+/** The sub-pel position is labeled in spiral manner from the center. */
+
+void GenerateHalfPelPred(uint8* subpel_pred, uint8 *ncand, int lx)
+{
+    /* let's do straightforward way first */
+    uint8 *ref;
+    uint8 *dst;
+    uint8 tmp8;
+    int32 tmp32;
+    int16 tmp_horz[18*22], *dst_16, *src_16;
+    register int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; // temp register
+    int msk;
+    int i, j;
+
+    /* first copy full-pel to the first array */
+    /* to be optimized later based on byte-offset load */
+    ref = ncand - 3 - lx - (lx << 1); /* move back (-3,-3) */
+    dst = subpel_pred;
+
+    dst -= 4; /* offset */
+    for (j = 0; j < 22; j++) /* 24x22 */
+    {
+        i = 6;
+        while (i > 0)
+        {
+            tmp32 = *ref++;
+            tmp8 = *ref++;
+            tmp32 |= (tmp8 << 8);
+            tmp8 = *ref++;
+            tmp32 |= (tmp8 << 16);
+            tmp8 = *ref++;
+            tmp32 |= (tmp8 << 24);
+            *((uint32*)(dst += 4)) = tmp32;
+            i--;
+        }
+        ref += (lx - 24);
+    }
+
+    /* from the first array, we do horizontal interp */
+    ref = subpel_pred + 2;
+    dst_16 = tmp_horz; /* 17 x 22 */
+
+    for (j = 4; j > 0; j--)
+    {
+        for (i = 16; i > 0; i -= 4)
+        {
+            a = ref[-2];
+            b = ref[-1];
+            c = ref[0];
+            d = ref[1];
+            e = ref[2];
+            f = ref[3];
+            *dst_16++ = a + f - 5 * (b + e) + 20 * (c + d);
+            a = ref[4];
+            *dst_16++ = b + a - 5 * (c + f) + 20 * (d + e);
+            b = ref[5];
+            *dst_16++ = c + b - 5 * (d + a) + 20 * (e + f);
+            c = ref[6];
+            *dst_16++ = d + c - 5 * (e + b) + 20 * (f + a);
+
+            ref += 4;
+        }
+        /* do the 17th column here */
+        d = ref[3];
+        *dst_16 =  e + d - 5 * (f + c) + 20 * (a + b);
+        dst_16 += 2; /* stride for tmp_horz is 18 */
+        ref += 8;  /* stride for ref is 24 */
+        if (j == 3)  // move 18 lines down
+        {
+            dst_16 += 324;//18*18;
+            ref += 432;//18*24;
+        }
+    }
+
+    ref -= 480;//20*24;
+    dst_16 -= 360;//20*18;
+    dst = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE; /* go to the 14th array 17x18*/
+
+    for (j = 18; j > 0; j--)
+    {
+        for (i = 16; i > 0; i -= 4)
+        {
+            a = ref[-2];
+            b = ref[-1];
+            c = ref[0];
+            d = ref[1];
+            e = ref[2];
+            f = ref[3];
+            tmp32 = a + f - 5 * (b + e) + 20 * (c + d);
+            *dst_16++ = tmp32;
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *dst++ = tmp32;
+
+            a = ref[4];
+            tmp32 = b + a - 5 * (c + f) + 20 * (d + e);
+            *dst_16++ = tmp32;
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *dst++ = tmp32;
+
+            b = ref[5];
+            tmp32 = c + b - 5 * (d + a) + 20 * (e + f);
+            *dst_16++ = tmp32;
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *dst++ = tmp32;
+
+            c = ref[6];
+            tmp32 = d + c - 5 * (e + b) + 20 * (f + a);
+            *dst_16++ = tmp32;
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *dst++ = tmp32;
+
+            ref += 4;
+        }
+        /* do the 17th column here */
+        d = ref[3];
+        tmp32 =  e + d - 5 * (f + c) + 20 * (a + b);
+        *dst_16 = tmp32;
+        tmp32 = (tmp32 + 16) >> 5;
+        CLIP_RESULT(tmp32)
+        *dst = tmp32;
+
+        dst += 8;  /* stride for dst is 24 */
+        dst_16 += 2; /* stride for tmp_horz is 18 */
+        ref += 8;  /* stride for ref is 24 */
+    }
+
+
+    /* Do middle point filtering*/
+    src_16 = tmp_horz; /* 17 x 22 */
+    dst = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE; /* 12th array 17x17*/
+    dst -= 24; // offset
+    for (i = 0; i < 17; i++)
+    {
+        for (j = 16; j > 0; j -= 4)
+        {
+            a = *src_16;
+            b = *(src_16 += 18);
+            c = *(src_16 += 18);
+            d = *(src_16 += 18);
+            e = *(src_16 += 18);
+            f = *(src_16 += 18);
+
+            tmp32 = a + f - 5 * (b + e) + 20 * (c + d);
+            tmp32 = (tmp32 + 512) >> 10;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;
+
+            a = *(src_16 += 18);
+            tmp32 = b + a - 5 * (c + f) + 20 * (d + e);
+            tmp32 = (tmp32 + 512) >> 10;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;
+
+            b = *(src_16 += 18);
+            tmp32 = c + b - 5 * (d + a) + 20 * (e + f);
+            tmp32 = (tmp32 + 512) >> 10;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;
+
+            c = *(src_16 += 18);
+            tmp32 = d + c - 5 * (e + b) + 20 * (f + a);
+            tmp32 = (tmp32 + 512) >> 10;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;
+
+            src_16 -= (18 << 2);
+        }
+
+        d = src_16[90]; // 18*5
+        tmp32 = e + d - 5 * (f + c) + 20 * (a + b);
+        tmp32 = (tmp32 + 512) >> 10;
+        CLIP_RESULT(tmp32)
+        dst[24] = tmp32;
+
+        src_16 -= ((18 << 4) - 1);
+        dst -= ((24 << 4) - 1);
+    }
+
+    /* do vertical interpolation */
+    ref = subpel_pred + 2;
+    dst = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE; /* 10th array 18x17 */
+    dst -= 24; // offset
+
+    for (i = 2; i > 0; i--)
+    {
+        for (j = 16; j > 0; j -= 4)
+        {
+            a = *ref;
+            b = *(ref += 24);
+            c = *(ref += 24);
+            d = *(ref += 24);
+            e = *(ref += 24);
+            f = *(ref += 24);
+
+            tmp32 = a + f - 5 * (b + e) + 20 * (c + d);
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;  // 10th
+
+            a = *(ref += 24);
+            tmp32 = b + a - 5 * (c + f) + 20 * (d + e);
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;  // 10th
+
+            b = *(ref += 24);
+            tmp32 = c + b - 5 * (d + a) + 20 * (e + f);
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;  // 10th
+
+            c = *(ref += 24);
+            tmp32 = d + c - 5 * (e + b) + 20 * (f + a);
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;  // 10th
+
+            ref -= (24 << 2);
+        }
+
+        d = ref[120]; // 24*5
+        tmp32 = e + d - 5 * (f + c) + 20 * (a + b);
+        tmp32 = (tmp32 + 16) >> 5;
+        CLIP_RESULT(tmp32)
+        dst[24] = tmp32;  // 10th
+
+        dst -= ((24 << 4) - 1);
+        ref -= ((24 << 4) - 1);
+    }
+
+    // note that using SIMD here doesn't help much, the cycle almost stays the same
+    // one can just use the above code and change the for(i=2 to for(i=18
+    for (i = 16; i > 0; i -= 4)
+    {
+        msk = 0;
+        for (j = 17; j > 0; j--)
+        {
+            a = *((uint32*)ref); /* load 4 bytes */
+            b = (a >> 8) & 0xFF00FF; /* second and fourth byte */
+            a &= 0xFF00FF;
+
+            c = *((uint32*)(ref + 120));
+            d = (c >> 8) & 0xFF00FF;
+            c &= 0xFF00FF;
+
+            a += c;
+            b += d;
+
+            e = *((uint32*)(ref + 72)); /* e, f */
+            f = (e >> 8) & 0xFF00FF;
+            e &= 0xFF00FF;
+
+            c = *((uint32*)(ref + 48)); /* c, d */
+            d = (c >> 8) & 0xFF00FF;
+            c &= 0xFF00FF;
+
+            c += e;
+            d += f;
+
+            a += 20 * c;
+            b += 20 * d;
+            a += 0x100010;
+            b += 0x100010;
+
+            e = *((uint32*)(ref += 24)); /* e, f */
+            f = (e >> 8) & 0xFF00FF;
+            e &= 0xFF00FF;
+
+            c = *((uint32*)(ref + 72)); /* c, d */
+            d = (c >> 8) & 0xFF00FF;
+            c &= 0xFF00FF;
+
+            c += e;
+            d += f;
+
+            a -= 5 * c;
+            b -= 5 * d;
+
+            c = a << 16;
+            d = b << 16;
+            CLIP_UPPER16(a)
+            CLIP_UPPER16(c)
+            CLIP_UPPER16(b)
+            CLIP_UPPER16(d)
+
+            a |= (c >> 16);
+            b |= (d >> 16);
+            //  a>>=5;
+            //  b>>=5;
+            /* clip */
+            //  msk |= b;  msk|=a;
+            //  a &= 0xFF00FF;
+            //  b &= 0xFF00FF;
+            a |= (b << 8);  /* pack it back */
+
+            *((uint16*)(dst += 24)) = a & 0xFFFF; //dst is not word-aligned.
+            *((uint16*)(dst + 2)) = a >> 16;
+
+        }
+        dst -= 404; // 24*17-4
+        ref -= 404;
+        /*      if(msk & 0xFF00FF00) // need clipping
+                {
+                    VertInterpWClip(dst,ref); // re-do 4 column with clip
+                }*/
+    }
+
+    return ;
+}
+
+void VertInterpWClip(uint8 *dst, uint8 *ref)
+{
+    int i, j;
+    int a, b, c, d, e, f;
+    int32 tmp32;
+
+    dst -= 4;
+    ref -= 4;
+
+    for (i = 4; i > 0; i--)
+    {
+        for (j = 16; j > 0; j -= 4)
+        {
+            a = *ref;
+            b = *(ref += 24);
+            c = *(ref += 24);
+            d = *(ref += 24);
+            e = *(ref += 24);
+            f = *(ref += 24);
+
+            tmp32 = a + f - 5 * (b + e) + 20 * (c + d);
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;  // 10th
+
+            a = *(ref += 24);
+            tmp32 = b + a - 5 * (c + f) + 20 * (d + e);
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;  // 10th
+
+            b = *(ref += 24);
+            tmp32 = c + b - 5 * (d + a) + 20 * (e + f);
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;  // 10th
+
+            c = *(ref += 24);
+            tmp32 = d + c - 5 * (e + b) + 20 * (f + a);
+            tmp32 = (tmp32 + 16) >> 5;
+            CLIP_RESULT(tmp32)
+            *(dst += 24) = tmp32;  // 10th
+
+            ref -= (24 << 2);
+        }
+
+        d = ref[120]; // 24*5
+        tmp32 = e + d - 5 * (f + c) + 20 * (a + b);
+        tmp32 = (tmp32 + 16) >> 5;
+        CLIP_RESULT(tmp32)
+        dst[24] = tmp32;  // 10th
+
+        dst -= ((24 << 4) - 1);
+        ref -= ((24 << 4) - 1);
+    }
+
+    return ;
+}
+
+
+void GenerateQuartPelPred(uint8 **bilin_base, uint8 *qpel_cand, int hpel_pos)
+{
+    // for even value of hpel_pos, start with pattern 1, otherwise, start with pattern 2
+    int i, j;
+
+    uint8 *c1 = qpel_cand;
+    uint8 *tl = bilin_base[0];
+    uint8 *tr = bilin_base[1];
+    uint8 *bl = bilin_base[2];
+    uint8 *br = bilin_base[3];
+    int a, b, c, d;
+    int offset = 1 - (384 * 7);
+
+    if (!(hpel_pos&1)) // diamond pattern
+    {
+        j = 16;
+        while (j--)
+        {
+            i = 16;
+            while (i--)
+            {
+                d = tr[24];
+                a = *tr++;
+                b = bl[1];
+                c = *br++;
+
+                *c1 = (c + a + 1) >> 1;
+                *(c1 += 384) = (b + a + 1) >> 1; /* c2 */
+                *(c1 += 384) = (b + c + 1) >> 1; /* c3 */
+                *(c1 += 384) = (b + d + 1) >> 1; /* c4 */
+
+                b = *bl++;
+
+                *(c1 += 384) = (c + d + 1) >> 1;  /* c5 */
+                *(c1 += 384) = (b + d + 1) >> 1;  /* c6 */
+                *(c1 += 384) = (b + c + 1) >> 1;  /* c7 */
+                *(c1 += 384) = (b + a + 1) >> 1;  /* c8 */
+
+                c1 += offset;
+            }
+            // advance to the next line, pitch is 24
+            tl += 8;
+            tr += 8;
+            bl += 8;
+            br += 8;
+            c1 += 8;
+        }
+    }
+    else // star pattern
+    {
+        j = 16;
+        while (j--)
+        {
+            i = 16;
+            while (i--)
+            {
+                a = *br++;
+                b = *tr++;
+                c = tl[1];
+                *c1 = (a + b + 1) >> 1;
+                b = bl[1];
+                *(c1 += 384) = (a + c + 1) >> 1; /* c2 */
+                c = tl[25];
+                *(c1 += 384) = (a + b + 1) >> 1; /* c3 */
+                b = tr[23];
+                *(c1 += 384) = (a + c + 1) >> 1; /* c4 */
+                c = tl[24];
+                *(c1 += 384) = (a + b + 1) >> 1; /* c5 */
+                b = *bl++;
+                *(c1 += 384) = (a + c + 1) >> 1; /* c6 */
+                c = *tl++;
+                *(c1 += 384) = (a + b + 1) >> 1; /* c7 */
+                *(c1 += 384) = (a + c + 1) >> 1; /* c8 */
+
+                c1 += offset;
+            }
+            // advance to the next line, pitch is 24
+            tl += 8;
+            tr += 8;
+            bl += 8;
+            br += 8;
+            c1 += 8;
+        }
+    }
+
+    return ;
+}
+
+
+/* assuming cand always has a pitch of 24 */
+int SATD_MB(uint8 *cand, uint8 *cur, int dmin)
+{
+    int cost;
+
+
+    dmin = (dmin << 16) | 24;
+    cost = AVCSAD_Macroblock_C(cand, cur, dmin, NULL);
+
+    return cost;
+}
+
+
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/header.cpp b/media/libstagefright/codecs/avc/enc/src/header.cpp
new file mode 100644
index 0000000..9acff9e
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/header.cpp
@@ -0,0 +1,917 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include "avcenc_api.h"
+
+/** see subclause 7.4.2.1 */
+/* no need for checking the valid range , already done in SetEncodeParam(),
+if we have to send another SPS, the ranges should be verified first before
+users call PVAVCEncodeSPS() */
+AVCEnc_Status EncodeSPS(AVCEncObject *encvid, AVCEncBitstream *stream)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCSeqParamSet *seqParam = video->currSeqParams;
+    AVCVUIParams *vui = &(seqParam->vui_parameters);
+    int i;
+    AVCEnc_Status status = AVCENC_SUCCESS;
+
+    //DEBUG_LOG(userData,AVC_LOGTYPE_INFO,"EncodeSPS",-1,-1);
+
+    status = BitstreamWriteBits(stream, 8, seqParam->profile_idc);
+    status = BitstreamWrite1Bit(stream, seqParam->constrained_set0_flag);
+    status = BitstreamWrite1Bit(stream, seqParam->constrained_set1_flag);
+    status = BitstreamWrite1Bit(stream, seqParam->constrained_set2_flag);
+    status = BitstreamWrite1Bit(stream, seqParam->constrained_set3_flag);
+    status = BitstreamWriteBits(stream, 4, 0);  /* forbidden zero bits */
+    if (status != AVCENC_SUCCESS)  /* we can check after each write also */
+    {
+        return status;
+    }
+
+    status = BitstreamWriteBits(stream, 8, seqParam->level_idc);
+    status = ue_v(stream, seqParam->seq_parameter_set_id);
+    status = ue_v(stream, seqParam->log2_max_frame_num_minus4);
+    status = ue_v(stream, seqParam->pic_order_cnt_type);
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    if (seqParam->pic_order_cnt_type == 0)
+    {
+        status = ue_v(stream, seqParam->log2_max_pic_order_cnt_lsb_minus4);
+    }
+    else if (seqParam->pic_order_cnt_type == 1)
+    {
+        status = BitstreamWrite1Bit(stream, seqParam->delta_pic_order_always_zero_flag);
+        status = se_v(stream, seqParam->offset_for_non_ref_pic); /* upto 32 bits */
+        status = se_v(stream, seqParam->offset_for_top_to_bottom_field); /* upto 32 bits */
+        status = ue_v(stream, seqParam->num_ref_frames_in_pic_order_cnt_cycle);
+
+        for (i = 0; i < (int)(seqParam->num_ref_frames_in_pic_order_cnt_cycle); i++)
+        {
+            status = se_v(stream, seqParam->offset_for_ref_frame[i]); /* upto 32 bits */
+        }
+    }
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    status = ue_v(stream, seqParam->num_ref_frames);
+    status = BitstreamWrite1Bit(stream, seqParam->gaps_in_frame_num_value_allowed_flag);
+    status = ue_v(stream, seqParam->pic_width_in_mbs_minus1);
+    status = ue_v(stream, seqParam->pic_height_in_map_units_minus1);
+    status = BitstreamWrite1Bit(stream, seqParam->frame_mbs_only_flag);
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+    /* if frame_mbs_only_flag is 0, then write, mb_adaptive_frame_field_frame here */
+
+    status = BitstreamWrite1Bit(stream, seqParam->direct_8x8_inference_flag);
+    status = BitstreamWrite1Bit(stream, seqParam->frame_cropping_flag);
+    if (seqParam->frame_cropping_flag)
+    {
+        status = ue_v(stream, seqParam->frame_crop_left_offset);
+        status = ue_v(stream, seqParam->frame_crop_right_offset);
+        status = ue_v(stream, seqParam->frame_crop_top_offset);
+        status = ue_v(stream, seqParam->frame_crop_bottom_offset);
+    }
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    status = BitstreamWrite1Bit(stream, seqParam->vui_parameters_present_flag);
+    if (seqParam->vui_parameters_present_flag)
+    {
+        /* not supported */
+        //return AVCENC_SPS_FAIL;
+        EncodeVUI(stream, vui);
+    }
+
+    return status;
+}
+
+
+void EncodeVUI(AVCEncBitstream* stream, AVCVUIParams* vui)
+{
+    int temp;
+
+    temp = vui->aspect_ratio_info_present_flag;
+    BitstreamWrite1Bit(stream, temp);
+    if (temp)
+    {
+        BitstreamWriteBits(stream, 8, vui->aspect_ratio_idc);
+        if (vui->aspect_ratio_idc == 255)
+        {
+            BitstreamWriteBits(stream, 16, vui->sar_width);
+            BitstreamWriteBits(stream, 16, vui->sar_height);
+        }
+    }
+    temp = vui->overscan_info_present_flag;
+    BitstreamWrite1Bit(stream, temp);
+    if (temp)
+    {
+        BitstreamWrite1Bit(stream, vui->overscan_appropriate_flag);
+    }
+    temp = vui->video_signal_type_present_flag;
+    BitstreamWrite1Bit(stream, temp);
+    if (temp)
+    {
+        BitstreamWriteBits(stream, 3, vui->video_format);
+        BitstreamWrite1Bit(stream, vui->video_full_range_flag);
+        temp = vui->colour_description_present_flag;
+        BitstreamWrite1Bit(stream, temp);
+        if (temp)
+        {
+            BitstreamWriteBits(stream, 8, vui->colour_primaries);
+            BitstreamWriteBits(stream, 8, vui->transfer_characteristics);
+            BitstreamWriteBits(stream, 8, vui->matrix_coefficients);
+        }
+    }
+    temp = vui->chroma_location_info_present_flag;
+    BitstreamWrite1Bit(stream, temp);
+    if (temp)
+    {
+        ue_v(stream, vui->chroma_sample_loc_type_top_field);
+        ue_v(stream, vui->chroma_sample_loc_type_bottom_field);
+    }
+
+    temp = vui->timing_info_present_flag;
+    BitstreamWrite1Bit(stream, temp);
+    if (temp)
+    {
+        BitstreamWriteBits(stream, 32, vui->num_units_in_tick);
+        BitstreamWriteBits(stream, 32, vui->time_scale);
+        BitstreamWrite1Bit(stream, vui->fixed_frame_rate_flag);
+    }
+
+    temp = vui->nal_hrd_parameters_present_flag;
+    BitstreamWrite1Bit(stream, temp);
+    if (temp)
+    {
+        EncodeHRD(stream, &(vui->nal_hrd_parameters));
+    }
+    temp = vui->vcl_hrd_parameters_present_flag;
+    BitstreamWrite1Bit(stream, temp);
+    if (temp)
+    {
+        EncodeHRD(stream, &(vui->vcl_hrd_parameters));
+    }
+    if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag)
+    {
+        BitstreamWrite1Bit(stream, vui->low_delay_hrd_flag);
+    }
+    BitstreamWrite1Bit(stream, vui->pic_struct_present_flag);
+    temp = vui->bitstream_restriction_flag;
+    BitstreamWrite1Bit(stream, temp);
+    if (temp)
+    {
+        BitstreamWrite1Bit(stream, vui->motion_vectors_over_pic_boundaries_flag);
+        ue_v(stream, vui->max_bytes_per_pic_denom);
+        ue_v(stream, vui->max_bits_per_mb_denom);
+        ue_v(stream, vui->log2_max_mv_length_horizontal);
+        ue_v(stream, vui->log2_max_mv_length_vertical);
+        ue_v(stream, vui->max_dec_frame_reordering);
+        ue_v(stream, vui->max_dec_frame_buffering);
+    }
+
+    return ;
+}
+
+
+void EncodeHRD(AVCEncBitstream* stream, AVCHRDParams* hrd)
+{
+    int i;
+
+    ue_v(stream, hrd->cpb_cnt_minus1);
+    BitstreamWriteBits(stream, 4, hrd->bit_rate_scale);
+    BitstreamWriteBits(stream, 4, hrd->cpb_size_scale);
+    for (i = 0; i <= (int)hrd->cpb_cnt_minus1; i++)
+    {
+        ue_v(stream, hrd->bit_rate_value_minus1[i]);
+        ue_v(stream, hrd->cpb_size_value_minus1[i]);
+        ue_v(stream, hrd->cbr_flag[i]);
+    }
+    BitstreamWriteBits(stream, 5, hrd->initial_cpb_removal_delay_length_minus1);
+    BitstreamWriteBits(stream, 5, hrd->cpb_removal_delay_length_minus1);
+    BitstreamWriteBits(stream, 5, hrd->dpb_output_delay_length_minus1);
+    BitstreamWriteBits(stream, 5, hrd->time_offset_length);
+
+    return ;
+}
+
+
+
+/** see subclause 7.4.2.2 */
+/* no need for checking the valid range , already done in SetEncodeParam().
+If we have to send another SPS, the ranges should be verified first before
+users call PVAVCEncodeSPS()*/
+AVCEnc_Status EncodePPS(AVCEncObject *encvid, AVCEncBitstream *stream)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    AVCPicParamSet *picParam = video->currPicParams;
+    int i, iGroup, numBits;
+    uint temp;
+
+    status = ue_v(stream, picParam->pic_parameter_set_id);
+    status = ue_v(stream, picParam->seq_parameter_set_id);
+    status = BitstreamWrite1Bit(stream, picParam->entropy_coding_mode_flag);
+    status = BitstreamWrite1Bit(stream, picParam->pic_order_present_flag);
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    status = ue_v(stream, picParam->num_slice_groups_minus1);
+    if (picParam->num_slice_groups_minus1 > 0)
+    {
+        status = ue_v(stream, picParam->slice_group_map_type);
+        if (picParam->slice_group_map_type == 0)
+        {
+            for (iGroup = 0; iGroup <= (int)picParam->num_slice_groups_minus1; iGroup++)
+            {
+                status = ue_v(stream, picParam->run_length_minus1[iGroup]);
+            }
+        }
+        else if (picParam->slice_group_map_type == 2)
+        {
+            for (iGroup = 0; iGroup < (int)picParam->num_slice_groups_minus1; iGroup++)
+            {
+                status = ue_v(stream, picParam->top_left[iGroup]);
+                status = ue_v(stream, picParam->bottom_right[iGroup]);
+            }
+        }
+        else if (picParam->slice_group_map_type == 3 ||
+                 picParam->slice_group_map_type == 4 ||
+                 picParam->slice_group_map_type == 5)
+        {
+            status = BitstreamWrite1Bit(stream, picParam->slice_group_change_direction_flag);
+            status = ue_v(stream, picParam->slice_group_change_rate_minus1);
+        }
+        else /*if(picParam->slice_group_map_type == 6)*/
+        {
+            status = ue_v(stream, picParam->pic_size_in_map_units_minus1);
+
+            numBits = 0;/* ceil(log2(num_slice_groups_minus1+1)) bits */
+            i = picParam->num_slice_groups_minus1;
+            while (i > 0)
+            {
+                numBits++;
+                i >>= 1;
+            }
+
+            for (i = 0; i <= (int)picParam->pic_size_in_map_units_minus1; i++)
+            {
+                status = BitstreamWriteBits(stream, numBits, picParam->slice_group_id[i]);
+            }
+        }
+    }
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    status = ue_v(stream, picParam->num_ref_idx_l0_active_minus1);
+    status = ue_v(stream, picParam->num_ref_idx_l1_active_minus1);
+    status = BitstreamWrite1Bit(stream, picParam->weighted_pred_flag);
+    status = BitstreamWriteBits(stream, 2, picParam->weighted_bipred_idc);
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    status = se_v(stream, picParam->pic_init_qp_minus26);
+    status = se_v(stream, picParam->pic_init_qs_minus26);
+    status = se_v(stream, picParam->chroma_qp_index_offset);
+
+    temp = picParam->deblocking_filter_control_present_flag << 2;
+    temp |= (picParam->constrained_intra_pred_flag << 1);
+    temp |= picParam->redundant_pic_cnt_present_flag;
+
+    status = BitstreamWriteBits(stream, 3, temp);
+
+    return status;
+}
+
+/** see subclause 7.4.3 */
+AVCEnc_Status EncodeSliceHeader(AVCEncObject *encvid, AVCEncBitstream *stream)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    AVCPicParamSet *currPPS = video->currPicParams;
+    AVCSeqParamSet *currSPS = video->currSeqParams;
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    int slice_type, temp, i;
+    int num_bits;
+
+    num_bits = (stream->write_pos << 3) - stream->bit_left;
+
+    status = ue_v(stream, sliceHdr->first_mb_in_slice);
+
+    slice_type = video->slice_type;
+
+    if (video->mbNum == 0) /* first mb in frame */
+    {
+        status = ue_v(stream, sliceHdr->slice_type);
+    }
+    else
+    {
+        status = ue_v(stream, slice_type);
+    }
+
+    status = ue_v(stream, sliceHdr->pic_parameter_set_id);
+
+    status = BitstreamWriteBits(stream, currSPS->log2_max_frame_num_minus4 + 4, sliceHdr->frame_num);
+
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+    /* if frame_mbs_only_flag is 0, encode field_pic_flag, bottom_field_flag here */
+
+    if (video->nal_unit_type == AVC_NALTYPE_IDR)
+    {
+        status = ue_v(stream, sliceHdr->idr_pic_id);
+    }
+
+    if (currSPS->pic_order_cnt_type == 0)
+    {
+        status = BitstreamWriteBits(stream, currSPS->log2_max_pic_order_cnt_lsb_minus4 + 4,
+                                    sliceHdr->pic_order_cnt_lsb);
+
+        if (currPPS->pic_order_present_flag && !sliceHdr->field_pic_flag)
+        {
+            status = se_v(stream, sliceHdr->delta_pic_order_cnt_bottom); /* 32 bits */
+        }
+    }
+    if (currSPS->pic_order_cnt_type == 1 && !currSPS->delta_pic_order_always_zero_flag)
+    {
+        status = se_v(stream, sliceHdr->delta_pic_order_cnt[0]);    /* 32 bits */
+        if (currPPS->pic_order_present_flag && !sliceHdr->field_pic_flag)
+        {
+            status = se_v(stream, sliceHdr->delta_pic_order_cnt[1]); /* 32 bits */
+        }
+    }
+
+    if (currPPS->redundant_pic_cnt_present_flag)
+    {
+        status = ue_v(stream, sliceHdr->redundant_pic_cnt);
+    }
+
+    if (slice_type == AVC_B_SLICE)
+    {
+        status = BitstreamWrite1Bit(stream, sliceHdr->direct_spatial_mv_pred_flag);
+    }
+
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    if (slice_type == AVC_P_SLICE || slice_type == AVC_SP_SLICE || slice_type == AVC_B_SLICE)
+    {
+        status = BitstreamWrite1Bit(stream, sliceHdr->num_ref_idx_active_override_flag);
+        if (sliceHdr->num_ref_idx_active_override_flag)
+        {
+            /* we shouldn't enter this part at all */
+            status = ue_v(stream, sliceHdr->num_ref_idx_l0_active_minus1);
+            if (slice_type == AVC_B_SLICE)
+            {
+                status = ue_v(stream, sliceHdr->num_ref_idx_l1_active_minus1);
+            }
+        }
+    }
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    /* ref_pic_list_reordering() */
+    status = ref_pic_list_reordering(video, stream, sliceHdr, slice_type);
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    if ((currPPS->weighted_pred_flag && (slice_type == AVC_P_SLICE || slice_type == AVC_SP_SLICE)) ||
+            (currPPS->weighted_bipred_idc == 1 && slice_type == AVC_B_SLICE))
+    {
+        //      pred_weight_table(); // not supported !!
+        return AVCENC_PRED_WEIGHT_TAB_FAIL;
+    }
+
+    if (video->nal_ref_idc != 0)
+    {
+        status = dec_ref_pic_marking(video, stream, sliceHdr);
+        if (status != AVCENC_SUCCESS)
+        {
+            return status;
+        }
+    }
+
+    if (currPPS->entropy_coding_mode_flag && slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE)
+    {
+        return AVCENC_CABAC_FAIL;
+        /*      ue_v(stream,&(sliceHdr->cabac_init_idc));
+                if(sliceHdr->cabac_init_idc > 2){
+                    // not supported !!!!
+                }*/
+    }
+
+    status = se_v(stream, sliceHdr->slice_qp_delta);
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    if (slice_type == AVC_SP_SLICE || slice_type == AVC_SI_SLICE)
+    {
+        if (slice_type == AVC_SP_SLICE)
+        {
+            status = BitstreamWrite1Bit(stream, sliceHdr->sp_for_switch_flag);
+            /* if sp_for_switch_flag is 0, P macroblocks in SP slice is decoded using
+            SP decoding process for non-switching pictures in 8.6.1 */
+            /* else, P macroblocks in SP slice is decoded using SP and SI decoding
+            process for switching picture in 8.6.2 */
+        }
+        status = se_v(stream, sliceHdr->slice_qs_delta);
+        if (status != AVCENC_SUCCESS)
+        {
+            return status;
+        }
+    }
+
+    if (currPPS->deblocking_filter_control_present_flag)
+    {
+
+        status = ue_v(stream, sliceHdr->disable_deblocking_filter_idc);
+
+        if (sliceHdr->disable_deblocking_filter_idc != 1)
+        {
+            status = se_v(stream, sliceHdr->slice_alpha_c0_offset_div2);
+
+            status = se_v(stream, sliceHdr->slice_beta_offset_div_2);
+        }
+        if (status != AVCENC_SUCCESS)
+        {
+            return status;
+        }
+    }
+
+    if (currPPS->num_slice_groups_minus1 > 0 && currPPS->slice_group_map_type >= 3
+            && currPPS->slice_group_map_type <= 5)
+    {
+        /* Ceil(Log2(PicSizeInMapUnits/(float)SliceGroupChangeRate + 1)) */
+        temp = video->PicSizeInMapUnits / video->SliceGroupChangeRate;
+        if (video->PicSizeInMapUnits % video->SliceGroupChangeRate)
+        {
+            temp++;
+        }
+        i = 0;
+        while (temp > 1)
+        {
+            temp >>= 1;
+            i++;
+        }
+
+        BitstreamWriteBits(stream, i, sliceHdr->slice_group_change_cycle);
+    }
+
+
+    encvid->rateCtrl->NumberofHeaderBits += (stream->write_pos << 3) - stream->bit_left - num_bits;
+
+    return AVCENC_SUCCESS;
+}
+
+/** see subclause 7.4.3.1 */
+AVCEnc_Status ref_pic_list_reordering(AVCCommonObj *video, AVCEncBitstream *stream, AVCSliceHeader *sliceHdr, int slice_type)
+{
+    (void)(video);
+    int i;
+    AVCEnc_Status status = AVCENC_SUCCESS;
+
+    if (slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE)
+    {
+        status = BitstreamWrite1Bit(stream, sliceHdr->ref_pic_list_reordering_flag_l0);
+        if (sliceHdr->ref_pic_list_reordering_flag_l0)
+        {
+            i = 0;
+            do
+            {
+                status = ue_v(stream, sliceHdr->reordering_of_pic_nums_idc_l0[i]);
+                if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 0 ||
+                        sliceHdr->reordering_of_pic_nums_idc_l0[i] == 1)
+                {
+                    status = ue_v(stream, sliceHdr->abs_diff_pic_num_minus1_l0[i]);
+                    /* this check should be in InitSlice(), if we ever use it */
+                    /*if(sliceHdr->reordering_of_pic_nums_idc_l0[i] == 0 &&
+                        sliceHdr->abs_diff_pic_num_minus1_l0[i] > video->MaxPicNum/2 -1)
+                    {
+                        return AVCENC_REF_PIC_REORDER_FAIL; // out of range
+                    }
+                    if(sliceHdr->reordering_of_pic_nums_idc_l0[i] == 1 &&
+                        sliceHdr->abs_diff_pic_num_minus1_l0[i] > video->MaxPicNum/2 -2)
+                    {
+                        return AVCENC_REF_PIC_REORDER_FAIL; // out of range
+                    }*/
+                }
+                else if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 2)
+                {
+                    status = ue_v(stream, sliceHdr->long_term_pic_num_l0[i]);
+                }
+                i++;
+            }
+            while (sliceHdr->reordering_of_pic_nums_idc_l0[i] != 3
+                    && i <= (int)sliceHdr->num_ref_idx_l0_active_minus1 + 1) ;
+        }
+    }
+    if (slice_type == AVC_B_SLICE)
+    {
+        status = BitstreamWrite1Bit(stream, sliceHdr->ref_pic_list_reordering_flag_l1);
+        if (sliceHdr->ref_pic_list_reordering_flag_l1)
+        {
+            i = 0;
+            do
+            {
+                status = ue_v(stream, sliceHdr->reordering_of_pic_nums_idc_l1[i]);
+                if (sliceHdr->reordering_of_pic_nums_idc_l1[i] == 0 ||
+                        sliceHdr->reordering_of_pic_nums_idc_l1[i] == 1)
+                {
+                    status = ue_v(stream, sliceHdr->abs_diff_pic_num_minus1_l1[i]);
+                    /* This check should be in InitSlice() if we ever use it
+                    if(sliceHdr->reordering_of_pic_nums_idc_l1[i] == 0 &&
+                        sliceHdr->abs_diff_pic_num_minus1_l1[i] > video->MaxPicNum/2 -1)
+                    {
+                        return AVCENC_REF_PIC_REORDER_FAIL; // out of range
+                    }
+                    if(sliceHdr->reordering_of_pic_nums_idc_l1[i] == 1 &&
+                        sliceHdr->abs_diff_pic_num_minus1_l1[i] > video->MaxPicNum/2 -2)
+                    {
+                        return AVCENC_REF_PIC_REORDER_FAIL; // out of range
+                    }*/
+                }
+                else if (sliceHdr->reordering_of_pic_nums_idc_l1[i] == 2)
+                {
+                    status = ue_v(stream, sliceHdr->long_term_pic_num_l1[i]);
+                }
+                i++;
+            }
+            while (sliceHdr->reordering_of_pic_nums_idc_l1[i] != 3
+                    && i <= (int)sliceHdr->num_ref_idx_l1_active_minus1 + 1) ;
+        }
+    }
+
+    return status;
+}
+
+/** see subclause 7.4.3.3 */
+AVCEnc_Status dec_ref_pic_marking(AVCCommonObj *video, AVCEncBitstream *stream, AVCSliceHeader *sliceHdr)
+{
+    int i;
+    AVCEnc_Status status = AVCENC_SUCCESS;
+
+    if (video->nal_unit_type == AVC_NALTYPE_IDR)
+    {
+        status = BitstreamWrite1Bit(stream, sliceHdr->no_output_of_prior_pics_flag);
+        status = BitstreamWrite1Bit(stream, sliceHdr->long_term_reference_flag);
+        if (sliceHdr->long_term_reference_flag == 0) /* used for short-term */
+        {
+            video->MaxLongTermFrameIdx = -1; /* no long-term frame indx */
+        }
+        else /* used for long-term */
+        {
+            video->MaxLongTermFrameIdx = 0;
+            video->LongTermFrameIdx = 0;
+        }
+    }
+    else
+    {
+        status = BitstreamWrite1Bit(stream, sliceHdr->adaptive_ref_pic_marking_mode_flag); /* default to zero */
+        if (sliceHdr->adaptive_ref_pic_marking_mode_flag)
+        {
+            i = 0;
+            do
+            {
+                status = ue_v(stream, sliceHdr->memory_management_control_operation[i]);
+                if (sliceHdr->memory_management_control_operation[i] == 1 ||
+                        sliceHdr->memory_management_control_operation[i] == 3)
+                {
+                    status = ue_v(stream, sliceHdr->difference_of_pic_nums_minus1[i]);
+                }
+                if (sliceHdr->memory_management_control_operation[i] == 2)
+                {
+                    status = ue_v(stream, sliceHdr->long_term_pic_num[i]);
+                }
+                if (sliceHdr->memory_management_control_operation[i] == 3 ||
+                        sliceHdr->memory_management_control_operation[i] == 6)
+                {
+                    status = ue_v(stream, sliceHdr->long_term_frame_idx[i]);
+                }
+                if (sliceHdr->memory_management_control_operation[i] == 4)
+                {
+                    status = ue_v(stream, sliceHdr->max_long_term_frame_idx_plus1[i]);
+                }
+                i++;
+            }
+            while (sliceHdr->memory_management_control_operation[i] != 0 && i < MAX_DEC_REF_PIC_MARKING);
+            if (i >= MAX_DEC_REF_PIC_MARKING && sliceHdr->memory_management_control_operation[i] != 0)
+            {
+                return AVCENC_DEC_REF_PIC_MARK_FAIL; /* we're screwed!!, not enough memory */
+            }
+        }
+    }
+
+    return status;
+}
+
+/* see subclause 8.2.1 Decoding process for picture order count.
+See also PostPOC() for initialization of some variables. */
+AVCEnc_Status InitPOC(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCSeqParamSet *currSPS = video->currSeqParams;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    AVCFrameIO  *currInput = encvid->currInput;
+    int i;
+
+    switch (currSPS->pic_order_cnt_type)
+    {
+        case 0: /* POC MODE 0 , subclause 8.2.1.1 */
+            /* encoding part */
+            if (video->nal_unit_type == AVC_NALTYPE_IDR)
+            {
+                encvid->dispOrdPOCRef = currInput->disp_order;
+            }
+            while (currInput->disp_order < encvid->dispOrdPOCRef)
+            {
+                encvid->dispOrdPOCRef -= video->MaxPicOrderCntLsb;
+            }
+            sliceHdr->pic_order_cnt_lsb = currInput->disp_order - encvid->dispOrdPOCRef;
+            while (sliceHdr->pic_order_cnt_lsb >= video->MaxPicOrderCntLsb)
+            {
+                sliceHdr->pic_order_cnt_lsb -= video->MaxPicOrderCntLsb;
+            }
+            /* decoding part */
+            /* Calculate the MSBs of current picture */
+            if (video->nal_unit_type == AVC_NALTYPE_IDR)
+            {
+                video->prevPicOrderCntMsb = 0;
+                video->prevPicOrderCntLsb = 0;
+            }
+            if (sliceHdr->pic_order_cnt_lsb  <  video->prevPicOrderCntLsb  &&
+                    (video->prevPicOrderCntLsb - sliceHdr->pic_order_cnt_lsb)  >= (video->MaxPicOrderCntLsb / 2))
+                video->PicOrderCntMsb = video->prevPicOrderCntMsb + video->MaxPicOrderCntLsb;
+            else if (sliceHdr->pic_order_cnt_lsb  >  video->prevPicOrderCntLsb  &&
+                     (sliceHdr->pic_order_cnt_lsb - video->prevPicOrderCntLsb)  > (video->MaxPicOrderCntLsb / 2))
+                video->PicOrderCntMsb = video->prevPicOrderCntMsb - video->MaxPicOrderCntLsb;
+            else
+                video->PicOrderCntMsb = video->prevPicOrderCntMsb;
+
+            /* JVT-I010 page 81 is different from JM7.3 */
+            if (!sliceHdr->field_pic_flag || !sliceHdr->bottom_field_flag)
+            {
+                video->PicOrderCnt = video->TopFieldOrderCnt = video->PicOrderCntMsb + sliceHdr->pic_order_cnt_lsb;
+            }
+
+            if (!sliceHdr->field_pic_flag)
+            {
+                video->BottomFieldOrderCnt = video->TopFieldOrderCnt + sliceHdr->delta_pic_order_cnt_bottom;
+            }
+            else if (sliceHdr->bottom_field_flag)
+            {
+                video->PicOrderCnt = video->BottomFieldOrderCnt = video->PicOrderCntMsb + sliceHdr->pic_order_cnt_lsb;
+            }
+
+            if (!sliceHdr->field_pic_flag)
+            {
+                video->PicOrderCnt = AVC_MIN(video->TopFieldOrderCnt, video->BottomFieldOrderCnt);
+            }
+
+            if (video->currPicParams->pic_order_present_flag && !sliceHdr->field_pic_flag)
+            {
+                sliceHdr->delta_pic_order_cnt_bottom = 0; /* defaulted to zero */
+            }
+
+            break;
+        case 1: /* POC MODE 1, subclause 8.2.1.2 */
+            /* calculate FrameNumOffset */
+            if (video->nal_unit_type == AVC_NALTYPE_IDR)
+            {
+                encvid->dispOrdPOCRef = currInput->disp_order;  /* reset the reference point */
+                video->prevFrameNumOffset = 0;
+                video->FrameNumOffset = 0;
+            }
+            else if (video->prevFrameNum > sliceHdr->frame_num)
+            {
+                video->FrameNumOffset = video->prevFrameNumOffset + video->MaxFrameNum;
+            }
+            else
+            {
+                video->FrameNumOffset = video->prevFrameNumOffset;
+            }
+            /* calculate absFrameNum */
+            if (currSPS->num_ref_frames_in_pic_order_cnt_cycle)
+            {
+                video->absFrameNum = video->FrameNumOffset + sliceHdr->frame_num;
+            }
+            else
+            {
+                video->absFrameNum = 0;
+            }
+
+            if (video->absFrameNum > 0 && video->nal_ref_idc == 0)
+            {
+                video->absFrameNum--;
+            }
+
+            /* derive picOrderCntCycleCnt and frameNumInPicOrderCntCycle */
+            if (video->absFrameNum > 0)
+            {
+                video->picOrderCntCycleCnt = (video->absFrameNum - 1) / currSPS->num_ref_frames_in_pic_order_cnt_cycle;
+                video->frameNumInPicOrderCntCycle = (video->absFrameNum - 1) % currSPS->num_ref_frames_in_pic_order_cnt_cycle;
+            }
+            /* derive expectedDeltaPerPicOrderCntCycle, this value can be computed up front. */
+            video->expectedDeltaPerPicOrderCntCycle = 0;
+            for (i = 0; i < (int)currSPS->num_ref_frames_in_pic_order_cnt_cycle; i++)
+            {
+                video->expectedDeltaPerPicOrderCntCycle += currSPS->offset_for_ref_frame[i];
+            }
+            /* derive expectedPicOrderCnt */
+            if (video->absFrameNum)
+            {
+                video->expectedPicOrderCnt = video->picOrderCntCycleCnt * video->expectedDeltaPerPicOrderCntCycle;
+                for (i = 0; i <= video->frameNumInPicOrderCntCycle; i++)
+                {
+                    video->expectedPicOrderCnt += currSPS->offset_for_ref_frame[i];
+                }
+            }
+            else
+            {
+                video->expectedPicOrderCnt = 0;
+            }
+
+            if (video->nal_ref_idc == 0)
+            {
+                video->expectedPicOrderCnt += currSPS->offset_for_non_ref_pic;
+            }
+            /* derive TopFieldOrderCnt and BottomFieldOrderCnt */
+            /* encoding part */
+            if (!currSPS->delta_pic_order_always_zero_flag)
+            {
+                sliceHdr->delta_pic_order_cnt[0] = currInput->disp_order - encvid->dispOrdPOCRef - video->expectedPicOrderCnt;
+
+                if (video->currPicParams->pic_order_present_flag && !sliceHdr->field_pic_flag)
+                {
+                    sliceHdr->delta_pic_order_cnt[1] = sliceHdr->delta_pic_order_cnt[0]; /* should be calculated from currInput->bottom_field->disp_order */
+                }
+                else
+                {
+                    sliceHdr->delta_pic_order_cnt[1] = 0;
+                }
+            }
+            else
+            {
+                sliceHdr->delta_pic_order_cnt[0] = sliceHdr->delta_pic_order_cnt[1] = 0;
+            }
+
+            if (sliceHdr->field_pic_flag == 0)
+            {
+                video->TopFieldOrderCnt = video->expectedPicOrderCnt + sliceHdr->delta_pic_order_cnt[0];
+                video->BottomFieldOrderCnt = video->TopFieldOrderCnt + currSPS->offset_for_top_to_bottom_field + sliceHdr->delta_pic_order_cnt[1];
+
+                video->PicOrderCnt = AVC_MIN(video->TopFieldOrderCnt, video->BottomFieldOrderCnt);
+            }
+            else if (sliceHdr->bottom_field_flag == 0)
+            {
+                video->TopFieldOrderCnt = video->expectedPicOrderCnt + sliceHdr->delta_pic_order_cnt[0];
+                video->PicOrderCnt = video->TopFieldOrderCnt;
+            }
+            else
+            {
+                video->BottomFieldOrderCnt = video->expectedPicOrderCnt + currSPS->offset_for_top_to_bottom_field + sliceHdr->delta_pic_order_cnt[0];
+                video->PicOrderCnt = video->BottomFieldOrderCnt;
+            }
+            break;
+
+
+        case 2: /* POC MODE 2, subclause 8.2.1.3 */
+            /* decoding order must be the same as display order */
+            /* we don't check for that. The decoder will just output in decoding order. */
+            /* Check for 2 consecutive non-reference frame */
+            if (video->nal_ref_idc == 0)
+            {
+                if (encvid->dispOrdPOCRef == 1)
+                {
+                    return AVCENC_CONSECUTIVE_NONREF;
+                }
+                encvid->dispOrdPOCRef = 1;  /* act as a flag for non ref */
+            }
+            else
+            {
+                encvid->dispOrdPOCRef = 0;
+            }
+
+
+            if (video->nal_unit_type == AVC_NALTYPE_IDR)
+            {
+                video->FrameNumOffset = 0;
+            }
+            else if (video->prevFrameNum > sliceHdr->frame_num)
+            {
+                video->FrameNumOffset = video->prevFrameNumOffset + video->MaxFrameNum;
+            }
+            else
+            {
+                video->FrameNumOffset = video->prevFrameNumOffset;
+            }
+            /* derive tempPicOrderCnt, we just use PicOrderCnt */
+            if (video->nal_unit_type == AVC_NALTYPE_IDR)
+            {
+                video->PicOrderCnt = 0;
+            }
+            else if (video->nal_ref_idc == 0)
+            {
+                video->PicOrderCnt = 2 * (video->FrameNumOffset + sliceHdr->frame_num) - 1;
+            }
+            else
+            {
+                video->PicOrderCnt = 2 * (video->FrameNumOffset + sliceHdr->frame_num);
+            }
+            /* derive TopFieldOrderCnt and BottomFieldOrderCnt */
+            if (sliceHdr->field_pic_flag == 0)
+            {
+                video->TopFieldOrderCnt = video->BottomFieldOrderCnt = video->PicOrderCnt;
+            }
+            else if (sliceHdr->bottom_field_flag)
+            {
+                video->BottomFieldOrderCnt = video->PicOrderCnt;
+            }
+            else
+            {
+                video->TopFieldOrderCnt = video->PicOrderCnt;
+            }
+            break;
+        default:
+            return AVCENC_POC_FAIL;
+    }
+
+    return AVCENC_SUCCESS;
+}
+
+/** see subclause 8.2.1 */
+AVCEnc_Status PostPOC(AVCCommonObj *video)
+{
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    AVCSeqParamSet *currSPS = video->currSeqParams;
+
+    video->prevFrameNum = sliceHdr->frame_num;
+
+    switch (currSPS->pic_order_cnt_type)
+    {
+        case 0: /* subclause 8.2.1.1 */
+            if (video->mem_mgr_ctrl_eq_5)
+            {
+                video->prevPicOrderCntMsb = 0;
+                video->prevPicOrderCntLsb = video->TopFieldOrderCnt;
+            }
+            else
+            {
+                video->prevPicOrderCntMsb = video->PicOrderCntMsb;
+                video->prevPicOrderCntLsb = sliceHdr->pic_order_cnt_lsb;
+            }
+            break;
+        case 1:  /* subclause 8.2.1.2 and 8.2.1.3 */
+        case 2:
+            if (video->mem_mgr_ctrl_eq_5)
+            {
+                video->prevFrameNumOffset = 0;
+            }
+            else
+            {
+                video->prevFrameNumOffset = video->FrameNumOffset;
+            }
+            break;
+    }
+
+    return AVCENC_SUCCESS;
+}
+
diff --git a/media/libstagefright/codecs/avc/enc/src/init.cpp b/media/libstagefright/codecs/avc/enc/src/init.cpp
new file mode 100644
index 0000000..c258b57
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/init.cpp
@@ -0,0 +1,899 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include "avcenc_api.h"
+
+#define LOG2_MAX_FRAME_NUM_MINUS4   12   /* 12 default */
+#define SLICE_GROUP_CHANGE_CYCLE    1    /* default */
+
+/* initialized variables to be used in SPS*/
+AVCEnc_Status  SetEncodeParam(AVCHandle* avcHandle, AVCEncParams* encParam,
+                              void* extSPS, void* extPPS)
+{
+    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+    AVCCommonObj *video = encvid->common;
+    AVCSeqParamSet *seqParam = video->currSeqParams;
+    AVCPicParamSet *picParam = video->currPicParams;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    AVCEnc_Status status;
+    void *userData = avcHandle->userData;
+    int ii, maxFrameNum;
+
+    AVCSeqParamSet* extS = NULL;
+    AVCPicParamSet* extP = NULL;
+
+    if (extSPS) extS = (AVCSeqParamSet*) extSPS;
+    if (extPPS) extP = (AVCPicParamSet*) extPPS;
+
+    /* This part sets the default values of the encoding options this
+    library supports in seqParam, picParam and sliceHdr structures and
+    also copy the values from the encParam into the above 3 structures.
+
+    Some parameters will be assigned later when we encode SPS or PPS such as
+    the seq_parameter_id or pic_parameter_id. Also some of the slice parameters
+    have to be re-assigned per slice basis such as frame_num, slice_type,
+    first_mb_in_slice, pic_order_cnt_lsb, slice_qp_delta, slice_group_change_cycle */
+
+    /* profile_idc, constrained_setx_flag and level_idc is set by VerifyProfile(),
+    and VerifyLevel() functions later. */
+
+    encvid->fullsearch_enable = encParam->fullsearch;
+
+    encvid->outOfBandParamSet = ((encParam->out_of_band_param_set == AVC_ON) ? TRUE : FALSE);
+
+    /* parameters derived from the the encParam that are used in SPS */
+    if (extS)
+    {
+        video->MaxPicOrderCntLsb =  1 << (extS->log2_max_pic_order_cnt_lsb_minus4 + 4);
+        video->PicWidthInMbs = extS->pic_width_in_mbs_minus1 + 1;
+        video->PicHeightInMapUnits = extS->pic_height_in_map_units_minus1 + 1 ;
+        video->FrameHeightInMbs = (2 - extS->frame_mbs_only_flag) * video->PicHeightInMapUnits ;
+    }
+    else
+    {
+        video->MaxPicOrderCntLsb =  1 << (encParam->log2_max_poc_lsb_minus_4 + 4);
+        video->PicWidthInMbs = (encParam->width + 15) >> 4; /* round it to multiple of 16 */
+        video->FrameHeightInMbs = (encParam->height + 15) >> 4; /* round it to multiple of 16 */
+        video->PicHeightInMapUnits = video->FrameHeightInMbs;
+    }
+
+    video->PicWidthInSamplesL = video->PicWidthInMbs * 16 ;
+    if (video->PicWidthInSamplesL + 32 > 0xFFFF)
+    {
+        return AVCENC_NOT_SUPPORTED; // we use 2-bytes for pitch
+    }
+
+    video->PicWidthInSamplesC = video->PicWidthInMbs * 8 ;
+    video->PicHeightInMbs = video->FrameHeightInMbs;
+    video->PicSizeInMapUnits = video->PicWidthInMbs * video->PicHeightInMapUnits ;
+    video->PicHeightInSamplesL = video->PicHeightInMbs * 16;
+    video->PicHeightInSamplesC = video->PicHeightInMbs * 8;
+    video->PicSizeInMbs = video->PicWidthInMbs * video->PicHeightInMbs;
+
+    if (!extS && !extP)
+    {
+        maxFrameNum = (encParam->idr_period == -1) ? (1 << 16) : encParam->idr_period;
+        ii = 0;
+        while (maxFrameNum > 0)
+        {
+            ii++;
+            maxFrameNum >>= 1;
+        }
+        if (ii < 4) ii = 4;
+        else if (ii > 16) ii = 16;
+
+        seqParam->log2_max_frame_num_minus4 = ii - 4;//LOG2_MAX_FRAME_NUM_MINUS4; /* default */
+
+        video->MaxFrameNum = 1 << ii; //(LOG2_MAX_FRAME_NUM_MINUS4 + 4); /* default */
+        video->MaxPicNum = video->MaxFrameNum;
+
+        /************* set the SPS *******************/
+        seqParam->seq_parameter_set_id = 0; /* start with zero */
+        /* POC */
+        seqParam->pic_order_cnt_type = encParam->poc_type; /* POC type */
+        if (encParam->poc_type == 0)
+        {
+            if (/*encParam->log2_max_poc_lsb_minus_4<0 || (no need, it's unsigned)*/
+                encParam->log2_max_poc_lsb_minus_4 > 12)
+            {
+                return AVCENC_INVALID_POC_LSB;
+            }
+            seqParam->log2_max_pic_order_cnt_lsb_minus4 = encParam->log2_max_poc_lsb_minus_4;
+        }
+        else if (encParam->poc_type == 1)
+        {
+            seqParam->delta_pic_order_always_zero_flag = encParam->delta_poc_zero_flag;
+            seqParam->offset_for_non_ref_pic = encParam->offset_poc_non_ref;
+            seqParam->offset_for_top_to_bottom_field = encParam->offset_top_bottom;
+            seqParam->num_ref_frames_in_pic_order_cnt_cycle = encParam->num_ref_in_cycle;
+            if (encParam->offset_poc_ref == NULL)
+            {
+                return AVCENC_ENCPARAM_MEM_FAIL;
+            }
+            for (ii = 0; ii < encParam->num_ref_frame; ii++)
+            {
+                seqParam->offset_for_ref_frame[ii] = encParam->offset_poc_ref[ii];
+            }
+        }
+        /* number of reference frame */
+        if (encParam->num_ref_frame > 16 || encParam->num_ref_frame < 0)
+        {
+            return AVCENC_INVALID_NUM_REF;
+        }
+        seqParam->num_ref_frames = encParam->num_ref_frame; /* num reference frame range 0...16*/
+        seqParam->gaps_in_frame_num_value_allowed_flag = FALSE;
+        seqParam->pic_width_in_mbs_minus1 = video->PicWidthInMbs - 1;
+        seqParam->pic_height_in_map_units_minus1 = video->PicHeightInMapUnits - 1;
+        seqParam->frame_mbs_only_flag = TRUE;
+        seqParam->mb_adaptive_frame_field_flag = FALSE;
+        seqParam->direct_8x8_inference_flag = FALSE; /* default */
+        seqParam->frame_cropping_flag = FALSE;
+        seqParam->frame_crop_bottom_offset = 0;
+        seqParam->frame_crop_left_offset = 0;
+        seqParam->frame_crop_right_offset = 0;
+        seqParam->frame_crop_top_offset = 0;
+        seqParam->vui_parameters_present_flag = FALSE; /* default */
+    }
+    else if (extS) // use external SPS and PPS
+    {
+        seqParam->seq_parameter_set_id = extS->seq_parameter_set_id;
+        seqParam->log2_max_frame_num_minus4 = extS->log2_max_frame_num_minus4;
+        video->MaxFrameNum = 1 << (extS->log2_max_frame_num_minus4 + 4);
+        video->MaxPicNum = video->MaxFrameNum;
+        if (encParam->idr_period > (int)(video->MaxFrameNum) || (encParam->idr_period == -1))
+        {
+            encParam->idr_period = (int)video->MaxFrameNum;
+        }
+
+        seqParam->pic_order_cnt_type = extS->pic_order_cnt_type;
+        if (seqParam->pic_order_cnt_type == 0)
+        {
+            if (/*extS->log2_max_pic_order_cnt_lsb_minus4<0 || (no need it's unsigned)*/
+                extS->log2_max_pic_order_cnt_lsb_minus4 > 12)
+            {
+                return AVCENC_INVALID_POC_LSB;
+            }
+            seqParam->log2_max_pic_order_cnt_lsb_minus4 = extS->log2_max_pic_order_cnt_lsb_minus4;
+        }
+        else if (seqParam->pic_order_cnt_type == 1)
+        {
+            seqParam->delta_pic_order_always_zero_flag = extS->delta_pic_order_always_zero_flag;
+            seqParam->offset_for_non_ref_pic = extS->offset_for_non_ref_pic;
+            seqParam->offset_for_top_to_bottom_field = extS->offset_for_top_to_bottom_field;
+            seqParam->num_ref_frames_in_pic_order_cnt_cycle = extS->num_ref_frames_in_pic_order_cnt_cycle;
+            if (extS->offset_for_ref_frame == NULL)
+            {
+                return AVCENC_ENCPARAM_MEM_FAIL;
+            }
+            for (ii = 0; ii < (int) extS->num_ref_frames; ii++)
+            {
+                seqParam->offset_for_ref_frame[ii] = extS->offset_for_ref_frame[ii];
+            }
+        }
+        /* number of reference frame */
+        if (extS->num_ref_frames > 16 /*|| extS->num_ref_frames<0 (no need, it's unsigned)*/)
+        {
+            return AVCENC_INVALID_NUM_REF;
+        }
+        seqParam->num_ref_frames = extS->num_ref_frames; /* num reference frame range 0...16*/
+        seqParam->gaps_in_frame_num_value_allowed_flag = extS->gaps_in_frame_num_value_allowed_flag;
+        seqParam->pic_width_in_mbs_minus1 = extS->pic_width_in_mbs_minus1;
+        seqParam->pic_height_in_map_units_minus1 = extS->pic_height_in_map_units_minus1;
+        seqParam->frame_mbs_only_flag = extS->frame_mbs_only_flag;
+        if (extS->frame_mbs_only_flag != TRUE)
+        {
+            return AVCENC_NOT_SUPPORTED;
+        }
+        seqParam->mb_adaptive_frame_field_flag = extS->mb_adaptive_frame_field_flag;
+        if (extS->mb_adaptive_frame_field_flag != FALSE)
+        {
+            return AVCENC_NOT_SUPPORTED;
+        }
+
+        seqParam->direct_8x8_inference_flag = extS->direct_8x8_inference_flag;
+        seqParam->frame_cropping_flag = extS->frame_cropping_flag ;
+        if (extS->frame_cropping_flag != FALSE)
+        {
+            return AVCENC_NOT_SUPPORTED;
+        }
+
+        seqParam->frame_crop_bottom_offset = 0;
+        seqParam->frame_crop_left_offset = 0;
+        seqParam->frame_crop_right_offset = 0;
+        seqParam->frame_crop_top_offset = 0;
+        seqParam->vui_parameters_present_flag = extS->vui_parameters_present_flag;
+        if (extS->vui_parameters_present_flag)
+        {
+            memcpy(&(seqParam->vui_parameters), &(extS->vui_parameters), sizeof(AVCVUIParams));
+        }
+    }
+    else
+    {
+        return AVCENC_NOT_SUPPORTED;
+    }
+
+    /***************** now PPS ******************************/
+    if (!extP && !extS)
+    {
+        picParam->pic_parameter_set_id = (uint)(-1); /* start with zero */
+        picParam->seq_parameter_set_id = (uint)(-1); /* start with zero */
+        picParam->entropy_coding_mode_flag = 0; /* default to CAVLC */
+        picParam->pic_order_present_flag = 0; /* default for now, will need it for B-slice */
+        /* FMO */
+        if (encParam->num_slice_group < 1 || encParam->num_slice_group > MAX_NUM_SLICE_GROUP)
+        {
+            return AVCENC_INVALID_NUM_SLICEGROUP;
+        }
+        picParam->num_slice_groups_minus1 = encParam->num_slice_group - 1;
+
+        if (picParam->num_slice_groups_minus1 > 0)
+        {
+            picParam->slice_group_map_type = encParam->fmo_type;
+            switch (encParam->fmo_type)
+            {
+                case 0:
+                    for (ii = 0; ii <= (int)picParam->num_slice_groups_minus1; ii++)
+                    {
+                        picParam->run_length_minus1[ii] = encParam->run_length_minus1[ii];
+                    }
+                    break;
+                case 2:
+                    for (ii = 0; ii < (int)picParam->num_slice_groups_minus1; ii++)
+                    {
+                        picParam->top_left[ii] = encParam->top_left[ii];
+                        picParam->bottom_right[ii] = encParam->bottom_right[ii];
+                    }
+                    break;
+                case 3:
+                case 4:
+                case 5:
+                    if (encParam->change_dir_flag == AVC_ON)
+                    {
+                        picParam->slice_group_change_direction_flag = TRUE;
+                    }
+                    else
+                    {
+                        picParam->slice_group_change_direction_flag = FALSE;
+                    }
+                    if (/*encParam->change_rate_minus1 < 0 || (no need it's unsigned) */
+                        encParam->change_rate_minus1 > video->PicSizeInMapUnits - 1)
+                    {
+                        return AVCENC_INVALID_CHANGE_RATE;
+                    }
+                    picParam->slice_group_change_rate_minus1 = encParam->change_rate_minus1;
+                    video->SliceGroupChangeRate = picParam->slice_group_change_rate_minus1 + 1;
+                    break;
+                case 6:
+                    picParam->pic_size_in_map_units_minus1 = video->PicSizeInMapUnits - 1;
+
+                    /* allocate picParam->slice_group_id */
+                    picParam->slice_group_id = (uint*)avcHandle->CBAVC_Malloc(userData, sizeof(uint) * video->PicSizeInMapUnits, DEFAULT_ATTR);
+                    if (picParam->slice_group_id == NULL)
+                    {
+                        return AVCENC_MEMORY_FAIL;
+                    }
+
+                    if (encParam->slice_group == NULL)
+                    {
+                        return AVCENC_ENCPARAM_MEM_FAIL;
+                    }
+                    for (ii = 0; ii < (int)video->PicSizeInMapUnits; ii++)
+                    {
+                        picParam->slice_group_id[ii] = encParam->slice_group[ii];
+                    }
+                    break;
+                default:
+                    return AVCENC_INVALID_FMO_TYPE;
+            }
+        }
+        picParam->num_ref_idx_l0_active_minus1 = encParam->num_ref_frame - 1; /* assume frame only */
+        picParam->num_ref_idx_l1_active_minus1 = 0; /* default value */
+        picParam->weighted_pred_flag = 0; /* no weighted prediction supported */
+        picParam->weighted_bipred_idc = 0; /* range 0,1,2 */
+        if (/*picParam->weighted_bipred_idc < 0 || (no need, it's unsigned) */
+            picParam->weighted_bipred_idc > 2)
+        {
+            return AVCENC_WEIGHTED_BIPRED_FAIL;
+        }
+        picParam->pic_init_qp_minus26 = 0; /* default, will be changed at slice level anyway */
+        if (picParam->pic_init_qp_minus26 < -26 || picParam->pic_init_qp_minus26 > 25)
+        {
+            return AVCENC_INIT_QP_FAIL; /* out of range */
+        }
+        picParam->pic_init_qs_minus26 = 0;
+        if (picParam->pic_init_qs_minus26 < -26 || picParam->pic_init_qs_minus26 > 25)
+        {
+            return AVCENC_INIT_QS_FAIL; /* out of range */
+        }
+
+        picParam->chroma_qp_index_offset = 0; /* default to zero for now */
+        if (picParam->chroma_qp_index_offset < -12 || picParam->chroma_qp_index_offset > 12)
+        {
+            return AVCENC_CHROMA_QP_FAIL; /* out of range */
+        }
+        /* deblocking */
+        picParam->deblocking_filter_control_present_flag = (encParam->db_filter == AVC_ON) ? TRUE : FALSE ;
+        /* constrained intra prediction */
+        picParam->constrained_intra_pred_flag = (encParam->constrained_intra_pred == AVC_ON) ? TRUE : FALSE;
+        picParam->redundant_pic_cnt_present_flag = 0; /* default */
+    }
+    else if (extP)// external PPS
+    {
+        picParam->pic_parameter_set_id = extP->pic_parameter_set_id - 1; /* to be increased by one */
+        picParam->seq_parameter_set_id = extP->seq_parameter_set_id;
+        picParam->entropy_coding_mode_flag = extP->entropy_coding_mode_flag;
+        if (extP->entropy_coding_mode_flag != 0) /* default to CAVLC */
+        {
+            return AVCENC_NOT_SUPPORTED;
+        }
+        picParam->pic_order_present_flag = extP->pic_order_present_flag; /* default for now, will need it for B-slice */
+        if (extP->pic_order_present_flag != 0)
+        {
+            return AVCENC_NOT_SUPPORTED;
+        }
+        /* FMO */
+        if (/*(extP->num_slice_groups_minus1<0) || (no need it's unsigned) */
+            (extP->num_slice_groups_minus1 > MAX_NUM_SLICE_GROUP - 1))
+        {
+            return AVCENC_INVALID_NUM_SLICEGROUP;
+        }
+        picParam->num_slice_groups_minus1 = extP->num_slice_groups_minus1;
+
+        if (picParam->num_slice_groups_minus1 > 0)
+        {
+            picParam->slice_group_map_type = extP->slice_group_map_type;
+            switch (extP->slice_group_map_type)
+            {
+                case 0:
+                    for (ii = 0; ii <= (int)extP->num_slice_groups_minus1; ii++)
+                    {
+                        picParam->run_length_minus1[ii] = extP->run_length_minus1[ii];
+                    }
+                    break;
+                case 2:
+                    for (ii = 0; ii < (int)picParam->num_slice_groups_minus1; ii++)
+                    {
+                        picParam->top_left[ii] = extP->top_left[ii];
+                        picParam->bottom_right[ii] = extP->bottom_right[ii];
+                    }
+                    break;
+                case 3:
+                case 4:
+                case 5:
+                    picParam->slice_group_change_direction_flag = extP->slice_group_change_direction_flag;
+                    if (/*extP->slice_group_change_rate_minus1 < 0 || (no need, it's unsigned) */
+                        extP->slice_group_change_rate_minus1 > video->PicSizeInMapUnits - 1)
+                    {
+                        return AVCENC_INVALID_CHANGE_RATE;
+                    }
+                    picParam->slice_group_change_rate_minus1 = extP->slice_group_change_rate_minus1;
+                    video->SliceGroupChangeRate = picParam->slice_group_change_rate_minus1 + 1;
+                    break;
+                case 6:
+                    if (extP->pic_size_in_map_units_minus1 != video->PicSizeInMapUnits - 1)
+                    {
+                        return AVCENC_NOT_SUPPORTED;
+                    }
+
+                    picParam->pic_size_in_map_units_minus1 = extP->pic_size_in_map_units_minus1;
+
+                    /* allocate picParam->slice_group_id */
+                    picParam->slice_group_id = (uint*)avcHandle->CBAVC_Malloc(userData, sizeof(uint) * video->PicSizeInMapUnits, DEFAULT_ATTR);
+                    if (picParam->slice_group_id == NULL)
+                    {
+                        return AVCENC_MEMORY_FAIL;
+                    }
+
+                    if (extP->slice_group_id == NULL)
+                    {
+                        return AVCENC_ENCPARAM_MEM_FAIL;
+                    }
+                    for (ii = 0; ii < (int)video->PicSizeInMapUnits; ii++)
+                    {
+                        picParam->slice_group_id[ii] = extP->slice_group_id[ii];
+                    }
+                    break;
+                default:
+                    return AVCENC_INVALID_FMO_TYPE;
+            }
+        }
+        picParam->num_ref_idx_l0_active_minus1 = extP->num_ref_idx_l0_active_minus1;
+        picParam->num_ref_idx_l1_active_minus1 = extP->num_ref_idx_l1_active_minus1; /* default value */
+        if (picParam->num_ref_idx_l1_active_minus1 != 0)
+        {
+            return AVCENC_NOT_SUPPORTED;
+        }
+
+        if (extP->weighted_pred_flag)
+        {
+            return AVCENC_NOT_SUPPORTED;
+        }
+
+        picParam->weighted_pred_flag = 0; /* no weighted prediction supported */
+        picParam->weighted_bipred_idc = extP->weighted_bipred_idc; /* range 0,1,2 */
+        if (/*picParam->weighted_bipred_idc < 0 || (no need, it's unsigned) */
+            picParam->weighted_bipred_idc > 2)
+        {
+            return AVCENC_WEIGHTED_BIPRED_FAIL;
+        }
+        picParam->pic_init_qp_minus26 = extP->pic_init_qp_minus26; /* default, will be changed at slice level anyway */
+        if (picParam->pic_init_qp_minus26 < -26 || picParam->pic_init_qp_minus26 > 25)
+        {
+            return AVCENC_INIT_QP_FAIL; /* out of range */
+        }
+        picParam->pic_init_qs_minus26 = extP->pic_init_qs_minus26;
+        if (picParam->pic_init_qs_minus26 < -26 || picParam->pic_init_qs_minus26 > 25)
+        {
+            return AVCENC_INIT_QS_FAIL; /* out of range */
+        }
+
+        picParam->chroma_qp_index_offset = extP->chroma_qp_index_offset; /* default to zero for now */
+        if (picParam->chroma_qp_index_offset < -12 || picParam->chroma_qp_index_offset > 12)
+        {
+            return AVCENC_CHROMA_QP_FAIL; /* out of range */
+        }
+        /* deblocking */
+        picParam->deblocking_filter_control_present_flag = extP->deblocking_filter_control_present_flag;
+        /* constrained intra prediction */
+        picParam->constrained_intra_pred_flag = extP->constrained_intra_pred_flag;
+        if (extP->redundant_pic_cnt_present_flag  != 0)
+        {
+            return AVCENC_NOT_SUPPORTED;
+        }
+        picParam->redundant_pic_cnt_present_flag = extP->redundant_pic_cnt_present_flag; /* default */
+    }
+    else
+    {
+        return AVCENC_NOT_SUPPORTED;
+    }
+
+    /****************** now set up some SliceHeader parameters ***********/
+    if (picParam->deblocking_filter_control_present_flag == TRUE)
+    {
+        /* these values only present when db_filter is ON */
+        if (encParam->disable_db_idc > 2)
+        {
+            return AVCENC_INVALID_DEBLOCK_IDC; /* out of range */
+        }
+        sliceHdr->disable_deblocking_filter_idc = encParam->disable_db_idc;
+
+        if (encParam->alpha_offset < -6 || encParam->alpha_offset > 6)
+        {
+            return AVCENC_INVALID_ALPHA_OFFSET;
+        }
+        sliceHdr->slice_alpha_c0_offset_div2 = encParam->alpha_offset;
+
+        if (encParam->beta_offset < -6 || encParam->beta_offset > 6)
+        {
+            return AVCENC_INVALID_BETA_OFFSET;
+        }
+        sliceHdr->slice_beta_offset_div_2 =  encParam->beta_offset;
+    }
+    if (encvid->outOfBandParamSet == TRUE)
+    {
+        sliceHdr->idr_pic_id = 0;
+    }
+    else
+    {
+        sliceHdr->idr_pic_id = (uint)(-1); /* start with zero */
+    }
+    sliceHdr->field_pic_flag = FALSE;
+    sliceHdr->bottom_field_flag = FALSE;  /* won't be used anyway */
+    video->MbaffFrameFlag = (seqParam->mb_adaptive_frame_field_flag && !sliceHdr->field_pic_flag);
+
+    /* the rest will be set in InitSlice() */
+
+    /* now the rate control and performance related parameters */
+    rateCtrl->scdEnable = (encParam->auto_scd == AVC_ON) ? TRUE : FALSE;
+    rateCtrl->idrPeriod = encParam->idr_period + 1;
+    rateCtrl->intraMBRate = encParam->intramb_refresh;
+    rateCtrl->dpEnable = (encParam->data_par == AVC_ON) ? TRUE : FALSE;
+
+    rateCtrl->subPelEnable = (encParam->sub_pel == AVC_ON) ? TRUE : FALSE;
+    rateCtrl->mvRange = encParam->search_range;
+
+    rateCtrl->subMBEnable = (encParam->submb_pred == AVC_ON) ? TRUE : FALSE;
+    rateCtrl->rdOptEnable = (encParam->rdopt_mode == AVC_ON) ? TRUE : FALSE;
+    rateCtrl->bidirPred = (encParam->bidir_pred == AVC_ON) ? TRUE : FALSE;
+
+    rateCtrl->rcEnable = (encParam->rate_control == AVC_ON) ? TRUE : FALSE;
+    rateCtrl->initQP = encParam->initQP;
+    rateCtrl->initQP = AVC_CLIP3(0, 51, rateCtrl->initQP);
+
+    rateCtrl->bitRate = encParam->bitrate;
+    rateCtrl->cpbSize = encParam->CPB_size;
+    rateCtrl->initDelayOffset = (rateCtrl->bitRate * encParam->init_CBP_removal_delay / 1000);
+
+    if (encParam->frame_rate == 0)
+    {
+        return AVCENC_INVALID_FRAMERATE;
+    }
+
+    rateCtrl->frame_rate = (OsclFloat)(encParam->frame_rate * 1.0 / 1000);
+//  rateCtrl->srcInterval = encParam->src_interval;
+    rateCtrl->first_frame = 1; /* set this flag for the first time */
+
+    /* contrained_setx_flag will be set inside the VerifyProfile called below.*/
+    if (!extS && !extP)
+    {
+        seqParam->profile_idc = encParam->profile;
+        seqParam->constrained_set0_flag = FALSE;
+        seqParam->constrained_set1_flag = FALSE;
+        seqParam->constrained_set2_flag = FALSE;
+        seqParam->constrained_set3_flag = FALSE;
+        seqParam->level_idc = encParam->level;
+    }
+    else
+    {
+        seqParam->profile_idc = extS->profile_idc;
+        seqParam->constrained_set0_flag = extS->constrained_set0_flag;
+        seqParam->constrained_set1_flag = extS->constrained_set1_flag;
+        seqParam->constrained_set2_flag = extS->constrained_set2_flag;
+        seqParam->constrained_set3_flag = extS->constrained_set3_flag;
+        seqParam->level_idc = extS->level_idc;
+    }
+
+
+    status = VerifyProfile(encvid, seqParam, picParam);
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    status = VerifyLevel(encvid, seqParam, picParam);
+    if (status != AVCENC_SUCCESS)
+    {
+        return status;
+    }
+
+    return AVCENC_SUCCESS;
+}
+
+/* verify the profile setting */
+AVCEnc_Status VerifyProfile(AVCEncObject *encvid, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam)
+{
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    AVCEnc_Status status = AVCENC_SUCCESS;
+
+    if (seqParam->profile_idc == 0) /* find profile for this setting */
+    {
+        /* find the right profile for it */
+        if (seqParam->direct_8x8_inference_flag == TRUE &&
+                picParam->entropy_coding_mode_flag == FALSE &&
+                picParam->num_slice_groups_minus1 <= 7 /*&&
+            picParam->num_slice_groups_minus1>=0 (no need, it's unsigned) */)
+        {
+            seqParam->profile_idc = AVC_EXTENDED;
+            seqParam->constrained_set2_flag = TRUE;
+        }
+
+        if (rateCtrl->dpEnable == FALSE &&
+                picParam->num_slice_groups_minus1 == 0 &&
+                picParam->redundant_pic_cnt_present_flag == FALSE)
+        {
+            seqParam->profile_idc = AVC_MAIN;
+            seqParam->constrained_set1_flag = TRUE;
+        }
+
+        if (rateCtrl->bidirPred == FALSE &&
+                rateCtrl->dpEnable == FALSE &&
+                seqParam->frame_mbs_only_flag == TRUE &&
+                picParam->weighted_pred_flag == FALSE &&
+                picParam->weighted_bipred_idc == 0 &&
+                picParam->entropy_coding_mode_flag == FALSE &&
+                picParam->num_slice_groups_minus1 <= 7 /*&&
+            picParam->num_slice_groups_minus1>=0 (no need, it's unsigned)*/)
+        {
+            seqParam->profile_idc = AVC_BASELINE;
+            seqParam->constrained_set0_flag = TRUE;
+        }
+
+        if (seqParam->profile_idc == 0) /* still zero */
+        {
+            return AVCENC_PROFILE_NOT_SUPPORTED;
+        }
+    }
+
+    /* check the list of supported profile by this library */
+    switch (seqParam->profile_idc)
+    {
+        case AVC_BASELINE:
+            if (rateCtrl->bidirPred == TRUE ||
+                    rateCtrl->dpEnable == TRUE ||
+                    seqParam->frame_mbs_only_flag != TRUE ||
+                    picParam->weighted_pred_flag == TRUE ||
+                    picParam->weighted_bipred_idc != 0 ||
+                    picParam->entropy_coding_mode_flag == TRUE ||
+                    picParam->num_slice_groups_minus1 > 7 /*||
+            picParam->num_slice_groups_minus1<0 (no need, it's unsigned) */)
+            {
+                status = AVCENC_TOOLS_NOT_SUPPORTED;
+            }
+            break;
+
+        case AVC_MAIN:
+        case AVC_EXTENDED:
+            status = AVCENC_PROFILE_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+/* verify the level setting */
+AVCEnc_Status VerifyLevel(AVCEncObject *encvid, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam)
+{
+    (void)(picParam);
+
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    AVCCommonObj *video = encvid->common;
+    int mb_per_sec, ii;
+    int lev_idx;
+    int dpb_size;
+
+    mb_per_sec = (int)(video->PicSizeInMbs * rateCtrl->frame_rate + 0.5);
+    dpb_size = (seqParam->num_ref_frames * video->PicSizeInMbs * 3) >> 6;
+
+    if (seqParam->level_idc == 0) /* find level for this setting */
+    {
+        for (ii = 0; ii < MAX_LEVEL_IDX; ii++)
+        {
+            if (mb_per_sec <= MaxMBPS[ii] &&
+                    video->PicSizeInMbs <= (uint)MaxFS[ii] &&
+                    rateCtrl->bitRate <= (int32)MaxBR[ii]*1000 &&
+                    rateCtrl->cpbSize <= (int32)MaxCPB[ii]*1000 &&
+                    rateCtrl->mvRange <= MaxVmvR[ii] &&
+                    dpb_size <= MaxDPBX2[ii]*512)
+            {
+                seqParam->level_idc = mapIdx2Lev[ii];
+                break;
+            }
+        }
+        if (seqParam->level_idc == 0)
+        {
+            return AVCENC_LEVEL_NOT_SUPPORTED;
+        }
+    }
+
+    /* check if this level is supported by this library */
+    lev_idx = mapLev2Idx[seqParam->level_idc];
+    if (seqParam->level_idc == AVC_LEVEL1_B)
+    {
+        seqParam->constrained_set3_flag = 1;
+    }
+
+
+    if (lev_idx == 255) /* not defined */
+    {
+        return AVCENC_LEVEL_NOT_SUPPORTED;
+    }
+
+    /* check if the encoding setting complies with the level */
+    if (mb_per_sec > MaxMBPS[lev_idx] ||
+            video->PicSizeInMbs > (uint)MaxFS[lev_idx] ||
+            rateCtrl->bitRate > (int32)MaxBR[lev_idx]*1000 ||
+            rateCtrl->cpbSize > (int32)MaxCPB[lev_idx]*1000 ||
+            rateCtrl->mvRange > MaxVmvR[lev_idx])
+    {
+        return AVCENC_LEVEL_FAIL;
+    }
+
+    return AVCENC_SUCCESS;
+}
+
+/* initialize variables at the beginning of each frame */
+/* determine the picture type */
+/* encode POC */
+/* maybe we should do more stuff here. MotionEstimation+SCD and generate a new SPS and PPS */
+AVCEnc_Status InitFrame(AVCEncObject *encvid)
+{
+    AVCStatus ret;
+    AVCEnc_Status status;
+    AVCCommonObj *video = encvid->common;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+
+    /* look for the next frame in coding_order and look for available picture
+       in the DPB. Note, video->currFS->PicOrderCnt, currFS->FrameNum and currPic->PicNum
+       are set to wrong number in this function (right for decoder). */
+    if (video->nal_unit_type == AVC_NALTYPE_IDR)
+    {
+        // call init DPB in here.
+        ret = AVCConfigureSequence(encvid->avcHandle, video, TRUE);
+        if (ret != AVC_SUCCESS)
+        {
+            return AVCENC_FAIL;
+        }
+    }
+
+    /* flexible macroblock ordering (every frame)*/
+    /* populate video->mapUnitToSliceGroupMap and video->MbToSliceGroupMap */
+    /* It changes once per each PPS. */
+    FMOInit(video);
+
+    ret = DPBInitBuffer(encvid->avcHandle, video); // get new buffer
+
+    if (ret != AVC_SUCCESS)
+    {
+        return (AVCEnc_Status)ret; // AVCENC_PICTURE_READY, FAIL
+    }
+
+    DPBInitPic(video, 0); /* 0 is dummy */
+
+    /************* determine picture type IDR or non-IDR ***********/
+    video->currPicType = AVC_FRAME;
+    video->slice_data_partitioning = FALSE;
+    encvid->currInput->is_reference = 1; /* default to all frames */
+    video->nal_ref_idc = 1;  /* need to set this for InitPOC */
+    video->currPic->isReference = TRUE;
+
+    /************* set frame_num ********************/
+    if (video->nal_unit_type == AVC_NALTYPE_IDR)
+    {
+        video->prevFrameNum = video->MaxFrameNum;
+        video->PrevRefFrameNum = 0;
+        sliceHdr->frame_num = 0;
+    }
+    /* otherwise, it's set to previous reference frame access unit's frame_num in decoding order,
+       see the end of PVAVCDecodeSlice()*/
+    /* There's also restriction on the frame_num, see page 59 of JVT-I1010.doc. */
+    /* Basically, frame_num can't be repeated unless it's opposite fields or non reference fields */
+    else
+    {
+        sliceHdr->frame_num = (video->PrevRefFrameNum + 1) % video->MaxFrameNum;
+    }
+    video->CurrPicNum = sliceHdr->frame_num;  /* for field_pic_flag = 0 */
+    //video->CurrPicNum = 2*sliceHdr->frame_num + 1; /* for field_pic_flag = 1 */
+
+    /* assign pic_order_cnt, video->PicOrderCnt */
+    status = InitPOC(encvid);
+    if (status != AVCENC_SUCCESS)  /* incorrigable fail */
+    {
+        return status;
+    }
+
+    /* Initialize refListIdx for this picture */
+    RefListInit(video);
+
+    /************* motion estimation and scene analysis ************/
+    // , to move this to MB-based MV search for comparison
+    // use sub-optimal QP for mv search
+    AVCMotionEstimation(encvid);  /* AVCENC_SUCCESS or AVCENC_NEW_IDR */
+
+    /* after this point, the picture type will be fixed to either IDR or non-IDR */
+    video->currFS->PicOrderCnt = video->PicOrderCnt;
+    video->currFS->FrameNum = video->sliceHdr->frame_num;
+    video->currPic->PicNum = video->CurrPicNum;
+    video->mbNum = 0; /* start from zero MB */
+    encvid->currSliceGroup = 0; /* start from slice group #0 */
+    encvid->numIntraMB = 0; /* reset this counter */
+
+    if (video->nal_unit_type == AVC_NALTYPE_IDR)
+    {
+        RCInitGOP(encvid);
+
+        /* calculate picture QP */
+        RCInitFrameQP(encvid);
+
+        return AVCENC_NEW_IDR;
+    }
+
+    /* calculate picture QP */
+    RCInitFrameQP(encvid); /* get QP after MV search */
+
+    return AVCENC_SUCCESS;
+}
+
+/* initialize variables for this slice */
+AVCEnc_Status InitSlice(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    AVCPicParamSet *currPPS = video->currPicParams;
+    AVCSeqParamSet *currSPS = video->currSeqParams;
+    int slice_type = video->slice_type;
+
+    sliceHdr->first_mb_in_slice = video->mbNum;
+    if (video->mbNum) // not first slice of a frame
+    {
+        video->sliceHdr->slice_type = (AVCSliceType)slice_type;
+    }
+
+    /* sliceHdr->slice_type already set in InitFrame */
+
+    sliceHdr->pic_parameter_set_id = video->currPicParams->pic_parameter_set_id;
+
+    /* sliceHdr->frame_num already set in InitFrame */
+
+    if (!currSPS->frame_mbs_only_flag)  /* we shouldn't need this check */
+    {
+        sliceHdr->field_pic_flag = sliceHdr->bottom_field_flag = FALSE;
+        return AVCENC_TOOLS_NOT_SUPPORTED;
+    }
+
+    /* sliceHdr->idr_pic_id already set in PVAVCEncodeNAL
+
+     sliceHdr->pic_order_cnt_lsb already set in InitFrame..InitPOC
+     sliceHdr->delta_pic_order_cnt_bottom  already set in InitPOC
+
+    sliceHdr->delta_pic_order_cnt[0] already set in InitPOC
+    sliceHdr->delta_pic_order_cnt[1] already set in InitPOC
+    */
+
+    sliceHdr->redundant_pic_cnt = 0; /* default if(currPPS->redundant_pic_cnt_present_flag), range 0..127 */
+    sliceHdr->direct_spatial_mv_pred_flag = 0; // default if(slice_type == AVC_B_SLICE)
+
+    sliceHdr->num_ref_idx_active_override_flag = FALSE; /* default, if(slice_type== P,SP or B)*/
+    sliceHdr->num_ref_idx_l0_active_minus1 = 0; /* default, if (num_ref_idx_active_override_flag) */
+    sliceHdr->num_ref_idx_l1_active_minus1 = 0; /* default, if above and B_slice */
+    /* the above 2 values range from 0..15 for frame picture and 0..31 for field picture */
+
+    /* ref_pic_list_reordering(), currently we don't do anything */
+    sliceHdr->ref_pic_list_reordering_flag_l0 = FALSE; /* default */
+    sliceHdr->ref_pic_list_reordering_flag_l1 = FALSE; /* default */
+    /* if the above are TRUE, some other params must be set */
+
+    if ((currPPS->weighted_pred_flag && (slice_type == AVC_P_SLICE || slice_type == AVC_SP_SLICE)) ||
+            (currPPS->weighted_bipred_idc == 1 && slice_type == AVC_B_SLICE))
+    {
+        //      pred_weight_table(); // not supported !!
+        return AVCENC_TOOLS_NOT_SUPPORTED;
+    }
+
+    /* dec_ref_pic_marking(), this will be done later*/
+    sliceHdr->no_output_of_prior_pics_flag = FALSE; /* default */
+    sliceHdr->long_term_reference_flag = FALSE; /* for IDR frame, do not make it long term */
+    sliceHdr->adaptive_ref_pic_marking_mode_flag = FALSE; /* default */
+    /* other params are not set here because they are not used */
+
+    sliceHdr->cabac_init_idc = 0; /* default, if entropy_coding_mode_flag && slice_type==I or SI, range 0..2  */
+    sliceHdr->slice_qp_delta = 0; /* default for now */
+    sliceHdr->sp_for_switch_flag = FALSE; /* default, if slice_type == SP */
+    sliceHdr->slice_qs_delta = 0; /* default, if slice_type == SP or SI */
+
+    /* derived variables from encParam */
+    /* deblocking filter */
+    video->FilterOffsetA = video->FilterOffsetB = 0;
+    if (currPPS->deblocking_filter_control_present_flag == TRUE)
+    {
+        video->FilterOffsetA = sliceHdr->slice_alpha_c0_offset_div2 << 1;
+        video->FilterOffsetB = sliceHdr->slice_beta_offset_div_2 << 1;
+    }
+
+    /* flexible macroblock ordering */
+    /* populate video->mapUnitToSliceGroupMap and video->MbToSliceGroupMap */
+    /* We already call it at the end of PVAVCEncInitialize(). It changes once per each PPS. */
+    if (video->currPicParams->num_slice_groups_minus1 > 0 && video->currPicParams->slice_group_map_type >= 3
+            && video->currPicParams->slice_group_map_type <= 5)
+    {
+        sliceHdr->slice_group_change_cycle = SLICE_GROUP_CHANGE_CYCLE;  /* default, don't understand how to set it!!!*/
+
+        video->MapUnitsInSliceGroup0 =
+            AVC_MIN(sliceHdr->slice_group_change_cycle * video->SliceGroupChangeRate, video->PicSizeInMapUnits);
+
+        FMOInit(video);
+    }
+
+    /* calculate SliceQPy first  */
+    /* calculate QSy first */
+
+    sliceHdr->slice_qp_delta = video->QPy - 26 - currPPS->pic_init_qp_minus26;
+    //sliceHdr->slice_qs_delta = video->QSy - 26 - currPPS->pic_init_qs_minus26;
+
+    return AVCENC_SUCCESS;
+}
+
diff --git a/media/libstagefright/codecs/avc/enc/src/intra_est.cpp b/media/libstagefright/codecs/avc/enc/src/intra_est.cpp
new file mode 100644
index 0000000..17e5985
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/intra_est.cpp
@@ -0,0 +1,2199 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+#define TH_I4  0  /* threshold biasing toward I16 mode instead of I4 mode */
+#define TH_Intra  0 /* threshold biasing toward INTER mode instead of intra mode */
+
+#define FIXED_INTRAPRED_MODE  AVC_I16
+#define FIXED_I16_MODE  AVC_I16_DC
+#define FIXED_I4_MODE   AVC_I4_Diagonal_Down_Left
+#define FIXED_INTRA_CHROMA_MODE AVC_IC_DC
+
+#define CLIP_RESULT(x)      if((uint)x > 0xFF){ \
+                 x = 0xFF & (~(x>>31));}
+
+
+bool IntraDecisionABE(AVCEncObject *encvid, int min_cost, uint8 *curL, int picPitch)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCFrameIO *currInput = encvid->currInput;
+    int orgPitch = currInput->pitch;
+    int x_pos = (video->mb_x) << 4;
+    int y_pos = (video->mb_y) << 4;
+    uint8 *orgY = currInput->YCbCr[0] + y_pos * orgPitch + x_pos;
+    int j;
+    uint8 *topL, *leftL, *orgY_2, *orgY_3;
+    int temp, SBE, offset;
+    OsclFloat ABE;
+    bool intra = true;
+
+    if (((x_pos >> 4) != (int)video->PicWidthInMbs - 1) &&
+            ((y_pos >> 4) != (int)video->PicHeightInMbs - 1) &&
+            video->intraAvailA &&
+            video->intraAvailB)
+    {
+        SBE = 0;
+        /* top neighbor */
+        topL = curL - picPitch;
+        /* left neighbor */
+        leftL = curL - 1;
+        orgY_2 = orgY - orgPitch;
+
+        for (j = 0; j < 16; j++)
+        {
+            temp = *topL++ - orgY[j];
+            SBE += ((temp >= 0) ? temp : -temp);
+            temp = *(leftL += picPitch) - *(orgY_2 += orgPitch);
+            SBE += ((temp >= 0) ? temp : -temp);
+        }
+
+        /* calculate chroma */
+        offset = (y_pos >> 2) * picPitch + (x_pos >> 1);
+        topL = video->currPic->Scb + offset;
+        orgY_2 = currInput->YCbCr[1] + offset + (y_pos >> 2) * (orgPitch - picPitch);
+
+        leftL = topL - 1;
+        topL -= (picPitch >> 1);
+        orgY_3 = orgY_2 - (orgPitch >> 1);
+        for (j = 0; j < 8; j++)
+        {
+            temp = *topL++ - orgY_2[j];
+            SBE += ((temp >= 0) ? temp : -temp);
+            temp = *(leftL += (picPitch >> 1)) - *(orgY_3 += (orgPitch >> 1));
+            SBE += ((temp >= 0) ? temp : -temp);
+        }
+
+        topL = video->currPic->Scr + offset;
+        orgY_2 = currInput->YCbCr[2] + offset + (y_pos >> 2) * (orgPitch - picPitch);
+
+        leftL = topL - 1;
+        topL -= (picPitch >> 1);
+        orgY_3 = orgY_2 - (orgPitch >> 1);
+        for (j = 0; j < 8; j++)
+        {
+            temp = *topL++ - orgY_2[j];
+            SBE += ((temp >= 0) ? temp : -temp);
+            temp = *(leftL += (picPitch >> 1)) - *(orgY_3 += (orgPitch >> 1));
+            SBE += ((temp >= 0) ? temp : -temp);
+        }
+
+        /* compare mincost/384 and SBE/64 */
+        ABE = SBE / 64.0;
+        if (ABE*0.8 >= min_cost / 384.0)
+        {
+            intra = false;
+        }
+    }
+
+    return intra;
+}
+
+/* perform searching for MB mode */
+/* assuming that this is done inside the encoding loop,
+no need to call InitNeighborAvailability */
+
+void MBIntraSearch(AVCEncObject *encvid, int mbnum, uint8 *curL, int picPitch)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCFrameIO *currInput = encvid->currInput;
+    AVCMacroblock *currMB = video->currMB;
+    int min_cost;
+    uint8 *orgY;
+    int x_pos = (video->mb_x) << 4;
+    int y_pos = (video->mb_y) << 4;
+    uint32 *saved_inter;
+    int j;
+    int orgPitch = currInput->pitch;
+    bool intra = true;
+
+    currMB->CBP = 0;
+
+    /* first do motion vector and variable block size search */
+    min_cost = encvid->min_cost[mbnum];
+
+    /* now perform intra prediction search */
+    /* need to add the check for encvid->intraSearch[video->mbNum] to skip intra
+       if it's not worth checking. */
+    if (video->slice_type == AVC_P_SLICE)
+    {
+        /* Decide whether intra search is necessary or not */
+        /* This one, we do it in the encoding loop so the neighboring pixel are the
+        actual reconstructed pixels. */
+        intra = IntraDecisionABE(encvid, min_cost, curL, picPitch);
+    }
+
+    if (intra == true || video->slice_type == AVC_I_SLICE)
+    {
+        orgY = currInput->YCbCr[0] + y_pos * orgPitch + x_pos;
+
+        /* i16 mode search */
+        /* generate all the predictions */
+        intrapred_luma_16x16(encvid);
+
+        /* evaluate them one by one */
+        find_cost_16x16(encvid, orgY, &min_cost);
+
+        if (video->slice_type == AVC_P_SLICE)
+        {
+            /* save current inter prediction */
+            saved_inter = encvid->subpel_pred; /* reuse existing buffer */
+            j = 16;
+            curL -= 4;
+            picPitch -= 16;
+            while (j--)
+            {
+                *saved_inter++ = *((uint32*)(curL += 4));
+                *saved_inter++ = *((uint32*)(curL += 4));
+                *saved_inter++ = *((uint32*)(curL += 4));
+                *saved_inter++ = *((uint32*)(curL += 4));
+                curL += picPitch;
+            }
+
+        }
+
+        /* i4 mode search */
+        mb_intra4x4_search(encvid, &min_cost);
+
+        encvid->min_cost[mbnum] = min_cost; /* update min_cost */
+    }
+
+
+    if (currMB->mb_intra)
+    {
+        chroma_intra_search(encvid);
+
+        /* need to set this in order for the MBInterPrediction to work!! */
+        memset(currMB->mvL0, 0, sizeof(int32)*16);
+        currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] =
+                                    currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = -1;
+    }
+    else if (video->slice_type == AVC_P_SLICE && intra == true)
+    {
+        /* restore current inter prediction */
+        saved_inter = encvid->subpel_pred; /* reuse existing buffer */
+        j = 16;
+        curL -= ((picPitch + 16) << 4);
+        while (j--)
+        {
+            *((uint32*)(curL += 4)) = *saved_inter++;
+            *((uint32*)(curL += 4)) = *saved_inter++;
+            *((uint32*)(curL += 4)) = *saved_inter++;
+            *((uint32*)(curL += 4)) = *saved_inter++;
+            curL += picPitch;
+        }
+    }
+
+    return ;
+}
+
+/* generate all the prediction values */
+void intrapred_luma_16x16(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCPictureData *currPic = video->currPic;
+
+    int x_pos = (video->mb_x) << 4;
+    int y_pos = (video->mb_y) << 4;
+    int pitch = currPic->pitch;
+
+    int offset = y_pos * pitch + x_pos;
+
+    uint8 *pred, *top, *left;
+    uint8 *curL = currPic->Sl + offset; /* point to reconstructed frame */
+    uint32 word1, word2, word3, word4;
+    uint32 sum = 0;
+
+    int a_16, b, c, factor_c;
+    uint8 *comp_ref_x0, *comp_ref_x1, *comp_ref_y0, *comp_ref_y1;
+    int H = 0, V = 0, tmp, value;
+    int i;
+
+    if (video->intraAvailB)
+    {
+        //get vertical prediction mode
+        top = curL - pitch;
+
+        pred = encvid->pred_i16[AVC_I16_Vertical] - 16;
+
+        word1 = *((uint32*)(top));  /* read 4 bytes from top */
+        word2 = *((uint32*)(top + 4)); /* read 4 bytes from top */
+        word3 = *((uint32*)(top + 8)); /* read 4 bytes from top */
+        word4 = *((uint32*)(top + 12)); /* read 4 bytes from top */
+
+        for (i = 0; i < 16; i++)
+        {
+            *((uint32*)(pred += 16)) = word1;
+            *((uint32*)(pred + 4)) = word2;
+            *((uint32*)(pred + 8)) = word3;
+            *((uint32*)(pred + 12)) = word4;
+
+        }
+
+        sum = word1 & 0xFF00FF;
+        word1 = (word1 >> 8) & 0xFF00FF;
+        sum += word1;
+        word1 = (word2 & 0xFF00FF);
+        sum += word1;
+        word2 = (word2 >> 8) & 0xFF00FF;
+        sum += word2;
+        word1 = (word3 & 0xFF00FF);
+        sum += word1;
+        word3 = (word3 >> 8) & 0xFF00FF;
+        sum += word3;
+        word1 = (word4 & 0xFF00FF);
+        sum += word1;
+        word4 = (word4 >> 8) & 0xFF00FF;
+        sum += word4;
+
+        sum += (sum >> 16);
+        sum &= 0xFFFF;
+
+        if (!video->intraAvailA)
+        {
+            sum = (sum + 8) >> 4;
+        }
+    }
+
+    if (video->intraAvailA)
+    {
+        // get horizontal mode
+        left = curL - 1 - pitch;
+
+        pred = encvid->pred_i16[AVC_I16_Horizontal] - 16;
+
+        for (i = 0; i < 16; i++)
+        {
+            word1 = *(left += pitch);
+            sum += word1;
+
+            word1 = (word1 << 8) | word1;
+            word1 = (word1 << 16) | word1; /* make it 4 */
+
+            *(uint32*)(pred += 16) = word1;
+            *(uint32*)(pred + 4) = word1;
+            *(uint32*)(pred + 8) = word1;
+            *(uint32*)(pred + 12) = word1;
+        }
+
+        if (!video->intraAvailB)
+        {
+            sum = (sum + 8) >> 4;
+        }
+        else
+        {
+            sum = (sum + 16) >> 5;
+        }
+    }
+
+    // get DC mode
+    if (!video->intraAvailA && !video->intraAvailB)
+    {
+        sum = 0x80808080;
+    }
+    else
+    {
+        sum = (sum << 8) | sum;
+        sum = (sum << 16) | sum;
+    }
+
+    pred = encvid->pred_i16[AVC_I16_DC] - 16;
+    for (i = 0; i < 16; i++)
+    {
+        *((uint32*)(pred += 16)) = sum;
+        *((uint32*)(pred + 4)) = sum;
+        *((uint32*)(pred + 8)) = sum;
+        *((uint32*)(pred + 12)) = sum;
+    }
+
+    // get plane mode
+    if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+    {
+        pred = encvid->pred_i16[AVC_I16_Plane] - 16;
+
+        comp_ref_x0 = curL - pitch + 8;
+        comp_ref_x1 = curL - pitch + 6;
+        comp_ref_y0 = curL - 1 + (pitch << 3);
+        comp_ref_y1 = curL - 1 + 6 * pitch;
+
+        for (i = 1; i < 8; i++)
+        {
+            H += i * (*comp_ref_x0++ - *comp_ref_x1--);
+            V += i * (*comp_ref_y0 - *comp_ref_y1);
+            comp_ref_y0 += pitch;
+            comp_ref_y1 -= pitch;
+        }
+
+        H += i * (*comp_ref_x0++ - curL[-pitch-1]);
+        V += i * (*comp_ref_y0 - *comp_ref_y1);
+
+
+        a_16 = ((*(curL - pitch + 15) + *(curL - 1 + 15 * pitch)) << 4) + 16;;
+        b = (5 * H + 32) >> 6;
+        c = (5 * V + 32) >> 6;
+
+        tmp = 0;
+        for (i = 0; i < 16; i++)
+        {
+            factor_c = a_16 + c * (tmp++ - 7);
+            factor_c -= 7 * b;
+
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = value;
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 8);
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 16);
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 24);
+            *((uint32*)(pred += 16)) = word1;
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = value;
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 8);
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 16);
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 24);
+            *((uint32*)(pred + 4)) = word1;
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = value;
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 8);
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 16);
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 24);
+            *((uint32*)(pred + 8)) = word1;
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = value;
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 8);
+            value = factor_c >> 5;
+            factor_c += b;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 16);
+            value = factor_c >> 5;
+            CLIP_RESULT(value)
+            word1 = (word1) | (value << 24);
+            *((uint32*)(pred + 12)) = word1;
+        }
+    }
+
+    return ;
+}
+
+
+/* evaluate each prediction mode of I16 */
+void find_cost_16x16(AVCEncObject *encvid, uint8 *orgY, int *min_cost)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCMacroblock *currMB = video->currMB;
+    int cost;
+    int org_pitch = encvid->currInput->pitch;
+
+    /* evaluate vertical mode */
+    if (video->intraAvailB)
+    {
+        cost = cost_i16(orgY, org_pitch, encvid->pred_i16[AVC_I16_Vertical], *min_cost);
+        if (cost < *min_cost)
+        {
+            *min_cost = cost;
+            currMB->mbMode = AVC_I16;
+            currMB->mb_intra = 1;
+            currMB->i16Mode = AVC_I16_Vertical;
+        }
+    }
+
+
+    /* evaluate horizontal mode */
+    if (video->intraAvailA)
+    {
+        cost = cost_i16(orgY, org_pitch, encvid->pred_i16[AVC_I16_Horizontal], *min_cost);
+        if (cost < *min_cost)
+        {
+            *min_cost = cost;
+            currMB->mbMode = AVC_I16;
+            currMB->mb_intra = 1;
+            currMB->i16Mode = AVC_I16_Horizontal;
+        }
+    }
+
+    /* evaluate DC mode */
+    cost = cost_i16(orgY, org_pitch, encvid->pred_i16[AVC_I16_DC], *min_cost);
+    if (cost < *min_cost)
+    {
+        *min_cost = cost;
+        currMB->mbMode = AVC_I16;
+        currMB->mb_intra = 1;
+        currMB->i16Mode = AVC_I16_DC;
+    }
+
+    /* evaluate plane mode */
+    if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+    {
+        cost = cost_i16(orgY, org_pitch, encvid->pred_i16[AVC_I16_Plane], *min_cost);
+        if (cost < *min_cost)
+        {
+            *min_cost = cost;
+            currMB->mbMode = AVC_I16;
+            currMB->mb_intra = 1;
+            currMB->i16Mode = AVC_I16_Plane;
+        }
+    }
+
+    return ;
+}
+
+
+int cost_i16(uint8 *org, int org_pitch, uint8 *pred, int min_cost)
+{
+
+    int cost;
+    int j, k;
+    int16 res[256], *pres; // residue
+    int m0, m1, m2, m3;
+
+    // calculate SATD
+    org_pitch -= 16;
+    pres = res;
+    // horizontal transform
+    for (j = 0; j < 16; j++)
+    {
+        k = 4;
+        while (k > 0)
+        {
+            m0 = org[0] - pred[0];
+            m3 = org[3] - pred[3];
+            m0 += m3;
+            m3 = m0 - (m3 << 1);
+            m1 = org[1] - pred[1];
+            m2 = org[2] - pred[2];
+            m1 += m2;
+            m2 = m1 - (m2 << 1);
+            pres[0] = m0 + m1;
+            pres[2] = m0 - m1;
+            pres[1] = m2 + m3;
+            pres[3] = m3 - m2;
+
+            org += 4;
+            pres += 4;
+            pred += 4;
+            k--;
+        }
+        org += org_pitch;
+    }
+    /* vertical transform */
+    cost = 0;
+    for (j = 0; j < 4; j++)
+    {
+        pres = res + (j << 6);
+        k = 16;
+        while (k > 0)
+        {
+            m0 = pres[0];
+            m3 = pres[3<<4];
+            m0 += m3;
+            m3 = m0 - (m3 << 1);
+            m1 = pres[1<<4];
+            m2 = pres[2<<4];
+            m1 += m2;
+            m2 = m1 - (m2 << 1);
+            pres[0] = m0 = m0 + m1;
+
+            if (k&0x3)  // only sum up non DC values.
+            {
+                cost += ((m0 > 0) ? m0 : -m0);
+            }
+
+            m1 = m0 - (m1 << 1);
+            cost += ((m1 > 0) ? m1 : -m1);
+            m3 = m2 + m3;
+            cost += ((m3 > 0) ? m3 : -m3);
+            m2 = m3 - (m2 << 1);
+            cost += ((m2 > 0) ? m2 : -m2);
+
+            pres++;
+            k--;
+        }
+        if ((cost >> 1) > min_cost) /* early drop out */
+        {
+            return (cost >> 1);
+        }
+    }
+
+    /* Hadamard of the DC coefficient */
+    pres = res;
+    k = 4;
+    while (k > 0)
+    {
+        m0 = pres[0];
+        m3 = pres[3<<2];
+        m0 >>= 2;
+        m0 += (m3 >> 2);
+        m3 = m0 - (m3 >> 1);
+        m1 = pres[1<<2];
+        m2 = pres[2<<2];
+        m1 >>= 2;
+        m1 += (m2 >> 2);
+        m2 = m1 - (m2 >> 1);
+        pres[0] = (m0 + m1);
+        pres[2<<2] = (m0 - m1);
+        pres[1<<2] = (m2 + m3);
+        pres[3<<2] = (m3 - m2);
+        pres += (4 << 4);
+        k--;
+    }
+
+    pres = res;
+    k = 4;
+    while (k > 0)
+    {
+        m0 = pres[0];
+        m3 = pres[3<<6];
+        m0 += m3;
+        m3 = m0 - (m3 << 1);
+        m1 = pres[1<<6];
+        m2 = pres[2<<6];
+        m1 += m2;
+        m2 = m1 - (m2 << 1);
+        m0 = m0 + m1;
+        cost += ((m0 >= 0) ? m0 : -m0);
+        m1 = m0 - (m1 << 1);
+        cost += ((m1 >= 0) ? m1 : -m1);
+        m3 = m2 + m3;
+        cost += ((m3 >= 0) ? m3 : -m3);
+        m2 = m3 - (m2 << 1);
+        cost += ((m2 >= 0) ? m2 : -m2);
+        pres += 4;
+
+        if ((cost >> 1) > min_cost) /* early drop out */
+        {
+            return (cost >> 1);
+        }
+
+        k--;
+    }
+
+    return (cost >> 1);
+}
+
+
+void mb_intra4x4_search(AVCEncObject *encvid, int *min_cost)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCMacroblock *currMB = video->currMB;
+    AVCPictureData *currPic = video->currPic;
+    AVCFrameIO *currInput = encvid->currInput;
+    int pitch = currPic->pitch;
+    int org_pitch = currInput->pitch;
+    int offset;
+    uint8 *curL, *comp, *org4, *org8;
+    int y = video->mb_y << 4;
+    int x = video->mb_x << 4;
+
+    int b8, b4, cost4x4, blkidx;
+    int cost = 0;
+    int numcoef;
+    int dummy = 0;
+    int mb_intra = currMB->mb_intra; // save the original value
+
+    offset = y * pitch + x;
+
+    curL = currPic->Sl + offset;
+    org8 = currInput->YCbCr[0] + y * org_pitch + x;
+    video->pred_pitch = 4;
+
+    cost = (int)(6.0 * encvid->lambda_mode + 0.4999);
+    cost <<= 2;
+
+    currMB->mb_intra = 1;  // temporary set this to one to enable the IDCT
+    // operation inside dct_luma
+
+    for (b8 = 0; b8 < 4; b8++)
+    {
+        comp = curL;
+        org4 = org8;
+
+        for (b4 = 0; b4 < 4; b4++)
+        {
+            blkidx = blkIdx2blkXY[b8][b4];
+            cost4x4 = blk_intra4x4_search(encvid, blkidx, comp, org4);
+            cost += cost4x4;
+            if (cost > *min_cost)
+            {
+                currMB->mb_intra = mb_intra; // restore the value
+                return ;
+            }
+
+            /* do residue, Xfrm, Q, invQ, invXfrm, recon and save the DCT coefs.*/
+            video->pred_block = encvid->pred_i4[currMB->i4Mode[blkidx]];
+            numcoef = dct_luma(encvid, blkidx, comp, org4, &dummy);
+            currMB->nz_coeff[blkidx] = numcoef;
+            if (numcoef)
+            {
+                video->cbp4x4 |= (1 << blkidx);
+                currMB->CBP |= (1 << b8);
+            }
+
+            if (b4&1)
+            {
+                comp += ((pitch << 2) - 4);
+                org4 += ((org_pitch << 2) - 4);
+            }
+            else
+            {
+                comp += 4;
+                org4 += 4;
+            }
+        }
+
+        if (b8&1)
+        {
+            curL += ((pitch << 3) - 8);
+            org8 += ((org_pitch << 3) - 8);
+        }
+        else
+        {
+            curL += 8;
+            org8 += 8;
+        }
+    }
+
+    currMB->mb_intra = mb_intra; // restore the value
+
+    if (cost < *min_cost)
+    {
+        *min_cost = cost;
+        currMB->mbMode = AVC_I4;
+        currMB->mb_intra = 1;
+    }
+
+    return ;
+}
+
+
+/* search for i4 mode for a 4x4 block */
+int blk_intra4x4_search(AVCEncObject *encvid, int blkidx, uint8 *cur, uint8 *org)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCNeighborAvailability availability;
+    AVCMacroblock *currMB = video->currMB;
+    bool top_left = FALSE;
+    int pitch = video->currPic->pitch;
+    uint8 mode_avail[AVCNumI4PredMode];
+    uint32 temp, DC;
+    uint8 *pred;
+    int org_pitch = encvid->currInput->pitch;
+    uint16 min_cost, cost;
+
+    int P_x, Q_x, R_x, P_y, Q_y, R_y, D, D0, D1;
+    int P0, Q0, R0, S0, P1, Q1, R1, P2, Q2;
+    uint8 P_A, P_B, P_C, P_D, P_E, P_F, P_G, P_H, P_I, P_J, P_K, P_L, P_X;
+    int r0, r1, r2, r3, r4, r5, r6, r7;
+    int x0, x1, x2, x3, x4, x5;
+    uint32 temp1, temp2;
+
+    int ipmode, mostProbableMode;
+    int fixedcost = 4 * encvid->lambda_mode;
+    int min_sad = 0x7FFF;
+
+    availability.left = TRUE;
+    availability.top = TRUE;
+    if (blkidx <= 3) /* top row block  (!block_y) */
+    { /* check availability up */
+        availability.top = video->intraAvailB ;
+    }
+    if (!(blkidx&0x3)) /* left column block (!block_x)*/
+    { /* check availability left */
+        availability.left = video->intraAvailA ;
+    }
+    availability.top_right = BlkTopRight[blkidx];
+
+    if (availability.top_right == 2)
+    {
+        availability.top_right = video->intraAvailB;
+    }
+    else if (availability.top_right == 3)
+    {
+        availability.top_right = video->intraAvailC;
+    }
+
+    if (availability.top == TRUE)
+    {
+        temp = *(uint32*)(cur - pitch);
+        P_A = temp & 0xFF;
+        P_B = (temp >> 8) & 0xFF;
+        P_C = (temp >> 16) & 0xFF;
+        P_D = (temp >> 24) & 0xFF;
+    }
+    else
+    {
+        P_A = P_B = P_C = P_D = 128;
+    }
+
+    if (availability.top_right == TRUE)
+    {
+        temp = *(uint32*)(cur - pitch + 4);
+        P_E = temp & 0xFF;
+        P_F = (temp >> 8) & 0xFF;
+        P_G = (temp >> 16) & 0xFF;
+        P_H = (temp >> 24) & 0xFF;
+    }
+    else
+    {
+        P_E = P_F = P_G = P_H = 128;
+    }
+
+    if (availability.left == TRUE)
+    {
+        cur--;
+        P_I = *cur;
+        P_J = *(cur += pitch);
+        P_K = *(cur += pitch);
+        P_L = *(cur + pitch);
+        cur -= (pitch << 1);
+        cur++;
+    }
+    else
+    {
+        P_I = P_J = P_K = P_L = 128;
+    }
+
+    /* check if top-left pixel is available */
+    if (((blkidx > 3) && (blkidx&0x3)) || ((blkidx > 3) && video->intraAvailA)
+            || ((blkidx&0x3) && video->intraAvailB)
+            || (video->intraAvailA && video->intraAvailD && video->intraAvailB))
+    {
+        top_left = TRUE;
+        P_X = *(cur - pitch - 1);
+    }
+    else
+    {
+        P_X = 128;
+    }
+
+    //===== INTRA PREDICTION FOR 4x4 BLOCK =====
+    /* vertical */
+    mode_avail[AVC_I4_Vertical] = 0;
+    if (availability.top)
+    {
+        mode_avail[AVC_I4_Vertical] = 1;
+        pred = encvid->pred_i4[AVC_I4_Vertical];
+
+        temp = (P_D << 24) | (P_C << 16) | (P_B << 8) | P_A ;
+        *((uint32*)pred) =  temp; /* write 4 at a time */
+        *((uint32*)(pred += 4)) =  temp;
+        *((uint32*)(pred += 4)) =  temp;
+        *((uint32*)(pred += 4)) =  temp;
+    }
+    /* horizontal */
+    mode_avail[AVC_I4_Horizontal] = 0;
+    mode_avail[AVC_I4_Horizontal_Up] = 0;
+    if (availability.left)
+    {
+        mode_avail[AVC_I4_Horizontal] = 1;
+        pred = encvid->pred_i4[AVC_I4_Horizontal];
+
+        temp = P_I | (P_I << 8);
+        temp = temp | (temp << 16);
+        *((uint32*)pred) = temp;
+        temp = P_J | (P_J << 8);
+        temp = temp | (temp << 16);
+        *((uint32*)(pred += 4)) = temp;
+        temp = P_K | (P_K << 8);
+        temp = temp | (temp << 16);
+        *((uint32*)(pred += 4)) = temp;
+        temp = P_L | (P_L << 8);
+        temp = temp | (temp << 16);
+        *((uint32*)(pred += 4)) = temp;
+
+        mode_avail[AVC_I4_Horizontal_Up] = 1;
+        pred = encvid->pred_i4[AVC_I4_Horizontal_Up];
+
+        Q0 = (P_J + P_K + 1) >> 1;
+        Q1 = (P_J + (P_K << 1) + P_L + 2) >> 2;
+        P0 = ((P_I + P_J + 1) >> 1);
+        P1 = ((P_I + (P_J << 1) + P_K + 2) >> 2);
+
+        temp = P0 | (P1 << 8);      // [P0 P1 Q0 Q1]
+        temp |= (Q0 << 16);     // [Q0 Q1 R0 DO]
+        temp |= (Q1 << 24);     // [R0 D0 D1 D1]
+        *((uint32*)pred) = temp;      // [D1 D1 D1 D1]
+
+        D0 = (P_K + 3 * P_L + 2) >> 2;
+        R0 = (P_K + P_L + 1) >> 1;
+
+        temp = Q0 | (Q1 << 8);
+        temp |= (R0 << 16);
+        temp |= (D0 << 24);
+        *((uint32*)(pred += 4)) = temp;
+
+        D1 = P_L;
+
+        temp = R0 | (D0 << 8);
+        temp |= (D1 << 16);
+        temp |= (D1 << 24);
+        *((uint32*)(pred += 4)) = temp;
+
+        temp = D1 | (D1 << 8);
+        temp |= (temp << 16);
+        *((uint32*)(pred += 4)) = temp;
+    }
+    /* DC */
+    mode_avail[AVC_I4_DC] = 1;
+    pred = encvid->pred_i4[AVC_I4_DC];
+    if (availability.left)
+    {
+        DC = P_I + P_J + P_K + P_L;
+
+        if (availability.top)
+        {
+            DC = (P_A + P_B + P_C + P_D + DC + 4) >> 3;
+        }
+        else
+        {
+            DC = (DC + 2) >> 2;
+
+        }
+    }
+    else if (availability.top)
+    {
+        DC = (P_A + P_B + P_C + P_D + 2) >> 2;
+
+    }
+    else
+    {
+        DC = 128;
+    }
+
+    temp = DC | (DC << 8);
+    temp = temp | (temp << 16);
+    *((uint32*)pred) = temp;
+    *((uint32*)(pred += 4)) = temp;
+    *((uint32*)(pred += 4)) = temp;
+    *((uint32*)(pred += 4)) = temp;
+
+    /* Down-left */
+    mode_avail[AVC_I4_Diagonal_Down_Left] = 0;
+
+    if (availability.top)
+    {
+        mode_avail[AVC_I4_Diagonal_Down_Left] = 1;
+
+        pred = encvid->pred_i4[AVC_I4_Diagonal_Down_Left];
+
+        r0 = P_A;
+        r1 = P_B;
+        r2 = P_C;
+        r3 = P_D;
+
+        r0 += (r1 << 1);
+        r0 += r2;
+        r0 += 2;
+        r0 >>= 2;
+        r1 += (r2 << 1);
+        r1 += r3;
+        r1 += 2;
+        r1 >>= 2;
+
+        if (availability.top_right)
+        {
+            r4 = P_E;
+            r5 = P_F;
+            r6 = P_G;
+            r7 = P_H;
+
+            r2 += (r3 << 1);
+            r2 += r4;
+            r2 += 2;
+            r2 >>= 2;
+            r3 += (r4 << 1);
+            r3 += r5;
+            r3 += 2;
+            r3 >>= 2;
+            r4 += (r5 << 1);
+            r4 += r6;
+            r4 += 2;
+            r4 >>= 2;
+            r5 += (r6 << 1);
+            r5 += r7;
+            r5 += 2;
+            r5 >>= 2;
+            r6 += (3 * r7);
+            r6 += 2;
+            r6 >>= 2;
+            temp = r0 | (r1 << 8);
+            temp |= (r2 << 16);
+            temp |= (r3 << 24);
+            *((uint32*)pred) = temp;
+
+            temp = (temp >> 8) | (r4 << 24);
+            *((uint32*)(pred += 4)) = temp;
+
+            temp = (temp >> 8) | (r5 << 24);
+            *((uint32*)(pred += 4)) = temp;
+
+            temp = (temp >> 8) | (r6 << 24);
+            *((uint32*)(pred += 4)) = temp;
+        }
+        else
+        {
+            r2 += (r3 * 3);
+            r2 += 2;
+            r2 >>= 2;
+            r3 = ((r3 << 2) + 2);
+            r3 >>= 2;
+
+            temp = r0 | (r1 << 8);
+            temp |= (r2 << 16);
+            temp |= (r3 << 24);
+            *((uint32*)pred) = temp;
+
+            temp = (temp >> 8) | (r3 << 24);
+            *((uint32*)(pred += 4)) = temp;
+
+            temp = (temp >> 8) | (r3 << 24);
+            *((uint32*)(pred += 4)) = temp;
+
+            temp = (temp >> 8) | (r3 << 24);
+            *((uint32*)(pred += 4)) = temp;
+
+        }
+    }
+
+    /* Down Right */
+    mode_avail[AVC_I4_Diagonal_Down_Right] = 0;
+    /* Diagonal Vertical Right */
+    mode_avail[AVC_I4_Vertical_Right] = 0;
+    /* Horizontal Down */
+    mode_avail[AVC_I4_Horizontal_Down] = 0;
+
+    if (top_left == TRUE)
+    {
+        /* Down Right */
+        mode_avail[AVC_I4_Diagonal_Down_Right] = 1;
+        pred = encvid->pred_i4[AVC_I4_Diagonal_Down_Right];
+
+        Q_x = (P_A + 2 * P_B + P_C + 2) >> 2;
+        R_x = (P_B + 2 * P_C + P_D + 2) >> 2;
+        P_x = (P_X + 2 * P_A + P_B + 2) >> 2;
+        D   = (P_A + 2 * P_X + P_I + 2) >> 2;
+        P_y = (P_X + 2 * P_I + P_J + 2) >> 2;
+        Q_y = (P_I + 2 * P_J + P_K + 2) >> 2;
+        R_y = (P_J + 2 * P_K + P_L + 2) >> 2;
+
+        /* we can pack these */
+        temp =  D | (P_x << 8);   //[D   P_x Q_x R_x]
+        //[P_y D   P_x Q_x]
+        temp |= (Q_x << 16); //[Q_y P_y D   P_x]
+        temp |= (R_x << 24);  //[R_y Q_y P_y D  ]
+        *((uint32*)pred) = temp;
+
+        temp =  P_y | (D << 8);
+        temp |= (P_x << 16);
+        temp |= (Q_x << 24);
+        *((uint32*)(pred += 4)) = temp;
+
+        temp =  Q_y | (P_y << 8);
+        temp |= (D << 16);
+        temp |= (P_x << 24);
+        *((uint32*)(pred += 4)) = temp;
+
+        temp = R_y | (Q_y << 8);
+        temp |= (P_y << 16);
+        temp |= (D << 24);
+        *((uint32*)(pred += 4)) = temp;
+
+
+        /* Diagonal Vertical Right */
+        mode_avail[AVC_I4_Vertical_Right] = 1;
+        pred = encvid->pred_i4[AVC_I4_Vertical_Right];
+
+        Q0 = P_A + P_B + 1;
+        R0 = P_B + P_C + 1;
+        S0 = P_C + P_D + 1;
+        P0 = P_X + P_A + 1;
+        D = (P_I + 2 * P_X + P_A + 2) >> 2;
+
+        P1 = (P0 + Q0) >> 2;
+        Q1 = (Q0 + R0) >> 2;
+        R1 = (R0 + S0) >> 2;
+
+        P0 >>= 1;
+        Q0 >>= 1;
+        R0 >>= 1;
+        S0 >>= 1;
+
+        P2 = (P_X + 2 * P_I + P_J + 2) >> 2;
+        Q2 = (P_I + 2 * P_J + P_K + 2) >> 2;
+
+        temp =  P0 | (Q0 << 8);  //[P0 Q0 R0 S0]
+        //[D  P1 Q1 R1]
+        temp |= (R0 << 16); //[P2 P0 Q0 R0]
+        temp |= (S0 << 24); //[Q2 D  P1 Q1]
+        *((uint32*)pred) =  temp;
+
+        temp =  D | (P1 << 8);
+        temp |= (Q1 << 16);
+        temp |= (R1 << 24);
+        *((uint32*)(pred += 4)) =  temp;
+
+        temp = P2 | (P0 << 8);
+        temp |= (Q0 << 16);
+        temp |= (R0 << 24);
+        *((uint32*)(pred += 4)) =  temp;
+
+        temp = Q2 | (D << 8);
+        temp |= (P1 << 16);
+        temp |= (Q1 << 24);
+        *((uint32*)(pred += 4)) =  temp;
+
+
+        /* Horizontal Down */
+        mode_avail[AVC_I4_Horizontal_Down] = 1;
+        pred = encvid->pred_i4[AVC_I4_Horizontal_Down];
+
+
+        Q2 = (P_A + 2 * P_B + P_C + 2) >> 2;
+        P2 = (P_X + 2 * P_A + P_B + 2) >> 2;
+        D = (P_I + 2 * P_X + P_A + 2) >> 2;
+        P0 = P_X + P_I + 1;
+        Q0 = P_I + P_J + 1;
+        R0 = P_J + P_K + 1;
+        S0 = P_K + P_L + 1;
+
+        P1 = (P0 + Q0) >> 2;
+        Q1 = (Q0 + R0) >> 2;
+        R1 = (R0 + S0) >> 2;
+
+        P0 >>= 1;
+        Q0 >>= 1;
+        R0 >>= 1;
+        S0 >>= 1;
+
+
+        /* we can pack these */
+        temp = P0 | (D << 8);   //[P0 D  P2 Q2]
+        //[Q0 P1 P0 D ]
+        temp |= (P2 << 16);  //[R0 Q1 Q0 P1]
+        temp |= (Q2 << 24); //[S0 R1 R0 Q1]
+        *((uint32*)pred) = temp;
+
+        temp = Q0 | (P1 << 8);
+        temp |= (P0 << 16);
+        temp |= (D << 24);
+        *((uint32*)(pred += 4)) = temp;
+
+        temp = R0 | (Q1 << 8);
+        temp |= (Q0 << 16);
+        temp |= (P1 << 24);
+        *((uint32*)(pred += 4)) = temp;
+
+        temp = S0 | (R1 << 8);
+        temp |= (R0 << 16);
+        temp |= (Q1 << 24);
+        *((uint32*)(pred += 4)) = temp;
+
+    }
+
+    /* vertical left */
+    mode_avail[AVC_I4_Vertical_Left] = 0;
+    if (availability.top)
+    {
+        mode_avail[AVC_I4_Vertical_Left] = 1;
+        pred = encvid->pred_i4[AVC_I4_Vertical_Left];
+
+        x0 = P_A + P_B + 1;
+        x1 = P_B + P_C + 1;
+        x2 = P_C + P_D + 1;
+        if (availability.top_right)
+        {
+            x3 = P_D + P_E + 1;
+            x4 = P_E + P_F + 1;
+            x5 = P_F + P_G + 1;
+        }
+        else
+        {
+            x3 = x4 = x5 = (P_D << 1) + 1;
+        }
+
+        temp1 = (x0 >> 1);
+        temp1 |= ((x1 >> 1) << 8);
+        temp1 |= ((x2 >> 1) << 16);
+        temp1 |= ((x3 >> 1) << 24);
+
+        *((uint32*)pred) = temp1;
+
+        temp2 = ((x0 + x1) >> 2);
+        temp2 |= (((x1 + x2) >> 2) << 8);
+        temp2 |= (((x2 + x3) >> 2) << 16);
+        temp2 |= (((x3 + x4) >> 2) << 24);
+
+        *((uint32*)(pred += 4)) = temp2;
+
+        temp1 = (temp1 >> 8) | ((x4 >> 1) << 24);   /* rotate out old value */
+        *((uint32*)(pred += 4)) = temp1;
+
+        temp2 = (temp2 >> 8) | (((x4 + x5) >> 2) << 24); /* rotate out old value */
+        *((uint32*)(pred += 4)) = temp2;
+    }
+
+    //===== LOOP OVER ALL 4x4 INTRA PREDICTION MODES =====
+    // can re-order the search here instead of going in order
+
+    // find most probable mode
+    encvid->mostProbableI4Mode[blkidx] = mostProbableMode = FindMostProbableI4Mode(video, blkidx);
+
+    min_cost = 0xFFFF;
+
+    for (ipmode = 0; ipmode < AVCNumI4PredMode; ipmode++)
+    {
+        if (mode_avail[ipmode] == TRUE)
+        {
+            cost  = (ipmode == mostProbableMode) ? 0 : fixedcost;
+            pred = encvid->pred_i4[ipmode];
+
+            cost_i4(org, org_pitch, pred, &cost);
+
+            if (cost < min_cost)
+            {
+                currMB->i4Mode[blkidx] = (AVCIntra4x4PredMode)ipmode;
+                min_cost   = cost;
+                min_sad = cost - ((ipmode == mostProbableMode) ? 0 : fixedcost);
+            }
+        }
+    }
+
+    if (blkidx == 0)
+    {
+        encvid->i4_sad = min_sad;
+    }
+    else
+    {
+        encvid->i4_sad += min_sad;
+    }
+
+    return min_cost;
+}
+
+int FindMostProbableI4Mode(AVCCommonObj *video, int blkidx)
+{
+    int dcOnlyPredictionFlag;
+    AVCMacroblock *currMB = video->currMB;
+    int intra4x4PredModeA, intra4x4PredModeB, predIntra4x4PredMode;
+
+
+    dcOnlyPredictionFlag = 0;
+    if (blkidx&0x3)
+    {
+        intra4x4PredModeA = currMB->i4Mode[blkidx-1]; // block to the left
+    }
+    else /* for blk 0, 4, 8, 12 */
+    {
+        if (video->intraAvailA)
+        {
+            if (video->mblock[video->mbAddrA].mbMode == AVC_I4)
+            {
+                intra4x4PredModeA = video->mblock[video->mbAddrA].i4Mode[blkidx + 3];
+            }
+            else
+            {
+                intra4x4PredModeA = AVC_I4_DC;
+            }
+        }
+        else
+        {
+            dcOnlyPredictionFlag = 1;
+            goto PRED_RESULT_READY;  // skip below
+        }
+    }
+
+    if (blkidx >> 2)
+    {
+        intra4x4PredModeB = currMB->i4Mode[blkidx-4]; // block above
+    }
+    else /* block 0, 1, 2, 3 */
+    {
+        if (video->intraAvailB)
+        {
+            if (video->mblock[video->mbAddrB].mbMode == AVC_I4)
+            {
+                intra4x4PredModeB = video->mblock[video->mbAddrB].i4Mode[blkidx+12];
+            }
+            else
+            {
+                intra4x4PredModeB = AVC_I4_DC;
+            }
+        }
+        else
+        {
+            dcOnlyPredictionFlag = 1;
+        }
+    }
+
+PRED_RESULT_READY:
+    if (dcOnlyPredictionFlag)
+    {
+        intra4x4PredModeA = intra4x4PredModeB = AVC_I4_DC;
+    }
+
+    predIntra4x4PredMode = AVC_MIN(intra4x4PredModeA, intra4x4PredModeB);
+
+    return predIntra4x4PredMode;
+}
+
+void cost_i4(uint8 *org, int org_pitch, uint8 *pred, uint16 *cost)
+{
+    int k;
+    int16 res[16], *pres;
+    int m0, m1, m2, m3, tmp1;
+    int satd = 0;
+
+    pres = res;
+    // horizontal transform
+    k = 4;
+    while (k > 0)
+    {
+        m0 = org[0] - pred[0];
+        m3 = org[3] - pred[3];
+        m0 += m3;
+        m3 = m0 - (m3 << 1);
+        m1 = org[1] - pred[1];
+        m2 = org[2] - pred[2];
+        m1 += m2;
+        m2 = m1 - (m2 << 1);
+        pres[0] = m0 + m1;
+        pres[2] = m0 - m1;
+        pres[1] = m2 + m3;
+        pres[3] = m3 - m2;
+
+        org += org_pitch;
+        pres += 4;
+        pred += 4;
+        k--;
+    }
+    /* vertical transform */
+    pres = res;
+    k = 4;
+    while (k > 0)
+    {
+        m0 = pres[0];
+        m3 = pres[12];
+        m0 += m3;
+        m3 = m0 - (m3 << 1);
+        m1 = pres[4];
+        m2 = pres[8];
+        m1 += m2;
+        m2 = m1 - (m2 << 1);
+        pres[0] = m0 + m1;
+        pres[8] = m0 - m1;
+        pres[4] = m2 + m3;
+        pres[12] = m3 - m2;
+
+        pres++;
+        k--;
+
+    }
+
+    pres = res;
+    k = 4;
+    while (k > 0)
+    {
+        tmp1 = *pres++;
+        satd += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        satd += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        satd += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        satd += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        k--;
+    }
+
+    satd = (satd + 1) >> 1;
+    *cost += satd;
+
+    return ;
+}
+
+void chroma_intra_search(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCPictureData *currPic = video->currPic;
+
+    int x_pos = video->mb_x << 3;
+    int y_pos = video->mb_y << 3;
+    int pitch = currPic->pitch >> 1;
+    int offset = y_pos * pitch + x_pos;
+
+    uint8 *comp_ref_x, *comp_ref_y, *pred;
+    int  sum_x0, sum_x1, sum_y0, sum_y1;
+    int pred_0[2], pred_1[2], pred_2[2], pred_3[2];
+    uint32 pred_a, pred_b, pred_c, pred_d;
+    int i, j, component;
+    int a_16, b, c, factor_c, topleft;
+    int H, V, value;
+    uint8 *comp_ref_x0, *comp_ref_x1,  *comp_ref_y0, *comp_ref_y1;
+
+    uint8 *curCb = currPic->Scb + offset;
+    uint8 *curCr = currPic->Scr + offset;
+
+    uint8 *orgCb, *orgCr;
+    AVCFrameIO *currInput = encvid->currInput;
+    AVCMacroblock *currMB = video->currMB;
+    int org_pitch;
+    int cost, mincost;
+
+    /* evaluate DC mode */
+    if (video->intraAvailB & video->intraAvailA)
+    {
+        comp_ref_x = curCb - pitch;
+        comp_ref_y = curCb - 1;
+
+        for (i = 0; i < 2; i++)
+        {
+            pred_a = *((uint32*)comp_ref_x);
+            comp_ref_x += 4;
+            pred_b = (pred_a >> 8) & 0xFF00FF;
+            pred_a &= 0xFF00FF;
+            pred_a += pred_b;
+            pred_a += (pred_a >> 16);
+            sum_x0 = pred_a & 0xFFFF;
+
+            pred_a = *((uint32*)comp_ref_x);
+            pred_b = (pred_a >> 8) & 0xFF00FF;
+            pred_a &= 0xFF00FF;
+            pred_a += pred_b;
+            pred_a += (pred_a >> 16);
+            sum_x1 = pred_a & 0xFFFF;
+
+            pred_1[i] = (sum_x1 + 2) >> 2;
+
+            sum_y0 = *comp_ref_y;
+            sum_y0 += *(comp_ref_y += pitch);
+            sum_y0 += *(comp_ref_y += pitch);
+            sum_y0 += *(comp_ref_y += pitch);
+
+            sum_y1 = *(comp_ref_y += pitch);
+            sum_y1 += *(comp_ref_y += pitch);
+            sum_y1 += *(comp_ref_y += pitch);
+            sum_y1 += *(comp_ref_y += pitch);
+
+            pred_2[i] = (sum_y1 + 2) >> 2;
+
+            pred_0[i] = (sum_y0 + sum_x0 + 4) >> 3;
+            pred_3[i] = (sum_y1 + sum_x1 + 4) >> 3;
+
+            comp_ref_x = curCr - pitch;
+            comp_ref_y = curCr - 1;
+        }
+    }
+
+    else if (video->intraAvailA)
+    {
+        comp_ref_y = curCb - 1;
+        for (i = 0; i < 2; i++)
+        {
+            sum_y0 = *comp_ref_y;
+            sum_y0 += *(comp_ref_y += pitch);
+            sum_y0 += *(comp_ref_y += pitch);
+            sum_y0 += *(comp_ref_y += pitch);
+
+            sum_y1 = *(comp_ref_y += pitch);
+            sum_y1 += *(comp_ref_y += pitch);
+            sum_y1 += *(comp_ref_y += pitch);
+            sum_y1 += *(comp_ref_y += pitch);
+
+            pred_0[i] = pred_1[i] = (sum_y0 + 2) >> 2;
+            pred_2[i] = pred_3[i] = (sum_y1 + 2) >> 2;
+
+            comp_ref_y = curCr - 1;
+        }
+    }
+    else if (video->intraAvailB)
+    {
+        comp_ref_x = curCb - pitch;
+        for (i = 0; i < 2; i++)
+        {
+            pred_a = *((uint32*)comp_ref_x);
+            comp_ref_x += 4;
+            pred_b = (pred_a >> 8) & 0xFF00FF;
+            pred_a &= 0xFF00FF;
+            pred_a += pred_b;
+            pred_a += (pred_a >> 16);
+            sum_x0 = pred_a & 0xFFFF;
+
+            pred_a = *((uint32*)comp_ref_x);
+            pred_b = (pred_a >> 8) & 0xFF00FF;
+            pred_a &= 0xFF00FF;
+            pred_a += pred_b;
+            pred_a += (pred_a >> 16);
+            sum_x1 = pred_a & 0xFFFF;
+
+            pred_0[i] = pred_2[i] = (sum_x0 + 2) >> 2;
+            pred_1[i] = pred_3[i] = (sum_x1 + 2) >> 2;
+
+            comp_ref_x = curCr - pitch;
+        }
+    }
+    else
+    {
+        pred_0[0] = pred_0[1] = pred_1[0] = pred_1[1] =
+                                                pred_2[0] = pred_2[1] = pred_3[0] = pred_3[1] = 128;
+    }
+
+    pred = encvid->pred_ic[AVC_IC_DC];
+
+    pred_a = pred_0[0];
+    pred_b = pred_1[0];
+    pred_a |= (pred_a << 8);
+    pred_a |= (pred_a << 16);
+    pred_b |= (pred_b << 8);
+    pred_b |= (pred_b << 16);
+
+    pred_c = pred_0[1];
+    pred_d = pred_1[1];
+    pred_c |= (pred_c << 8);
+    pred_c |= (pred_c << 16);
+    pred_d |= (pred_d << 8);
+    pred_d |= (pred_d << 16);
+
+
+    for (j = 0; j < 4; j++) /* 4 lines */
+    {
+        *((uint32*)pred) = pred_a;
+        *((uint32*)(pred + 4)) = pred_b;
+        *((uint32*)(pred + 8)) = pred_c;
+        *((uint32*)(pred + 12)) = pred_d;
+        pred += 16; /* move to the next line */
+    }
+
+    pred_a = pred_2[0];
+    pred_b = pred_3[0];
+    pred_a |= (pred_a << 8);
+    pred_a |= (pred_a << 16);
+    pred_b |= (pred_b << 8);
+    pred_b |= (pred_b << 16);
+
+    pred_c = pred_2[1];
+    pred_d = pred_3[1];
+    pred_c |= (pred_c << 8);
+    pred_c |= (pred_c << 16);
+    pred_d |= (pred_d << 8);
+    pred_d |= (pred_d << 16);
+
+    for (j = 0; j < 4; j++) /* 4 lines */
+    {
+        *((uint32*)pred) = pred_a;
+        *((uint32*)(pred + 4)) = pred_b;
+        *((uint32*)(pred + 8)) = pred_c;
+        *((uint32*)(pred + 12)) = pred_d;
+        pred += 16; /* move to the next line */
+    }
+
+    /* predict horizontal mode */
+    if (video->intraAvailA)
+    {
+        comp_ref_y = curCb - 1;
+        comp_ref_x = curCr - 1;
+        pred = encvid->pred_ic[AVC_IC_Horizontal];
+
+        for (i = 4; i < 6; i++)
+        {
+            for (j = 0; j < 4; j++)
+            {
+                pred_a = *comp_ref_y;
+                comp_ref_y += pitch;
+                pred_a |= (pred_a << 8);
+                pred_a |= (pred_a << 16);
+                *((uint32*)pred) = pred_a;
+                *((uint32*)(pred + 4)) = pred_a;
+
+                pred_a = *comp_ref_x;
+                comp_ref_x += pitch;
+                pred_a |= (pred_a << 8);
+                pred_a |= (pred_a << 16);
+                *((uint32*)(pred + 8)) = pred_a;
+                *((uint32*)(pred + 12)) = pred_a;
+
+                pred += 16;
+            }
+        }
+    }
+
+    /* vertical mode */
+    if (video->intraAvailB)
+    {
+        comp_ref_x = curCb - pitch;
+        comp_ref_y = curCr - pitch;
+        pred = encvid->pred_ic[AVC_IC_Vertical];
+
+        pred_a = *((uint32*)comp_ref_x);
+        pred_b = *((uint32*)(comp_ref_x + 4));
+        pred_c = *((uint32*)comp_ref_y);
+        pred_d = *((uint32*)(comp_ref_y + 4));
+
+        for (j = 0; j < 8; j++)
+        {
+            *((uint32*)pred) = pred_a;
+            *((uint32*)(pred + 4)) = pred_b;
+            *((uint32*)(pred + 8)) = pred_c;
+            *((uint32*)(pred + 12)) = pred_d;
+            pred += 16;
+        }
+    }
+
+    /* Intra_Chroma_Plane */
+    if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+    {
+        comp_ref_x = curCb - pitch;
+        comp_ref_y = curCb - 1;
+        topleft = curCb[-pitch-1];
+
+        pred = encvid->pred_ic[AVC_IC_Plane];
+        for (component = 0; component < 2; component++)
+        {
+            H = V = 0;
+            comp_ref_x0 = comp_ref_x + 4;
+            comp_ref_x1 = comp_ref_x + 2;
+            comp_ref_y0 = comp_ref_y + (pitch << 2);
+            comp_ref_y1 = comp_ref_y + (pitch << 1);
+            for (i = 1; i < 4; i++)
+            {
+                H += i * (*comp_ref_x0++ - *comp_ref_x1--);
+                V += i * (*comp_ref_y0 - *comp_ref_y1);
+                comp_ref_y0 += pitch;
+                comp_ref_y1 -= pitch;
+            }
+            H += i * (*comp_ref_x0++ - topleft);
+            V += i * (*comp_ref_y0 - *comp_ref_y1);
+
+            a_16 = ((*(comp_ref_x + 7) + *(comp_ref_y + 7 * pitch)) << 4) + 16;
+            b = (17 * H + 16) >> 5;
+            c = (17 * V + 16) >> 5;
+
+            pred_a = 0;
+            for (i = 4; i < 6; i++)
+            {
+                for (j = 0; j < 4; j++)
+                {
+                    factor_c = a_16 + c * (pred_a++ - 3);
+
+                    factor_c -= 3 * b;
+
+                    value = factor_c >> 5;
+                    factor_c += b;
+                    CLIP_RESULT(value)
+                    pred_b = value;
+                    value = factor_c >> 5;
+                    factor_c += b;
+                    CLIP_RESULT(value)
+                    pred_b |= (value << 8);
+                    value = factor_c >> 5;
+                    factor_c += b;
+                    CLIP_RESULT(value)
+                    pred_b |= (value << 16);
+                    value = factor_c >> 5;
+                    factor_c += b;
+                    CLIP_RESULT(value)
+                    pred_b |= (value << 24);
+                    *((uint32*)pred) = pred_b;
+
+                    value = factor_c >> 5;
+                    factor_c += b;
+                    CLIP_RESULT(value)
+                    pred_b = value;
+                    value = factor_c >> 5;
+                    factor_c += b;
+                    CLIP_RESULT(value)
+                    pred_b |= (value << 8);
+                    value = factor_c >> 5;
+                    factor_c += b;
+                    CLIP_RESULT(value)
+                    pred_b |= (value << 16);
+                    value = factor_c >> 5;
+                    factor_c += b;
+                    CLIP_RESULT(value)
+                    pred_b |= (value << 24);
+                    *((uint32*)(pred + 4)) = pred_b;
+                    pred += 16;
+                }
+            }
+
+            pred -= 120; /* point to cr */
+            comp_ref_x = curCr - pitch;
+            comp_ref_y = curCr - 1;
+            topleft = curCr[-pitch-1];
+        }
+    }
+
+    /* now evaluate it */
+
+    org_pitch = (currInput->pitch) >> 1;
+    offset = x_pos + y_pos * org_pitch;
+
+    orgCb = currInput->YCbCr[1] + offset;
+    orgCr = currInput->YCbCr[2] + offset;
+
+    mincost = 0x7fffffff;
+    cost = SATDChroma(orgCb, orgCr, org_pitch, encvid->pred_ic[AVC_IC_DC], mincost);
+    if (cost < mincost)
+    {
+        mincost = cost;
+        currMB->intra_chroma_pred_mode = AVC_IC_DC;
+    }
+
+    if (video->intraAvailA)
+    {
+        cost = SATDChroma(orgCb, orgCr, org_pitch, encvid->pred_ic[AVC_IC_Horizontal], mincost);
+        if (cost < mincost)
+        {
+            mincost = cost;
+            currMB->intra_chroma_pred_mode = AVC_IC_Horizontal;
+        }
+    }
+
+    if (video->intraAvailB)
+    {
+        cost = SATDChroma(orgCb, orgCr, org_pitch, encvid->pred_ic[AVC_IC_Vertical], mincost);
+        if (cost < mincost)
+        {
+            mincost = cost;
+            currMB->intra_chroma_pred_mode = AVC_IC_Vertical;
+        }
+    }
+
+    if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+    {
+        cost = SATDChroma(orgCb, orgCr, org_pitch, encvid->pred_ic[AVC_IC_Plane], mincost);
+        if (cost < mincost)
+        {
+            mincost = cost;
+            currMB->intra_chroma_pred_mode = AVC_IC_Plane;
+        }
+    }
+
+
+    return ;
+}
+
+
+int SATDChroma(uint8 *orgCb, uint8 *orgCr, int org_pitch, uint8 *pred, int min_cost)
+{
+    int cost;
+    /* first take difference between orgCb, orgCr and pred */
+    int16 res[128], *pres; // residue
+    int m0, m1, m2, m3, tmp1;
+    int j, k;
+
+    pres = res;
+    org_pitch -= 8;
+    // horizontal transform
+    for (j = 0; j < 8; j++)
+    {
+        k = 2;
+        while (k > 0)
+        {
+            m0 = orgCb[0] - pred[0];
+            m3 = orgCb[3] - pred[3];
+            m0 += m3;
+            m3 = m0 - (m3 << 1);
+            m1 = orgCb[1] - pred[1];
+            m2 = orgCb[2] - pred[2];
+            m1 += m2;
+            m2 = m1 - (m2 << 1);
+            pres[0] = m0 + m1;
+            pres[2] = m0 - m1;
+            pres[1] = m2 + m3;
+            pres[3] = m3 - m2;
+
+            orgCb += 4;
+            pres += 4;
+            pred += 4;
+            k--;
+        }
+        orgCb += org_pitch;
+        k = 2;
+        while (k > 0)
+        {
+            m0 = orgCr[0] - pred[0];
+            m3 = orgCr[3] - pred[3];
+            m0 += m3;
+            m3 = m0 - (m3 << 1);
+            m1 = orgCr[1] - pred[1];
+            m2 = orgCr[2] - pred[2];
+            m1 += m2;
+            m2 = m1 - (m2 << 1);
+            pres[0] = m0 + m1;
+            pres[2] = m0 - m1;
+            pres[1] = m2 + m3;
+            pres[3] = m3 - m2;
+
+            orgCr += 4;
+            pres += 4;
+            pred += 4;
+            k--;
+        }
+        orgCr += org_pitch;
+    }
+
+    /* vertical transform */
+    for (j = 0; j < 2; j++)
+    {
+        pres = res + (j << 6);
+        k = 16;
+        while (k > 0)
+        {
+            m0 = pres[0];
+            m3 = pres[3<<4];
+            m0 += m3;
+            m3 = m0 - (m3 << 1);
+            m1 = pres[1<<4];
+            m2 = pres[2<<4];
+            m1 += m2;
+            m2 = m1 - (m2 << 1);
+            pres[0] = m0 + m1;
+            pres[2<<4] = m0 - m1;
+            pres[1<<4] = m2 + m3;
+            pres[3<<4] = m3 - m2;
+
+            pres++;
+            k--;
+        }
+    }
+
+    /* now sum of absolute value */
+    pres = res;
+    cost = 0;
+    k = 128;
+    while (k > 0)
+    {
+        tmp1 = *pres++;
+        cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        tmp1 = *pres++;
+        cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+        k -= 8;
+        if (cost > min_cost) /* early drop out */
+        {
+            return cost;
+        }
+    }
+
+    return cost;
+}
+
+
+
+///////////////////////////////// old code, unused
+/* find the best intra mode based on original (unencoded) frame */
+/* output is
+    currMB->mb_intra, currMB->mbMode,
+    currMB->i16Mode  (if currMB->mbMode == AVC_I16)
+    currMB->i4Mode[..] (if currMB->mbMode == AVC_I4) */
+
+#ifdef FIXED_INTRAPRED_MODE
+void MBIntraSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum)
+{
+    (void)(mbNum);
+
+    AVCCommonObj *video = encvid->common;
+    int indx, block_x, block_y;
+
+    video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
+
+    if (!video->currPicParams->constrained_intra_pred_flag)
+    {
+        video->intraAvailA = video->mbAvailA;
+        video->intraAvailB = video->mbAvailB;
+        video->intraAvailC = video->mbAvailC;
+        video->intraAvailD = video->mbAvailD;
+    }
+    else
+    {
+        if (video->mbAvailA)
+        {
+            video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
+        }
+        if (video->mbAvailB)
+        {
+            video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
+        }
+        if (video->mbAvailC)
+        {
+            video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
+        }
+        if (video->mbAvailD)
+        {
+            video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
+        }
+    }
+
+    currMB->mb_intra = TRUE;
+    currMB->mbMode = FIXED_INTRAPRED_MODE;
+
+    if (currMB->mbMode == AVC_I16)
+    {
+        currMB->i16Mode = FIXED_I16_MODE;
+
+        if (FIXED_I16_MODE == AVC_I16_Vertical && !video->intraAvailB)
+        {
+            currMB->i16Mode = AVC_I16_DC;
+        }
+
+        if (FIXED_I16_MODE == AVC_I16_Horizontal && !video->intraAvailA)
+        {
+            currMB->i16Mode = AVC_I16_DC;
+        }
+
+        if (FIXED_I16_MODE == AVC_I16_Plane && !(video->intraAvailA && video->intraAvailB && video->intraAvailD))
+        {
+            currMB->i16Mode = AVC_I16_DC;
+        }
+    }
+    else //if(currMB->mbMode == AVC_I4)
+    {
+        for (indx = 0; indx < 16; indx++)
+        {
+            block_x = blkIdx2blkX[indx];
+            block_y = blkIdx2blkY[indx];
+
+            currMB->i4Mode[(block_y<<2)+block_x] = FIXED_I4_MODE;
+
+            if (FIXED_I4_MODE == AVC_I4_Vertical && !(block_y > 0 || video->intraAvailB))
+            {
+                currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+            }
+
+            if (FIXED_I4_MODE == AVC_I4_Horizontal && !(block_x || video->intraAvailA))
+            {
+                currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+            }
+
+            if (FIXED_I4_MODE == AVC_I4_Diagonal_Down_Left &&
+                    (block_y == 0 && !video->intraAvailB))
+            {
+                currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+            }
+
+            if (FIXED_I4_MODE == AVC_I4_Diagonal_Down_Right &&
+                    !((block_y && block_x)
+                      || (block_y && video->intraAvailA)
+                      || (block_x && video->intraAvailB)
+                      || (video->intraAvailA && video->intraAvailD && video->intraAvailB)))
+            {
+                currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+            }
+
+            if (FIXED_I4_MODE == AVC_I4_Vertical_Right &&
+                    !((block_y && block_x)
+                      || (block_y && video->intraAvailA)
+                      || (block_x && video->intraAvailB)
+                      || (video->intraAvailA && video->intraAvailD && video->intraAvailB)))
+            {
+                currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+            }
+
+            if (FIXED_I4_MODE == AVC_I4_Horizontal_Down &&
+                    !((block_y && block_x)
+                      || (block_y && video->intraAvailA)
+                      || (block_x && video->intraAvailB)
+                      || (video->intraAvailA && video->intraAvailD && video->intraAvailB)))
+            {
+                currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+            }
+
+            if (FIXED_I4_MODE == AVC_I4_Vertical_Left &&
+                    (block_y == 0 && !video->intraAvailB))
+            {
+                currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+            }
+
+            if (FIXED_I4_MODE == AVC_I4_Horizontal_Up && !(block_x || video->intraAvailA))
+            {
+                currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+            }
+        }
+    }
+
+    currMB->intra_chroma_pred_mode = FIXED_INTRA_CHROMA_MODE;
+
+    if (FIXED_INTRA_CHROMA_MODE == AVC_IC_Horizontal && !(video->intraAvailA))
+    {
+        currMB->intra_chroma_pred_mode = AVC_IC_DC;
+    }
+
+    if (FIXED_INTRA_CHROMA_MODE == AVC_IC_Vertical && !(video->intraAvailB))
+    {
+        currMB->intra_chroma_pred_mode = AVC_IC_DC;
+    }
+
+    if (FIXED_INTRA_CHROMA_MODE == AVC_IC_Plane && !(video->intraAvailA && video->intraAvailB && video->intraAvailD))
+    {
+        currMB->intra_chroma_pred_mode = AVC_IC_DC;
+    }
+
+    /* also reset the motion vectors */
+    /* set MV and Ref_Idx codes of Intra blocks in P-slices */
+    memset(currMB->mvL0, 0, sizeof(int32)*16);
+    currMB->ref_idx_L0[0] = -1;
+    currMB->ref_idx_L0[1] = -1;
+    currMB->ref_idx_L0[2] = -1;
+    currMB->ref_idx_L0[3] = -1;
+
+    // output from this function, currMB->mbMode should be set to either
+    // AVC_I4, AVC_I16, or else in AVCMBMode enum, mbType, mb_intra, intra_chroma_pred_mode */
+    return ;
+}
+#else // faster combined prediction+SAD calculation
+void MBIntraSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCFrameIO *currInput = encvid->currInput;
+    uint8 *curL, *curCb, *curCr;
+    uint8 *comp, *pred_block;
+    int block_x, block_y, offset;
+    uint sad, sad4, sadI4, sadI16;
+    int component, SubBlock_indx, temp;
+    int pitch = video->currPic->pitch;
+
+    /* calculate the cost of each intra prediction mode  and compare to the
+    inter mode */
+    /* full search for all intra prediction */
+    offset = (video->mb_y << 4) * pitch + (video->mb_x << 4);
+    curL = currInput->YCbCr[0] + offset;
+    pred_block = video->pred_block + 84;
+
+    /* Assuming that InitNeighborAvailability has been called prior to this function */
+    video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
+
+    if (!video->currPicParams->constrained_intra_pred_flag)
+    {
+        video->intraAvailA = video->mbAvailA;
+        video->intraAvailB = video->mbAvailB;
+        video->intraAvailC = video->mbAvailC;
+        video->intraAvailD = video->mbAvailD;
+    }
+    else
+    {
+        if (video->mbAvailA)
+        {
+            video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
+        }
+        if (video->mbAvailB)
+        {
+            video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
+        }
+        if (video->mbAvailC)
+        {
+            video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
+        }
+        if (video->mbAvailD)
+        {
+            video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
+        }
+    }
+
+    /* currently we're doing exhaustive search. Smart search will be used later */
+
+    /* I16 modes */
+    curL = currInput->YCbCr[0] + offset;
+    video->pintra_pred_top = curL - pitch;
+    video->pintra_pred_left = curL - 1;
+    if (video->mb_y)
+    {
+        video->intra_pred_topleft = *(curL - pitch - 1);
+    }
+
+    /* Intra_16x16_Vertical */
+    sadI16 = 65536;
+    /* check availability of top */
+    if (video->intraAvailB)
+    {
+        sad = SAD_I16_Vert(video, curL, sadI16);
+
+        if (sad < sadI16)
+        {
+            sadI16 = sad;
+            currMB->i16Mode = AVC_I16_Vertical;
+        }
+    }
+    /* Intra_16x16_Horizontal */
+    /* check availability of left */
+    if (video->intraAvailA)
+    {
+        sad = SAD_I16_HorzDC(video, curL, AVC_I16_Horizontal, sadI16);
+
+        if (sad < sadI16)
+        {
+            sadI16 = sad;
+            currMB->i16Mode = AVC_I16_Horizontal;
+        }
+    }
+
+    /* Intra_16x16_DC, default mode */
+    sad = SAD_I16_HorzDC(video, curL, AVC_I16_DC, sadI16);
+    if (sad < sadI16)
+    {
+        sadI16 = sad;
+        currMB->i16Mode = AVC_I16_DC;
+    }
+
+    /* Intra_16x16_Plane */
+    if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+    {
+        sad = SAD_I16_Plane(video, curL, sadI16);
+
+        if (sad < sadI16)
+        {
+            sadI16 = sad;
+            currMB->i16Mode = AVC_I16_Plane;
+        }
+    }
+
+    sadI16 >>= 1;  /* before comparison */
+
+    /* selection between intra4, intra16 or inter mode */
+    if (sadI16 < encvid->min_cost)
+    {
+        currMB->mb_intra = TRUE;
+        currMB->mbMode = AVC_I16;
+        encvid->min_cost = sadI16;
+    }
+
+    if (currMB->mb_intra) /* only do the chrominance search when intra is decided */
+    {
+        /* Note that we might be able to guess the type of prediction from
+        the luma prediction type */
+
+        /* now search for the best chroma intra prediction */
+        offset = (offset >> 2) + (video->mb_x << 2);
+        curCb = currInput->YCbCr[1] + offset;
+        curCr = currInput->YCbCr[2] + offset;
+
+        pitch >>= 1;
+        video->pintra_pred_top_cb = curCb - pitch;
+        video->pintra_pred_left_cb = curCb - 1;
+        video->pintra_pred_top_cr = curCr - pitch;
+        video->pintra_pred_left_cr = curCr - 1;
+
+        if (video->mb_y)
+        {
+            video->intra_pred_topleft_cb = *(curCb - pitch - 1);
+            video->intra_pred_topleft_cr = *(curCr - pitch - 1);
+        }
+
+        /* Intra_Chroma_DC */
+        sad4 = SAD_Chroma_DC(video, curCb, curCr, 65536);
+        currMB->intra_chroma_pred_mode = AVC_IC_DC;
+
+        /* Intra_Chroma_Horizontal */
+        if (video->intraAvailA)
+        {
+            /* check availability of left */
+            sad = SAD_Chroma_Horz(video, curCb, curCr, sad4);
+            if (sad < sad4)
+            {
+                sad4 = sad;
+                currMB->intra_chroma_pred_mode = AVC_IC_Horizontal;
+            }
+        }
+
+        /* Intra_Chroma_Vertical */
+        if (video->intraAvailB)
+        {
+            /* check availability of top */
+            sad = SAD_Chroma_Vert(video, curCb, curCr, sad4);
+
+            if (sad < sad4)
+            {
+                sad4 = sad;
+                currMB->intra_chroma_pred_mode = AVC_IC_Vertical;
+            }
+        }
+
+        /* Intra_Chroma_Plane */
+        if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+        {
+            /* check availability of top and left */
+            Intra_Chroma_Plane(video, pitch);
+
+            sad = SADChroma(pred_block + 452, curCb, curCr, pitch);
+
+            if (sad < sad4)
+            {
+                sad4 = sad;
+                currMB->intra_chroma_pred_mode = AVC_IC_Plane;
+            }
+        }
+
+        /* also reset the motion vectors */
+        /* set MV and Ref_Idx codes of Intra blocks in P-slices */
+        memset(currMB->mvL0, 0, sizeof(int32)*16);
+        memset(currMB->ref_idx_L0, -1, sizeof(int16)*4);
+
+    }
+
+    // output from this function, currMB->mbMode should be set to either
+    // AVC_I4, AVC_I16, or else in AVCMBMode enum, mbType, mb_intra, intra_chroma_pred_mode */
+
+    return ;
+}
+#endif
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/motion_comp.cpp b/media/libstagefright/codecs/avc/enc/src/motion_comp.cpp
new file mode 100644
index 0000000..ac62d78
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/motion_comp.cpp
@@ -0,0 +1,2156 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include "avcenc_int.h"
+
+
+#define CLIP_RESULT(x)      if((uint)x > 0xFF){ \
+                 x = 0xFF & (~(x>>31));}
+
+/* (blkwidth << 2) + (dy << 1) + dx */
+static void (*const eChromaMC_SIMD[8])(uint8 *, int , int , int , uint8 *, int, int , int) =
+{
+    &eChromaFullMC_SIMD,
+    &eChromaHorizontalMC_SIMD,
+    &eChromaVerticalMC_SIMD,
+    &eChromaDiagonalMC_SIMD,
+    &eChromaFullMC_SIMD,
+    &eChromaHorizontalMC2_SIMD,
+    &eChromaVerticalMC2_SIMD,
+    &eChromaDiagonalMC2_SIMD
+};
+/* Perform motion prediction and compensation with residue if exist. */
+void AVCMBMotionComp(AVCEncObject *encvid, AVCCommonObj *video)
+{
+    (void)(encvid);
+
+    AVCMacroblock *currMB = video->currMB;
+    AVCPictureData *currPic = video->currPic;
+    int mbPartIdx, subMbPartIdx;
+    int ref_idx;
+    int offset_MbPart_indx = 0;
+    int16 *mv;
+    uint32 x_pos, y_pos;
+    uint8 *curL, *curCb, *curCr;
+    uint8 *ref_l, *ref_Cb, *ref_Cr;
+    uint8 *predBlock, *predCb, *predCr;
+    int block_x, block_y, offset_x, offset_y, offsetP, offset;
+    int x_position = (video->mb_x << 4);
+    int y_position = (video->mb_y << 4);
+    int MbHeight, MbWidth, mbPartIdx_X, mbPartIdx_Y, offset_indx;
+    int picWidth = currPic->width;
+    int picPitch = currPic->pitch;
+    int picHeight = currPic->height;
+    uint32 tmp_word;
+
+    tmp_word = y_position * picPitch;
+    curL = currPic->Sl + tmp_word + x_position;
+    offset = (tmp_word >> 2) + (x_position >> 1);
+    curCb = currPic->Scb + offset;
+    curCr = currPic->Scr + offset;
+
+    predBlock = curL;
+    predCb = curCb;
+    predCr = curCr;
+
+    GetMotionVectorPredictor(video, 1);
+
+    for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+    {
+        MbHeight = currMB->SubMbPartHeight[mbPartIdx];
+        MbWidth = currMB->SubMbPartWidth[mbPartIdx];
+        mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1);
+        mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) >> 1;
+        ref_idx = currMB->ref_idx_L0[(mbPartIdx_Y << 1) + mbPartIdx_X];
+        offset_indx = 0;
+
+        ref_l = video->RefPicList0[ref_idx]->Sl;
+        ref_Cb = video->RefPicList0[ref_idx]->Scb;
+        ref_Cr = video->RefPicList0[ref_idx]->Scr;
+
+        for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+        {
+            block_x = (mbPartIdx_X << 1) + ((subMbPartIdx + offset_indx) & 1);
+            block_y = (mbPartIdx_Y << 1) + (((subMbPartIdx + offset_indx) >> 1) & 1);
+            mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
+            offset_x = x_position + (block_x << 2);
+            offset_y = y_position + (block_y << 2);
+            x_pos = (offset_x << 2) + *mv++;   /*quarter pel */
+            y_pos = (offset_y << 2) + *mv;   /*quarter pel */
+
+            //offset = offset_y * currPic->width;
+            //offsetC = (offset >> 2) + (offset_x >> 1);
+            offsetP = (block_y << 2) * picPitch + (block_x << 2);
+            eLumaMotionComp(ref_l, picPitch, picHeight, x_pos, y_pos,
+                            /*comp_Sl + offset + offset_x,*/
+                            predBlock + offsetP, picPitch, MbWidth, MbHeight);
+
+            offsetP = (block_y * picWidth) + (block_x << 1);
+            eChromaMotionComp(ref_Cb, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
+                              /*comp_Scb +  offsetC,*/
+                              predCb + offsetP, picPitch >> 1, MbWidth >> 1, MbHeight >> 1);
+            eChromaMotionComp(ref_Cr, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
+                              /*comp_Scr +  offsetC,*/
+                              predCr + offsetP, picPitch >> 1, MbWidth >> 1, MbHeight >> 1);
+
+            offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
+        }
+        offset_MbPart_indx = currMB->MbPartWidth >> 4;
+    }
+
+    return ;
+}
+
+
+/* preform the actual  motion comp here */
+void eLumaMotionComp(uint8 *ref, int picpitch, int picheight,
+                     int x_pos, int y_pos,
+                     uint8 *pred, int pred_pitch,
+                     int blkwidth, int blkheight)
+{
+    (void)(picheight);
+
+    int dx, dy;
+    int temp2[21][21]; /* for intermediate results */
+    uint8 *ref2;
+
+    dx = x_pos & 3;
+    dy = y_pos & 3;
+    x_pos = x_pos >> 2;  /* round it to full-pel resolution */
+    y_pos = y_pos >> 2;
+
+    /* perform actual motion compensation */
+    if (dx == 0 && dy == 0)
+    {  /* fullpel position *//* G */
+
+        ref += y_pos * picpitch + x_pos;
+
+        eFullPelMC(ref, picpitch, pred, pred_pitch, blkwidth, blkheight);
+
+    }   /* other positions */
+    else  if (dy == 0)
+    { /* no vertical interpolation *//* a,b,c*/
+
+        ref += y_pos * picpitch + x_pos;
+
+        eHorzInterp1MC(ref, picpitch, pred, pred_pitch, blkwidth, blkheight, dx);
+    }
+    else if (dx == 0)
+    { /*no horizontal interpolation *//* d,h,n */
+
+        ref += y_pos * picpitch + x_pos;
+
+        eVertInterp1MC(ref, picpitch, pred, pred_pitch, blkwidth, blkheight, dy);
+    }
+    else if (dy == 2)
+    {  /* horizontal cross *//* i, j, k */
+
+        ref += y_pos * picpitch + x_pos - 2; /* move to the left 2 pixels */
+
+        eVertInterp2MC(ref, picpitch, &temp2[0][0], 21, blkwidth + 5, blkheight);
+
+        eHorzInterp2MC(&temp2[0][2], 21, pred, pred_pitch, blkwidth, blkheight, dx);
+    }
+    else if (dx == 2)
+    { /* vertical cross */ /* f,q */
+
+        ref += (y_pos - 2) * picpitch + x_pos; /* move to up 2 lines */
+
+        eHorzInterp3MC(ref, picpitch, &temp2[0][0], 21, blkwidth, blkheight + 5);
+        eVertInterp3MC(&temp2[2][0], 21, pred, pred_pitch, blkwidth, blkheight, dy);
+    }
+    else
+    { /* diagonal *//* e,g,p,r */
+
+        ref2 = ref + (y_pos + (dy / 2)) * picpitch + x_pos;
+
+        ref += (y_pos * picpitch) + x_pos + (dx / 2);
+
+        eDiagonalInterpMC(ref2, ref, picpitch, pred, pred_pitch, blkwidth, blkheight);
+    }
+
+    return ;
+}
+
+void eCreateAlign(uint8 *ref, int picpitch, int y_pos,
+                  uint8 *out, int blkwidth, int blkheight)
+{
+    int i, j;
+    int offset, out_offset;
+    uint32 prev_pix, result, pix1, pix2, pix4;
+
+    ref += y_pos * picpitch;// + x_pos;
+    out_offset = 24 - blkwidth;
+
+    //switch(x_pos&0x3){
+    switch (((uint32)ref)&0x3)
+    {
+        case 1:
+            offset =  picpitch - blkwidth - 3;
+            for (j = 0; j < blkheight; j++)
+            {
+                pix1 = *ref++;
+                pix2 = *((uint16*)ref);
+                ref += 2;
+                result = (pix2 << 8) | pix1;
+
+                for (i = 3; i < blkwidth; i += 4)
+                {
+                    pix4 = *((uint32*)ref);
+                    ref += 4;
+                    prev_pix = (pix4 << 24) & 0xFF000000; /* mask out byte belong to previous word */
+                    result |= prev_pix;
+                    *((uint32*)out) = result;  /* write 4 bytes */
+                    out += 4;
+                    result = pix4 >> 8; /* for the next loop */
+                }
+                ref += offset;
+                out += out_offset;
+            }
+            break;
+        case 2:
+            offset =  picpitch - blkwidth - 2;
+            for (j = 0; j < blkheight; j++)
+            {
+                result = *((uint16*)ref);
+                ref += 2;
+                for (i = 2; i < blkwidth; i += 4)
+                {
+                    pix4 = *((uint32*)ref);
+                    ref += 4;
+                    prev_pix = (pix4 << 16) & 0xFFFF0000; /* mask out byte belong to previous word */
+                    result |= prev_pix;
+                    *((uint32*)out) = result;  /* write 4 bytes */
+                    out += 4;
+                    result = pix4 >> 16; /* for the next loop */
+                }
+                ref += offset;
+                out += out_offset;
+            }
+            break;
+        case 3:
+            offset =  picpitch - blkwidth - 1;
+            for (j = 0; j < blkheight; j++)
+            {
+                result = *ref++;
+                for (i = 1; i < blkwidth; i += 4)
+                {
+                    pix4 = *((uint32*)ref);
+                    ref += 4;
+                    prev_pix = (pix4 << 8) & 0xFFFFFF00; /* mask out byte belong to previous word */
+                    result |= prev_pix;
+                    *((uint32*)out) = result;  /* write 4 bytes */
+                    out += 4;
+                    result = pix4 >> 24; /* for the next loop */
+                }
+                ref += offset;
+                out += out_offset;
+            }
+            break;
+    }
+}
+
+void eHorzInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+                    int blkwidth, int blkheight, int dx)
+{
+    uint8 *p_ref;
+    uint32 *p_cur;
+    uint32 tmp, pkres;
+    int result, curr_offset, ref_offset;
+    int j;
+    int32 r0, r1, r2, r3, r4, r5;
+    int32 r13, r6;
+
+    p_cur = (uint32*)out; /* assume it's word aligned */
+    curr_offset = (outpitch - blkwidth) >> 2;
+    p_ref = in;
+    ref_offset = inpitch - blkwidth;
+
+    if (dx&1)
+    {
+        dx = ((dx >> 1) ? -3 : -4); /* use in 3/4 pel */
+        p_ref -= 2;
+        r13 = 0;
+        for (j = blkheight; j > 0; j--)
+        {
+            tmp = (uint32)(p_ref + blkwidth);
+            r0 = p_ref[0];
+            r1 = p_ref[2];
+            r0 |= (r1 << 16);           /* 0,c,0,a */
+            r1 = p_ref[1];
+            r2 = p_ref[3];
+            r1 |= (r2 << 16);           /* 0,d,0,b */
+            while ((uint32)p_ref < tmp)
+            {
+                r2 = *(p_ref += 4); /* move pointer to e */
+                r3 = p_ref[2];
+                r2 |= (r3 << 16);           /* 0,g,0,e */
+                r3 = p_ref[1];
+                r4 = p_ref[3];
+                r3 |= (r4 << 16);           /* 0,h,0,f */
+
+                r4 = r0 + r3;       /* c+h, a+f */
+                r5 = r0 + r1;   /* c+d, a+b */
+                r6 = r2 + r3;   /* g+h, e+f */
+                r5 >>= 16;
+                r5 |= (r6 << 16);   /* e+f, c+d */
+                r4 += r5 * 20;      /* c+20*e+20*f+h, a+20*c+20*d+f */
+                r4 += 0x100010; /* +16, +16 */
+                r5 = r1 + r2;       /* d+g, b+e */
+                r4 -= r5 * 5;       /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+                r4 >>= 5;
+                r13 |= r4;      /* check clipping */
+
+                r5 = p_ref[dx+2];
+                r6 = p_ref[dx+4];
+                r5 |= (r6 << 16);
+                r4 += r5;
+                r4 += 0x10001;
+                r4 = (r4 >> 1) & 0xFF00FF;
+
+                r5 = p_ref[4];  /* i */
+                r6 = (r5 << 16);
+                r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+                r5 += r1;       /* d+i, b+g */ /* r5 not free */
+                r1 >>= 16;
+                r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+                r1 += r2;       /* f+g, d+e */
+                r5 += 20 * r1;  /* d+20f+20g+i, b+20d+20e+g */
+                r0 >>= 16;
+                r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+                r0 += r3;       /* e+h, c+f */
+                r5 += 0x100010; /* 16,16 */
+                r5 -= r0 * 5;       /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+                r5 >>= 5;
+                r13 |= r5;      /* check clipping */
+
+                r0 = p_ref[dx+3];
+                r1 = p_ref[dx+5];
+                r0 |= (r1 << 16);
+                r5 += r0;
+                r5 += 0x10001;
+                r5 = (r5 >> 1) & 0xFF00FF;
+
+                r4 |= (r5 << 8);    /* pack them together */
+                *p_cur++ = r4;
+                r1 = r3;
+                r0 = r2;
+            }
+            p_cur += curr_offset; /* move to the next line */
+            p_ref += ref_offset;  /*    ref_offset = inpitch-blkwidth; */
+
+            if (r13&0xFF000700) /* need clipping */
+            {
+                /* move back to the beginning of the line */
+                p_ref -= (ref_offset + blkwidth);   /* input */
+                p_cur -= (outpitch >> 2);
+
+                tmp = (uint32)(p_ref + blkwidth);
+                for (; (uint32)p_ref < tmp;)
+                {
+
+                    r0 = *p_ref++;
+                    r1 = *p_ref++;
+                    r2 = *p_ref++;
+                    r3 = *p_ref++;
+                    r4 = *p_ref++;
+                    /* first pixel */
+                    r5 = *p_ref++;
+                    result = (r0 + r5);
+                    r0 = (r1 + r4);
+                    result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                    r0 = (r2 + r3);
+                    result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    /* 3/4 pel,  no need to clip */
+                    result = (result + p_ref[dx] + 1);
+                    pkres = (result >> 1) ;
+                    /* second pixel */
+                    r0 = *p_ref++;
+                    result = (r1 + r0);
+                    r1 = (r2 + r5);
+                    result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                    r1 = (r3 + r4);
+                    result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    /* 3/4 pel,  no need to clip */
+                    result = (result + p_ref[dx] + 1);
+                    result = (result >> 1);
+                    pkres  |= (result << 8);
+                    /* third pixel */
+                    r1 = *p_ref++;
+                    result = (r2 + r1);
+                    r2 = (r3 + r0);
+                    result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                    r2 = (r4 + r5);
+                    result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    /* 3/4 pel,  no need to clip */
+                    result = (result + p_ref[dx] + 1);
+                    result = (result >> 1);
+                    pkres  |= (result << 16);
+                    /* fourth pixel */
+                    r2 = *p_ref++;
+                    result = (r3 + r2);
+                    r3 = (r4 + r1);
+                    result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                    r3 = (r5 + r0);
+                    result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    /* 3/4 pel,  no need to clip */
+                    result = (result + p_ref[dx] + 1);
+                    result = (result >> 1);
+                    pkres  |= (result << 24);
+                    *p_cur++ = pkres; /* write 4 pixels */
+                    p_ref -= 5;  /* offset back to the middle of filter */
+                }
+                p_cur += curr_offset;  /* move to the next line */
+                p_ref += ref_offset;    /* move to the next line */
+            }
+        }
+    }
+    else
+    {
+        p_ref -= 2;
+        r13 = 0;
+        for (j = blkheight; j > 0; j--)
+        {
+            tmp = (uint32)(p_ref + blkwidth);
+            r0 = p_ref[0];
+            r1 = p_ref[2];
+            r0 |= (r1 << 16);           /* 0,c,0,a */
+            r1 = p_ref[1];
+            r2 = p_ref[3];
+            r1 |= (r2 << 16);           /* 0,d,0,b */
+            while ((uint32)p_ref < tmp)
+            {
+                r2 = *(p_ref += 4); /* move pointer to e */
+                r3 = p_ref[2];
+                r2 |= (r3 << 16);           /* 0,g,0,e */
+                r3 = p_ref[1];
+                r4 = p_ref[3];
+                r3 |= (r4 << 16);           /* 0,h,0,f */
+
+                r4 = r0 + r3;       /* c+h, a+f */
+                r5 = r0 + r1;   /* c+d, a+b */
+                r6 = r2 + r3;   /* g+h, e+f */
+                r5 >>= 16;
+                r5 |= (r6 << 16);   /* e+f, c+d */
+                r4 += r5 * 20;      /* c+20*e+20*f+h, a+20*c+20*d+f */
+                r4 += 0x100010; /* +16, +16 */
+                r5 = r1 + r2;       /* d+g, b+e */
+                r4 -= r5 * 5;       /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+                r4 >>= 5;
+                r13 |= r4;      /* check clipping */
+                r4 &= 0xFF00FF; /* mask */
+
+                r5 = p_ref[4];  /* i */
+                r6 = (r5 << 16);
+                r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+                r5 += r1;       /* d+i, b+g */ /* r5 not free */
+                r1 >>= 16;
+                r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+                r1 += r2;       /* f+g, d+e */
+                r5 += 20 * r1;  /* d+20f+20g+i, b+20d+20e+g */
+                r0 >>= 16;
+                r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+                r0 += r3;       /* e+h, c+f */
+                r5 += 0x100010; /* 16,16 */
+                r5 -= r0 * 5;       /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+                r5 >>= 5;
+                r13 |= r5;      /* check clipping */
+                r5 &= 0xFF00FF; /* mask */
+
+                r4 |= (r5 << 8);    /* pack them together */
+                *p_cur++ = r4;
+                r1 = r3;
+                r0 = r2;
+            }
+            p_cur += curr_offset; /* move to the next line */
+            p_ref += ref_offset;  /*    ref_offset = inpitch-blkwidth; */
+
+            if (r13&0xFF000700) /* need clipping */
+            {
+                /* move back to the beginning of the line */
+                p_ref -= (ref_offset + blkwidth);   /* input */
+                p_cur -= (outpitch >> 2);
+
+                tmp = (uint32)(p_ref + blkwidth);
+                for (; (uint32)p_ref < tmp;)
+                {
+
+                    r0 = *p_ref++;
+                    r1 = *p_ref++;
+                    r2 = *p_ref++;
+                    r3 = *p_ref++;
+                    r4 = *p_ref++;
+                    /* first pixel */
+                    r5 = *p_ref++;
+                    result = (r0 + r5);
+                    r0 = (r1 + r4);
+                    result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                    r0 = (r2 + r3);
+                    result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    pkres  = result;
+                    /* second pixel */
+                    r0 = *p_ref++;
+                    result = (r1 + r0);
+                    r1 = (r2 + r5);
+                    result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                    r1 = (r3 + r4);
+                    result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    pkres  |= (result << 8);
+                    /* third pixel */
+                    r1 = *p_ref++;
+                    result = (r2 + r1);
+                    r2 = (r3 + r0);
+                    result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                    r2 = (r4 + r5);
+                    result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    pkres  |= (result << 16);
+                    /* fourth pixel */
+                    r2 = *p_ref++;
+                    result = (r3 + r2);
+                    r3 = (r4 + r1);
+                    result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                    r3 = (r5 + r0);
+                    result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    pkres  |= (result << 24);
+                    *p_cur++ = pkres;   /* write 4 pixels */
+                    p_ref -= 5;
+                }
+                p_cur += curr_offset; /* move to the next line */
+                p_ref += ref_offset;
+            }
+        }
+    }
+
+    return ;
+}
+
+void eHorzInterp2MC(int *in, int inpitch, uint8 *out, int outpitch,
+                    int blkwidth, int blkheight, int dx)
+{
+    int *p_ref;
+    uint32 *p_cur;
+    uint32 tmp, pkres;
+    int result, result2, curr_offset, ref_offset;
+    int j, r0, r1, r2, r3, r4, r5;
+
+    p_cur = (uint32*)out; /* assume it's word aligned */
+    curr_offset = (outpitch - blkwidth) >> 2;
+    p_ref = in;
+    ref_offset = inpitch - blkwidth;
+
+    if (dx&1)
+    {
+        dx = ((dx >> 1) ? -3 : -4); /* use in 3/4 pel */
+
+        for (j = blkheight; j > 0 ; j--)
+        {
+            tmp = (uint32)(p_ref + blkwidth);
+            for (; (uint32)p_ref < tmp;)
+            {
+
+                r0 = p_ref[-2];
+                r1 = p_ref[-1];
+                r2 = *p_ref++;
+                r3 = *p_ref++;
+                r4 = *p_ref++;
+                /* first pixel */
+                r5 = *p_ref++;
+                result = (r0 + r5);
+                r0 = (r1 + r4);
+                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                r0 = (r2 + r3);
+                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                result2 = ((p_ref[dx] + 16) >> 5);
+                CLIP_RESULT(result2)
+                /* 3/4 pel,  no need to clip */
+                result = (result + result2 + 1);
+                pkres = (result >> 1);
+                /* second pixel */
+                r0 = *p_ref++;
+                result = (r1 + r0);
+                r1 = (r2 + r5);
+                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                r1 = (r3 + r4);
+                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                result2 = ((p_ref[dx] + 16) >> 5);
+                CLIP_RESULT(result2)
+                /* 3/4 pel,  no need to clip */
+                result = (result + result2 + 1);
+                result = (result >> 1);
+                pkres  |= (result << 8);
+                /* third pixel */
+                r1 = *p_ref++;
+                result = (r2 + r1);
+                r2 = (r3 + r0);
+                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                r2 = (r4 + r5);
+                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                result2 = ((p_ref[dx] + 16) >> 5);
+                CLIP_RESULT(result2)
+                /* 3/4 pel,  no need to clip */
+                result = (result + result2 + 1);
+                result = (result >> 1);
+                pkres  |= (result << 16);
+                /* fourth pixel */
+                r2 = *p_ref++;
+                result = (r3 + r2);
+                r3 = (r4 + r1);
+                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                r3 = (r5 + r0);
+                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                result2 = ((p_ref[dx] + 16) >> 5);
+                CLIP_RESULT(result2)
+                /* 3/4 pel,  no need to clip */
+                result = (result + result2 + 1);
+                result = (result >> 1);
+                pkres  |= (result << 24);
+                *p_cur++ = pkres; /* write 4 pixels */
+                p_ref -= 3;  /* offset back to the middle of filter */
+            }
+            p_cur += curr_offset;  /* move to the next line */
+            p_ref += ref_offset;    /* move to the next line */
+        }
+    }
+    else
+    {
+        for (j = blkheight; j > 0 ; j--)
+        {
+            tmp = (uint32)(p_ref + blkwidth);
+            for (; (uint32)p_ref < tmp;)
+            {
+
+                r0 = p_ref[-2];
+                r1 = p_ref[-1];
+                r2 = *p_ref++;
+                r3 = *p_ref++;
+                r4 = *p_ref++;
+                /* first pixel */
+                r5 = *p_ref++;
+                result = (r0 + r5);
+                r0 = (r1 + r4);
+                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                r0 = (r2 + r3);
+                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                pkres  = result;
+                /* second pixel */
+                r0 = *p_ref++;
+                result = (r1 + r0);
+                r1 = (r2 + r5);
+                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                r1 = (r3 + r4);
+                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                pkres  |= (result << 8);
+                /* third pixel */
+                r1 = *p_ref++;
+                result = (r2 + r1);
+                r2 = (r3 + r0);
+                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                r2 = (r4 + r5);
+                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                pkres  |= (result << 16);
+                /* fourth pixel */
+                r2 = *p_ref++;
+                result = (r3 + r2);
+                r3 = (r4 + r1);
+                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                r3 = (r5 + r0);
+                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                pkres  |= (result << 24);
+                *p_cur++ = pkres; /* write 4 pixels */
+                p_ref -= 3;  /* offset back to the middle of filter */
+            }
+            p_cur += curr_offset;  /* move to the next line */
+            p_ref += ref_offset;    /* move to the next line */
+        }
+    }
+
+    return ;
+}
+
+void eHorzInterp3MC(uint8 *in, int inpitch, int *out, int outpitch,
+                    int blkwidth, int blkheight)
+{
+    uint8 *p_ref;
+    int   *p_cur;
+    uint32 tmp;
+    int result, curr_offset, ref_offset;
+    int j, r0, r1, r2, r3, r4, r5;
+
+    p_cur = out;
+    curr_offset = (outpitch - blkwidth);
+    p_ref = in;
+    ref_offset = inpitch - blkwidth;
+
+    for (j = blkheight; j > 0 ; j--)
+    {
+        tmp = (uint32)(p_ref + blkwidth);
+        for (; (uint32)p_ref < tmp;)
+        {
+
+            r0 = p_ref[-2];
+            r1 = p_ref[-1];
+            r2 = *p_ref++;
+            r3 = *p_ref++;
+            r4 = *p_ref++;
+            /* first pixel */
+            r5 = *p_ref++;
+            result = (r0 + r5);
+            r0 = (r1 + r4);
+            result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+            r0 = (r2 + r3);
+            result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+            *p_cur++ = result;
+            /* second pixel */
+            r0 = *p_ref++;
+            result = (r1 + r0);
+            r1 = (r2 + r5);
+            result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+            r1 = (r3 + r4);
+            result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+            *p_cur++ = result;
+            /* third pixel */
+            r1 = *p_ref++;
+            result = (r2 + r1);
+            r2 = (r3 + r0);
+            result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+            r2 = (r4 + r5);
+            result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+            *p_cur++ = result;
+            /* fourth pixel */
+            r2 = *p_ref++;
+            result = (r3 + r2);
+            r3 = (r4 + r1);
+            result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+            r3 = (r5 + r0);
+            result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+            *p_cur++ = result;
+            p_ref -= 3; /* move back to the middle of the filter */
+        }
+        p_cur += curr_offset; /* move to the next line */
+        p_ref += ref_offset;
+    }
+
+    return ;
+}
+void eVertInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+                    int blkwidth, int blkheight, int dy)
+{
+    uint8 *p_cur, *p_ref;
+    uint32 tmp;
+    int result, curr_offset, ref_offset;
+    int j, i;
+    int32 r0, r1, r2, r3, r4, r5, r6, r7, r8, r13;
+    uint8  tmp_in[24][24];
+
+    /* not word-aligned */
+    if (((uint32)in)&0x3)
+    {
+        eCreateAlign(in, inpitch, -2, &tmp_in[0][0], blkwidth, blkheight + 5);
+        in = &tmp_in[2][0];
+        inpitch = 24;
+    }
+    p_cur = out;
+    curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+    ref_offset = blkheight * inpitch; /* for limit */
+
+    curr_offset += 3;
+
+    if (dy&1)
+    {
+        dy = (dy >> 1) ? 0 : -inpitch;
+
+        for (j = 0; j < blkwidth; j += 4, in += 4)
+        {
+            r13 = 0;
+            p_ref = in;
+            p_cur -= outpitch;  /* compensate for the first offset */
+            tmp = (uint32)(p_ref + ref_offset); /* limit */
+            while ((uint32)p_ref < tmp)  /* the loop un-rolled  */
+            {
+                r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+                p_ref += inpitch;
+                r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+                r0 &= 0xFF00FF;
+
+                r1 = *((uint32*)(p_ref + (inpitch << 1)));  /* r1, r7, ref[3] */
+                r7 = (r1 >> 8) & 0xFF00FF;
+                r1 &= 0xFF00FF;
+
+                r0 += r1;
+                r6 += r7;
+
+                r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+                r8 = (r2 >> 8) & 0xFF00FF;
+                r2 &= 0xFF00FF;
+
+                r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+                r7 = (r1 >> 8) & 0xFF00FF;
+                r1 &= 0xFF00FF;
+                r1 += r2;
+
+                r7 += r8;
+
+                r0 += 20 * r1;
+                r6 += 20 * r7;
+                r0 += 0x100010;
+                r6 += 0x100010;
+
+                r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+                r8 = (r2 >> 8) & 0xFF00FF;
+                r2 &= 0xFF00FF;
+
+                r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+                r7 = (r1 >> 8) & 0xFF00FF;
+                r1 &= 0xFF00FF;
+                r1 += r2;
+
+                r7 += r8;
+
+                r0 -= 5 * r1;
+                r6 -= 5 * r7;
+
+                r0 >>= 5;
+                r6 >>= 5;
+                /* clip */
+                r13 |= r6;
+                r13 |= r0;
+                //CLIPPACK(r6,result)
+
+                r1 = *((uint32*)(p_ref + dy));
+                r2 = (r1 >> 8) & 0xFF00FF;
+                r1 &= 0xFF00FF;
+                r0 += r1;
+                r6 += r2;
+                r0 += 0x10001;
+                r6 += 0x10001;
+                r0 = (r0 >> 1) & 0xFF00FF;
+                r6 = (r6 >> 1) & 0xFF00FF;
+
+                r0 |= (r6 << 8);  /* pack it back */
+                *((uint32*)(p_cur += outpitch)) = r0;
+            }
+            p_cur += curr_offset; /* offset to the next pixel */
+            if (r13 & 0xFF000700) /* this column need clipping */
+            {
+                p_cur -= 4;
+                for (i = 0; i < 4; i++)
+                {
+                    p_ref = in + i;
+                    p_cur -= outpitch;  /* compensate for the first offset */
+
+                    tmp = (uint32)(p_ref + ref_offset); /* limit */
+                    while ((uint32)p_ref < tmp)
+                    {                           /* loop un-rolled */
+                        r0 = *(p_ref - (inpitch << 1));
+                        r1 = *(p_ref - inpitch);
+                        r2 = *p_ref;
+                        r3 = *(p_ref += inpitch);  /* modify pointer before loading */
+                        r4 = *(p_ref += inpitch);
+                        /* first pixel */
+                        r5 = *(p_ref += inpitch);
+                        result = (r0 + r5);
+                        r0 = (r1 + r4);
+                        result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                        r0 = (r2 + r3);
+                        result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                        result = (result + 16) >> 5;
+                        CLIP_RESULT(result)
+                        /* 3/4 pel,  no need to clip */
+                        result = (result + p_ref[dy-(inpitch<<1)] + 1);
+                        result = (result >> 1);
+                        *(p_cur += outpitch) = result;
+                        /* second pixel */
+                        r0 = *(p_ref += inpitch);
+                        result = (r1 + r0);
+                        r1 = (r2 + r5);
+                        result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                        r1 = (r3 + r4);
+                        result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                        result = (result + 16) >> 5;
+                        CLIP_RESULT(result)
+                        /* 3/4 pel,  no need to clip */
+                        result = (result + p_ref[dy-(inpitch<<1)] + 1);
+                        result = (result >> 1);
+                        *(p_cur += outpitch) = result;
+                        /* third pixel */
+                        r1 = *(p_ref += inpitch);
+                        result = (r2 + r1);
+                        r2 = (r3 + r0);
+                        result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                        r2 = (r4 + r5);
+                        result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                        result = (result + 16) >> 5;
+                        CLIP_RESULT(result)
+                        /* 3/4 pel,  no need to clip */
+                        result = (result + p_ref[dy-(inpitch<<1)] + 1);
+                        result = (result >> 1);
+                        *(p_cur += outpitch) = result;
+                        /* fourth pixel */
+                        r2 = *(p_ref += inpitch);
+                        result = (r3 + r2);
+                        r3 = (r4 + r1);
+                        result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                        r3 = (r5 + r0);
+                        result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                        result = (result + 16) >> 5;
+                        CLIP_RESULT(result)
+                        /* 3/4 pel,  no need to clip */
+                        result = (result + p_ref[dy-(inpitch<<1)] + 1);
+                        result = (result >> 1);
+                        *(p_cur += outpitch) = result;
+                        p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
+                    }
+                    p_cur += (curr_offset - 3);
+                }
+            }
+        }
+    }
+    else
+    {
+        for (j = 0; j < blkwidth; j += 4, in += 4)
+        {
+            r13 = 0;
+            p_ref = in;
+            p_cur -= outpitch;  /* compensate for the first offset */
+            tmp = (uint32)(p_ref + ref_offset); /* limit */
+            while ((uint32)p_ref < tmp)  /* the loop un-rolled  */
+            {
+                r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+                p_ref += inpitch;
+                r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+                r0 &= 0xFF00FF;
+
+                r1 = *((uint32*)(p_ref + (inpitch << 1)));  /* r1, r7, ref[3] */
+                r7 = (r1 >> 8) & 0xFF00FF;
+                r1 &= 0xFF00FF;
+
+                r0 += r1;
+                r6 += r7;
+
+                r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+                r8 = (r2 >> 8) & 0xFF00FF;
+                r2 &= 0xFF00FF;
+
+                r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+                r7 = (r1 >> 8) & 0xFF00FF;
+                r1 &= 0xFF00FF;
+                r1 += r2;
+
+                r7 += r8;
+
+                r0 += 20 * r1;
+                r6 += 20 * r7;
+                r0 += 0x100010;
+                r6 += 0x100010;
+
+                r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+                r8 = (r2 >> 8) & 0xFF00FF;
+                r2 &= 0xFF00FF;
+
+                r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+                r7 = (r1 >> 8) & 0xFF00FF;
+                r1 &= 0xFF00FF;
+                r1 += r2;
+
+                r7 += r8;
+
+                r0 -= 5 * r1;
+                r6 -= 5 * r7;
+
+                r0 >>= 5;
+                r6 >>= 5;
+                /* clip */
+                r13 |= r6;
+                r13 |= r0;
+                //CLIPPACK(r6,result)
+                r0 &= 0xFF00FF;
+                r6 &= 0xFF00FF;
+                r0 |= (r6 << 8);  /* pack it back */
+                *((uint32*)(p_cur += outpitch)) = r0;
+            }
+            p_cur += curr_offset; /* offset to the next pixel */
+            if (r13 & 0xFF000700) /* this column need clipping */
+            {
+                p_cur -= 4;
+                for (i = 0; i < 4; i++)
+                {
+                    p_ref = in + i;
+                    p_cur -= outpitch;  /* compensate for the first offset */
+                    tmp = (uint32)(p_ref + ref_offset); /* limit */
+                    while ((uint32)p_ref < tmp)
+                    {                           /* loop un-rolled */
+                        r0 = *(p_ref - (inpitch << 1));
+                        r1 = *(p_ref - inpitch);
+                        r2 = *p_ref;
+                        r3 = *(p_ref += inpitch);  /* modify pointer before loading */
+                        r4 = *(p_ref += inpitch);
+                        /* first pixel */
+                        r5 = *(p_ref += inpitch);
+                        result = (r0 + r5);
+                        r0 = (r1 + r4);
+                        result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                        r0 = (r2 + r3);
+                        result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                        result = (result + 16) >> 5;
+                        CLIP_RESULT(result)
+                        *(p_cur += outpitch) = result;
+                        /* second pixel */
+                        r0 = *(p_ref += inpitch);
+                        result = (r1 + r0);
+                        r1 = (r2 + r5);
+                        result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                        r1 = (r3 + r4);
+                        result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                        result = (result + 16) >> 5;
+                        CLIP_RESULT(result)
+                        *(p_cur += outpitch) = result;
+                        /* third pixel */
+                        r1 = *(p_ref += inpitch);
+                        result = (r2 + r1);
+                        r2 = (r3 + r0);
+                        result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                        r2 = (r4 + r5);
+                        result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                        result = (result + 16) >> 5;
+                        CLIP_RESULT(result)
+                        *(p_cur += outpitch) = result;
+                        /* fourth pixel */
+                        r2 = *(p_ref += inpitch);
+                        result = (r3 + r2);
+                        r3 = (r4 + r1);
+                        result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                        r3 = (r5 + r0);
+                        result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                        result = (result + 16) >> 5;
+                        CLIP_RESULT(result)
+                        *(p_cur += outpitch) = result;
+                        p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
+                    }
+                    p_cur += (curr_offset - 3);
+                }
+            }
+        }
+    }
+
+    return ;
+}
+
+void eVertInterp2MC(uint8 *in, int inpitch, int *out, int outpitch,
+                    int blkwidth, int blkheight)
+{
+    int *p_cur;
+    uint8 *p_ref;
+    uint32 tmp;
+    int result, curr_offset, ref_offset;
+    int j, r0, r1, r2, r3, r4, r5;
+
+    p_cur = out;
+    curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+    ref_offset = blkheight * inpitch; /* for limit */
+
+    for (j = 0; j < blkwidth; j++)
+    {
+        p_cur -= outpitch; /* compensate for the first offset */
+        p_ref = in++;
+
+        tmp = (uint32)(p_ref + ref_offset); /* limit */
+        while ((uint32)p_ref < tmp)
+        {                           /* loop un-rolled */
+            r0 = *(p_ref - (inpitch << 1));
+            r1 = *(p_ref - inpitch);
+            r2 = *p_ref;
+            r3 = *(p_ref += inpitch);  /* modify pointer before loading */
+            r4 = *(p_ref += inpitch);
+            /* first pixel */
+            r5 = *(p_ref += inpitch);
+            result = (r0 + r5);
+            r0 = (r1 + r4);
+            result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+            r0 = (r2 + r3);
+            result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+            *(p_cur += outpitch) = result;
+            /* second pixel */
+            r0 = *(p_ref += inpitch);
+            result = (r1 + r0);
+            r1 = (r2 + r5);
+            result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+            r1 = (r3 + r4);
+            result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+            *(p_cur += outpitch) = result;
+            /* third pixel */
+            r1 = *(p_ref += inpitch);
+            result = (r2 + r1);
+            r2 = (r3 + r0);
+            result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+            r2 = (r4 + r5);
+            result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+            *(p_cur += outpitch) = result;
+            /* fourth pixel */
+            r2 = *(p_ref += inpitch);
+            result = (r3 + r2);
+            r3 = (r4 + r1);
+            result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+            r3 = (r5 + r0);
+            result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+            *(p_cur += outpitch) = result;
+            p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
+        }
+        p_cur += curr_offset;
+    }
+
+    return ;
+}
+
+void eVertInterp3MC(int *in, int inpitch, uint8 *out, int outpitch,
+                    int blkwidth, int blkheight, int dy)
+{
+    uint8 *p_cur;
+    int *p_ref;
+    uint32 tmp;
+    int result, result2, curr_offset, ref_offset;
+    int j, r0, r1, r2, r3, r4, r5;
+
+    p_cur = out;
+    curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+    ref_offset = blkheight * inpitch; /* for limit */
+
+    if (dy&1)
+    {
+        dy = (dy >> 1) ? -(inpitch << 1) : -(inpitch << 1) - inpitch;
+
+        for (j = 0; j < blkwidth; j++)
+        {
+            p_cur -= outpitch; /* compensate for the first offset */
+            p_ref = in++;
+
+            tmp = (uint32)(p_ref + ref_offset); /* limit */
+            while ((uint32)p_ref < tmp)
+            {                           /* loop un-rolled */
+                r0 = *(p_ref - (inpitch << 1));
+                r1 = *(p_ref - inpitch);
+                r2 = *p_ref;
+                r3 = *(p_ref += inpitch);  /* modify pointer before loading */
+                r4 = *(p_ref += inpitch);
+                /* first pixel */
+                r5 = *(p_ref += inpitch);
+                result = (r0 + r5);
+                r0 = (r1 + r4);
+                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                r0 = (r2 + r3);
+                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                result2 = ((p_ref[dy] + 16) >> 5);
+                CLIP_RESULT(result2)
+                /* 3/4 pel,  no need to clip */
+                result = (result + result2 + 1);
+                result = (result >> 1);
+                *(p_cur += outpitch) = result;
+                /* second pixel */
+                r0 = *(p_ref += inpitch);
+                result = (r1 + r0);
+                r1 = (r2 + r5);
+                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                r1 = (r3 + r4);
+                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                result2 = ((p_ref[dy] + 16) >> 5);
+                CLIP_RESULT(result2)
+                /* 3/4 pel,  no need to clip */
+                result = (result + result2 + 1);
+                result = (result >> 1);
+                *(p_cur += outpitch) = result;
+                /* third pixel */
+                r1 = *(p_ref += inpitch);
+                result = (r2 + r1);
+                r2 = (r3 + r0);
+                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                r2 = (r4 + r5);
+                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                result2 = ((p_ref[dy] + 16) >> 5);
+                CLIP_RESULT(result2)
+                /* 3/4 pel,  no need to clip */
+                result = (result + result2 + 1);
+                result = (result >> 1);
+                *(p_cur += outpitch) = result;
+                /* fourth pixel */
+                r2 = *(p_ref += inpitch);
+                result = (r3 + r2);
+                r3 = (r4 + r1);
+                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                r3 = (r5 + r0);
+                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                result2 = ((p_ref[dy] + 16) >> 5);
+                CLIP_RESULT(result2)
+                /* 3/4 pel,  no need to clip */
+                result = (result + result2 + 1);
+                result = (result >> 1);
+                *(p_cur += outpitch) = result;
+                p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
+            }
+            p_cur += curr_offset;
+        }
+    }
+    else
+    {
+        for (j = 0; j < blkwidth; j++)
+        {
+            p_cur -= outpitch; /* compensate for the first offset */
+            p_ref = in++;
+
+            tmp = (uint32)(p_ref + ref_offset); /* limit */
+            while ((uint32)p_ref < tmp)
+            {                           /* loop un-rolled */
+                r0 = *(p_ref - (inpitch << 1));
+                r1 = *(p_ref - inpitch);
+                r2 = *p_ref;
+                r3 = *(p_ref += inpitch);  /* modify pointer before loading */
+                r4 = *(p_ref += inpitch);
+                /* first pixel */
+                r5 = *(p_ref += inpitch);
+                result = (r0 + r5);
+                r0 = (r1 + r4);
+                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                r0 = (r2 + r3);
+                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                *(p_cur += outpitch) = result;
+                /* second pixel */
+                r0 = *(p_ref += inpitch);
+                result = (r1 + r0);
+                r1 = (r2 + r5);
+                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                r1 = (r3 + r4);
+                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                *(p_cur += outpitch) = result;
+                /* third pixel */
+                r1 = *(p_ref += inpitch);
+                result = (r2 + r1);
+                r2 = (r3 + r0);
+                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                r2 = (r4 + r5);
+                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                *(p_cur += outpitch) = result;
+                /* fourth pixel */
+                r2 = *(p_ref += inpitch);
+                result = (r3 + r2);
+                r3 = (r4 + r1);
+                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                r3 = (r5 + r0);
+                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                result = (result + 512) >> 10;
+                CLIP_RESULT(result)
+                *(p_cur += outpitch) = result;
+                p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
+            }
+            p_cur += curr_offset;
+        }
+    }
+
+    return ;
+}
+
+void eDiagonalInterpMC(uint8 *in1, uint8 *in2, int inpitch,
+                       uint8 *out, int outpitch,
+                       int blkwidth, int blkheight)
+{
+    int j, i;
+    int result;
+    uint8 *p_cur, *p_ref, *p_tmp8;
+    int curr_offset, ref_offset;
+    uint8 tmp_res[24][24], tmp_in[24][24];
+    uint32 *p_tmp;
+    uint32 tmp, pkres, tmp_result;
+    int32 r0, r1, r2, r3, r4, r5;
+    int32 r6, r7, r8, r9, r10, r13;
+
+    ref_offset = inpitch - blkwidth;
+    p_ref = in1 - 2;
+    /* perform horizontal interpolation */
+    /* not word-aligned */
+    /* It is faster to read 1 byte at time to avoid calling CreateAlign */
+    /*  if(((uint32)p_ref)&0x3)
+        {
+            CreateAlign(p_ref,inpitch,0,&tmp_in[0][0],blkwidth+8,blkheight);
+            p_ref = &tmp_in[0][0];
+            ref_offset = 24-blkwidth;
+        }*/
+
+    p_tmp = (uint32*) & (tmp_res[0][0]);
+    for (j = blkheight; j > 0; j--)
+    {
+        r13 = 0;
+        tmp = (uint32)(p_ref + blkwidth);
+
+        //r0 = *((uint32*)p_ref);   /* d,c,b,a */
+        //r1 = (r0>>8)&0xFF00FF;    /* 0,d,0,b */
+        //r0 &= 0xFF00FF;           /* 0,c,0,a */
+        /* It is faster to read 1 byte at a time */
+        r0 = p_ref[0];
+        r1 = p_ref[2];
+        r0 |= (r1 << 16);           /* 0,c,0,a */
+        r1 = p_ref[1];
+        r2 = p_ref[3];
+        r1 |= (r2 << 16);           /* 0,d,0,b */
+
+        while ((uint32)p_ref < tmp)
+        {
+            //r2 = *((uint32*)(p_ref+=4));/* h,g,f,e */
+            //r3 = (r2>>8)&0xFF00FF;  /* 0,h,0,f */
+            //r2 &= 0xFF00FF;           /* 0,g,0,e */
+            /* It is faster to read 1 byte at a time */
+            r2 = *(p_ref += 4);
+            r3 = p_ref[2];
+            r2 |= (r3 << 16);           /* 0,g,0,e */
+            r3 = p_ref[1];
+            r4 = p_ref[3];
+            r3 |= (r4 << 16);           /* 0,h,0,f */
+
+            r4 = r0 + r3;       /* c+h, a+f */
+            r5 = r0 + r1;   /* c+d, a+b */
+            r6 = r2 + r3;   /* g+h, e+f */
+            r5 >>= 16;
+            r5 |= (r6 << 16);   /* e+f, c+d */
+            r4 += r5 * 20;      /* c+20*e+20*f+h, a+20*c+20*d+f */
+            r4 += 0x100010; /* +16, +16 */
+            r5 = r1 + r2;       /* d+g, b+e */
+            r4 -= r5 * 5;       /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+            r4 >>= 5;
+            r13 |= r4;      /* check clipping */
+            r4 &= 0xFF00FF; /* mask */
+
+            r5 = p_ref[4];  /* i */
+            r6 = (r5 << 16);
+            r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+            r5 += r1;       /* d+i, b+g */ /* r5 not free */
+            r1 >>= 16;
+            r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+            r1 += r2;       /* f+g, d+e */
+            r5 += 20 * r1;  /* d+20f+20g+i, b+20d+20e+g */
+            r0 >>= 16;
+            r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+            r0 += r3;       /* e+h, c+f */
+            r5 += 0x100010; /* 16,16 */
+            r5 -= r0 * 5;       /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+            r5 >>= 5;
+            r13 |= r5;      /* check clipping */
+            r5 &= 0xFF00FF; /* mask */
+
+            r4 |= (r5 << 8);    /* pack them together */
+            *p_tmp++ = r4;
+            r1 = r3;
+            r0 = r2;
+        }
+        p_tmp += ((24 - blkwidth) >> 2); /* move to the next line */
+        p_ref += ref_offset;  /*    ref_offset = inpitch-blkwidth; */
+
+        if (r13&0xFF000700) /* need clipping */
+        {
+            /* move back to the beginning of the line */
+            p_ref -= (ref_offset + blkwidth);   /* input */
+            p_tmp -= 6; /* intermediate output */
+            tmp = (uint32)(p_ref + blkwidth);
+            while ((uint32)p_ref < tmp)
+            {
+                r0 = *p_ref++;
+                r1 = *p_ref++;
+                r2 = *p_ref++;
+                r3 = *p_ref++;
+                r4 = *p_ref++;
+                /* first pixel */
+                r5 = *p_ref++;
+                result = (r0 + r5);
+                r0 = (r1 + r4);
+                result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                r0 = (r2 + r3);
+                result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                result = (result + 16) >> 5;
+                CLIP_RESULT(result)
+                pkres = result;
+                /* second pixel */
+                r0 = *p_ref++;
+                result = (r1 + r0);
+                r1 = (r2 + r5);
+                result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                r1 = (r3 + r4);
+                result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                result = (result + 16) >> 5;
+                CLIP_RESULT(result)
+                pkres |= (result << 8);
+                /* third pixel */
+                r1 = *p_ref++;
+                result = (r2 + r1);
+                r2 = (r3 + r0);
+                result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                r2 = (r4 + r5);
+                result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                result = (result + 16) >> 5;
+                CLIP_RESULT(result)
+                pkres |= (result << 16);
+                /* fourth pixel */
+                r2 = *p_ref++;
+                result = (r3 + r2);
+                r3 = (r4 + r1);
+                result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                r3 = (r5 + r0);
+                result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                result = (result + 16) >> 5;
+                CLIP_RESULT(result)
+                pkres |= (result << 24);
+
+                *p_tmp++ = pkres; /* write 4 pixel */
+                p_ref -= 5;
+            }
+            p_tmp += ((24 - blkwidth) >> 2); /* move to the next line */
+            p_ref += ref_offset;  /*    ref_offset = inpitch-blkwidth; */
+        }
+    }
+
+    /*  perform vertical interpolation */
+    /* not word-aligned */
+    if (((uint32)in2)&0x3)
+    {
+        eCreateAlign(in2, inpitch, -2, &tmp_in[0][0], blkwidth, blkheight + 5);
+        in2 = &tmp_in[2][0];
+        inpitch = 24;
+    }
+
+    p_cur = out;
+    curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically up and one pixel right */
+    pkres = blkheight * inpitch; /* reuse it for limit */
+
+    curr_offset += 3;
+
+    for (j = 0; j < blkwidth; j += 4, in2 += 4)
+    {
+        r13 = 0;
+        p_ref = in2;
+        p_tmp8 = &(tmp_res[0][j]); /* intermediate result */
+        p_tmp8 -= 24;  /* compensate for the first offset */
+        p_cur -= outpitch;  /* compensate for the first offset */
+        tmp = (uint32)(p_ref + pkres); /* limit */
+        while ((uint32)p_ref < tmp)  /* the loop un-rolled  */
+        {
+            /* Read 1 byte at a time is too slow, too many read and pack ops, need to call CreateAlign */
+            /*p_ref8 = p_ref-(inpitch<<1);          r0 = p_ref8[0];         r1 = p_ref8[2];
+            r0 |= (r1<<16);         r6 = p_ref8[1];         r1 = p_ref8[3];
+            r6 |= (r1<<16);         p_ref+=inpitch; */
+            r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+            p_ref += inpitch;
+            r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+            r0 &= 0xFF00FF;
+
+            /*p_ref8 = p_ref+(inpitch<<1);
+            r1 = p_ref8[0];         r7 = p_ref8[2];         r1 |= (r7<<16);
+            r7 = p_ref8[1];         r2 = p_ref8[3];         r7 |= (r2<<16);*/
+            r1 = *((uint32*)(p_ref + (inpitch << 1)));  /* r1, r7, ref[3] */
+            r7 = (r1 >> 8) & 0xFF00FF;
+            r1 &= 0xFF00FF;
+
+            r0 += r1;
+            r6 += r7;
+
+            /*r2 = p_ref[0];            r8 = p_ref[2];          r2 |= (r8<<16);
+            r8 = p_ref[1];          r1 = p_ref[3];          r8 |= (r1<<16);*/
+            r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+            r8 = (r2 >> 8) & 0xFF00FF;
+            r2 &= 0xFF00FF;
+
+            /*p_ref8 = p_ref-inpitch;           r1 = p_ref8[0];         r7 = p_ref8[2];
+            r1 |= (r7<<16);         r1 += r2;           r7 = p_ref8[1];
+            r2 = p_ref8[3];         r7 |= (r2<<16);*/
+            r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+            r7 = (r1 >> 8) & 0xFF00FF;
+            r1 &= 0xFF00FF;
+            r1 += r2;
+
+            r7 += r8;
+
+            r0 += 20 * r1;
+            r6 += 20 * r7;
+            r0 += 0x100010;
+            r6 += 0x100010;
+
+            /*p_ref8 = p_ref-(inpitch<<1);          r2 = p_ref8[0];         r8 = p_ref8[2];
+            r2 |= (r8<<16);         r8 = p_ref8[1];         r1 = p_ref8[3];         r8 |= (r1<<16);*/
+            r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+            r8 = (r2 >> 8) & 0xFF00FF;
+            r2 &= 0xFF00FF;
+
+            /*p_ref8 = p_ref+inpitch;           r1 = p_ref8[0];         r7 = p_ref8[2];
+            r1 |= (r7<<16);         r1 += r2;           r7 = p_ref8[1];
+            r2 = p_ref8[3];         r7 |= (r2<<16);*/
+            r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+            r7 = (r1 >> 8) & 0xFF00FF;
+            r1 &= 0xFF00FF;
+            r1 += r2;
+
+            r7 += r8;
+
+            r0 -= 5 * r1;
+            r6 -= 5 * r7;
+
+            r0 >>= 5;
+            r6 >>= 5;
+            /* clip */
+            r13 |= r6;
+            r13 |= r0;
+            //CLIPPACK(r6,result)
+            /* add with horizontal results */
+            r10 = *((uint32*)(p_tmp8 += 24));
+            r9 = (r10 >> 8) & 0xFF00FF;
+            r10 &= 0xFF00FF;
+
+            r0 += r10;
+            r0 += 0x10001;
+            r0 = (r0 >> 1) & 0xFF00FF;   /* mask to 8 bytes */
+
+            r6 += r9;
+            r6 += 0x10001;
+            r6 = (r6 >> 1) & 0xFF00FF;   /* mask to 8 bytes */
+
+            r0 |= (r6 << 8);  /* pack it back */
+            *((uint32*)(p_cur += outpitch)) = r0;
+        }
+        p_cur += curr_offset; /* offset to the next pixel */
+        if (r13 & 0xFF000700) /* this column need clipping */
+        {
+            p_cur -= 4;
+            for (i = 0; i < 4; i++)
+            {
+                p_ref = in2 + i;
+                p_tmp8 = &(tmp_res[0][j+i]); /* intermediate result */
+                p_tmp8 -= 24;  /* compensate for the first offset */
+                p_cur -= outpitch;  /* compensate for the first offset */
+                tmp = (uint32)(p_ref + pkres); /* limit */
+                while ((uint32)p_ref < tmp)  /* the loop un-rolled  */
+                {
+                    r0 = *(p_ref - (inpitch << 1));
+                    r1 = *(p_ref - inpitch);
+                    r2 = *p_ref;
+                    r3 = *(p_ref += inpitch);  /* modify pointer before loading */
+                    r4 = *(p_ref += inpitch);
+                    /* first pixel */
+                    r5 = *(p_ref += inpitch);
+                    result = (r0 + r5);
+                    r0 = (r1 + r4);
+                    result -= (r0 * 5);//result -= r0;  result -= (r0<<2);
+                    r0 = (r2 + r3);
+                    result += (r0 * 20);//result += (r0<<4);    result += (r0<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    tmp_result = *(p_tmp8 += 24);  /* modify pointer before loading */
+                    result = (result + tmp_result + 1);  /* no clip */
+                    result = (result >> 1);
+                    *(p_cur += outpitch) = result;
+                    /* second pixel */
+                    r0 = *(p_ref += inpitch);
+                    result = (r1 + r0);
+                    r1 = (r2 + r5);
+                    result -= (r1 * 5);//result -= r1;  result -= (r1<<2);
+                    r1 = (r3 + r4);
+                    result += (r1 * 20);//result += (r1<<4);    result += (r1<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    tmp_result = *(p_tmp8 += 24);  /* intermediate result */
+                    result = (result + tmp_result + 1);  /* no clip */
+                    result = (result >> 1);
+                    *(p_cur += outpitch) = result;
+                    /* third pixel */
+                    r1 = *(p_ref += inpitch);
+                    result = (r2 + r1);
+                    r2 = (r3 + r0);
+                    result -= (r2 * 5);//result -= r2;  result -= (r2<<2);
+                    r2 = (r4 + r5);
+                    result += (r2 * 20);//result += (r2<<4);    result += (r2<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    tmp_result = *(p_tmp8 += 24);  /* intermediate result */
+                    result = (result + tmp_result + 1);  /* no clip */
+                    result = (result >> 1);
+                    *(p_cur += outpitch) = result;
+                    /* fourth pixel */
+                    r2 = *(p_ref += inpitch);
+                    result = (r3 + r2);
+                    r3 = (r4 + r1);
+                    result -= (r3 * 5);//result -= r3;  result -= (r3<<2);
+                    r3 = (r5 + r0);
+                    result += (r3 * 20);//result += (r3<<4);    result += (r3<<2);
+                    result = (result + 16) >> 5;
+                    CLIP_RESULT(result)
+                    tmp_result = *(p_tmp8 += 24);  /* intermediate result */
+                    result = (result + tmp_result + 1);  /* no clip */
+                    result = (result >> 1);
+                    *(p_cur += outpitch) = result;
+                    p_ref -= (inpitch << 1);  /* move back to center of the filter of the next one */
+                }
+                p_cur += (curr_offset - 3);
+            }
+        }
+    }
+
+    return ;
+}
+
+/* position G */
+void eFullPelMC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+                int blkwidth, int blkheight)
+{
+    int i, j;
+    int offset_in = inpitch - blkwidth;
+    int offset_out = outpitch - blkwidth;
+    uint32 temp;
+    uint8 byte;
+
+    if (((uint32)in)&3)
+    {
+        for (j = blkheight; j > 0; j--)
+        {
+            for (i = blkwidth; i > 0; i -= 4)
+            {
+                temp = *in++;
+                byte = *in++;
+                temp |= (byte << 8);
+                byte = *in++;
+                temp |= (byte << 16);
+                byte = *in++;
+                temp |= (byte << 24);
+
+                *((uint32*)out) = temp; /* write 4 bytes */
+                out += 4;
+            }
+            out += offset_out;
+            in += offset_in;
+        }
+    }
+    else
+    {
+        for (j = blkheight; j > 0; j--)
+        {
+            for (i = blkwidth; i > 0; i -= 4)
+            {
+                temp = *((uint32*)in);
+                *((uint32*)out) = temp;
+                in += 4;
+                out += 4;
+            }
+            out += offset_out;
+            in += offset_in;
+        }
+    }
+    return ;
+}
+
+void ePadChroma(uint8 *ref, int picwidth, int picheight, int picpitch, int x_pos, int y_pos)
+{
+    int pad_height;
+    int pad_width;
+    uint8 *start;
+    uint32 word1, word2, word3;
+    int offset, j;
+
+
+    pad_height = 8 + ((y_pos & 7) ? 1 : 0);
+    pad_width = 8 + ((x_pos & 7) ? 1 : 0);
+
+    y_pos >>= 3;
+    x_pos >>= 3;
+    // pad vertical first
+    if (y_pos < 0) // need to pad up
+    {
+        if (x_pos < -8) start = ref - 8;
+        else if (x_pos + pad_width > picwidth + 7) start = ref + picwidth + 7 - pad_width;
+        else start = ref + x_pos;
+
+        /* word-align start */
+        offset = (uint32)start & 0x3;
+        if (offset) start -= offset;
+
+        word1 = *((uint32*)start);
+        word2 = *((uint32*)(start + 4));
+        word3 = *((uint32*)(start + 8));
+
+        /* pad up N rows */
+        j = -y_pos;
+        if (j > 8) j = 8;
+        while (j--)
+        {
+            *((uint32*)(start -= picpitch)) = word1;
+            *((uint32*)(start + 4)) = word2;
+            *((uint32*)(start + 8)) = word3;
+        }
+
+    }
+    else if (y_pos + pad_height >= picheight) /* pad down */
+    {
+        if (x_pos < -8) start = ref + picpitch * (picheight - 1) - 8;
+        else if (x_pos + pad_width > picwidth + 7) start = ref + picpitch * (picheight - 1) +
+                    picwidth + 7 - pad_width;
+        else    start = ref + picpitch * (picheight - 1) + x_pos;
+
+        /* word-align start */
+        offset = (uint32)start & 0x3;
+        if (offset) start -= offset;
+
+        word1 = *((uint32*)start);
+        word2 = *((uint32*)(start + 4));
+        word3 = *((uint32*)(start + 8));
+
+        /* pad down N rows */
+        j = y_pos + pad_height - picheight;
+        if (j > 8) j = 8;
+        while (j--)
+        {
+            *((uint32*)(start += picpitch)) = word1;
+            *((uint32*)(start + 4)) = word2;
+            *((uint32*)(start + 8)) = word3;
+        }
+    }
+
+    /* now pad horizontal */
+    if (x_pos < 0) // pad left
+    {
+        if (y_pos < -8) start = ref - (picpitch << 3);
+        else if (y_pos + pad_height > picheight + 7) start = ref + (picheight + 7 - pad_height) * picpitch;
+        else start = ref + y_pos * picpitch;
+
+        // now pad left 8 pixels for pad_height rows */
+        j = pad_height;
+        start -= picpitch;
+        while (j--)
+        {
+            word1 = *(start += picpitch);
+            word1 |= (word1 << 8);
+            word1 |= (word1 << 16);
+            *((uint32*)(start - 8)) = word1;
+            *((uint32*)(start - 4)) = word1;
+        }
+    }
+    else if (x_pos + pad_width >= picwidth) /* pad right */
+    {
+        if (y_pos < -8) start = ref - (picpitch << 3) + picwidth - 1;
+        else if (y_pos + pad_height > picheight + 7) start = ref + (picheight + 7 - pad_height) * picpitch + picwidth - 1;
+        else start = ref + y_pos * picpitch + picwidth - 1;
+
+        // now pad right 8 pixels for pad_height rows */
+        j = pad_height;
+        start -= picpitch;
+        while (j--)
+        {
+            word1 = *(start += picpitch);
+            word1 |= (word1 << 8);
+            word1 |= (word1 << 16);
+            *((uint32*)(start + 1)) = word1;
+            *((uint32*)(start + 5)) = word1;
+        }
+    }
+
+    return ;
+}
+
+
+void eChromaMotionComp(uint8 *ref, int picwidth, int picheight,
+                       int x_pos, int y_pos,
+                       uint8 *pred, int picpitch,
+                       int blkwidth, int blkheight)
+{
+    int dx, dy;
+    int offset_dx, offset_dy;
+    int index;
+
+    ePadChroma(ref, picwidth, picheight, picpitch, x_pos, y_pos);
+
+    dx = x_pos & 7;
+    dy = y_pos & 7;
+    offset_dx = (dx + 7) >> 3;
+    offset_dy = (dy + 7) >> 3;
+    x_pos = x_pos >> 3;  /* round it to full-pel resolution */
+    y_pos = y_pos >> 3;
+
+    ref += y_pos * picpitch + x_pos;
+
+    index = offset_dx + (offset_dy << 1) + ((blkwidth << 1) & 0x7);
+
+    (*(eChromaMC_SIMD[index]))(ref, picpitch , dx, dy, pred, picpitch, blkwidth, blkheight);
+    return ;
+}
+
+
+/* SIMD routines, unroll the loops in vertical direction, decreasing loops (things to be done) */
+void eChromaDiagonalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                            uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+    int32 r0, r1, r2, r3, result0, result1;
+    uint8 temp[288];
+    uint8 *ref, *out;
+    int i, j;
+    int dx_8 = 8 - dx;
+    int dy_8 = 8 - dy;
+
+    /* horizontal first */
+    out = temp;
+    for (i = 0; i < blkheight + 1; i++)
+    {
+        ref = pRef;
+        r0 = ref[0];
+        for (j = 0; j < blkwidth; j += 4)
+        {
+            r0 |= (ref[2] << 16);
+            result0 = dx_8 * r0;
+
+            r1 = ref[1] | (ref[3] << 16);
+            result0 += dx * r1;
+            *(int32 *)out = result0;
+
+            result0 = dx_8 * r1;
+
+            r2 = ref[4];
+            r0 = r0 >> 16;
+            r1 = r0 | (r2 << 16);
+            result0 += dx * r1;
+            *(int32 *)(out + 16) = result0;
+
+            ref += 4;
+            out += 4;
+            r0 = r2;
+        }
+        pRef += srcPitch;
+        out += (32 - blkwidth);
+    }
+
+//  pRef -= srcPitch*(blkheight+1);
+    ref = temp;
+
+    for (j = 0; j < blkwidth; j += 4)
+    {
+        r0 = *(int32 *)ref;
+        r1 = *(int32 *)(ref + 16);
+        ref += 32;
+        out = pOut;
+        for (i = 0; i < (blkheight >> 1); i++)
+        {
+            result0 = dy_8 * r0 + 0x00200020;
+            r2 = *(int32 *)ref;
+            result0 += dy * r2;
+            result0 >>= 6;
+            result0 &= 0x00FF00FF;
+            r0 = r2;
+
+            result1 = dy_8 * r1 + 0x00200020;
+            r3 = *(int32 *)(ref + 16);
+            result1 += dy * r3;
+            result1 >>= 6;
+            result1 &= 0x00FF00FF;
+            r1 = r3;
+            *(int32 *)out = result0 | (result1 << 8);
+            out += predPitch;
+            ref += 32;
+
+            result0 = dy_8 * r0 + 0x00200020;
+            r2 = *(int32 *)ref;
+            result0 += dy * r2;
+            result0 >>= 6;
+            result0 &= 0x00FF00FF;
+            r0 = r2;
+
+            result1 = dy_8 * r1 + 0x00200020;
+            r3 = *(int32 *)(ref + 16);
+            result1 += dy * r3;
+            result1 >>= 6;
+            result1 &= 0x00FF00FF;
+            r1 = r3;
+            *(int32 *)out = result0 | (result1 << 8);
+            out += predPitch;
+            ref += 32;
+        }
+        pOut += 4;
+        ref = temp + 4; /* since it can only iterate twice max */
+    }
+    return;
+}
+
+void eChromaHorizontalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                              uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+    (void)(dy);
+
+    int32 r0, r1, r2, result0, result1;
+    uint8 *ref, *out;
+    int i, j;
+    int dx_8 = 8 - dx;
+
+    /* horizontal first */
+    for (i = 0; i < blkheight; i++)
+    {
+        ref = pRef;
+        out = pOut;
+
+        r0 = ref[0];
+        for (j = 0; j < blkwidth; j += 4)
+        {
+            r0 |= (ref[2] << 16);
+            result0 = dx_8 * r0 + 0x00040004;
+
+            r1 = ref[1] | (ref[3] << 16);
+            result0 += dx * r1;
+            result0 >>= 3;
+            result0 &= 0x00FF00FF;
+
+            result1 = dx_8 * r1 + 0x00040004;
+
+            r2 = ref[4];
+            r0 = r0 >> 16;
+            r1 = r0 | (r2 << 16);
+            result1 += dx * r1;
+            result1 >>= 3;
+            result1 &= 0x00FF00FF;
+
+            *(int32 *)out = result0 | (result1 << 8);
+
+            ref += 4;
+            out += 4;
+            r0 = r2;
+        }
+
+        pRef += srcPitch;
+        pOut += predPitch;
+    }
+    return;
+}
+
+void eChromaVerticalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                            uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+    (void)(dx);
+
+    int32 r0, r1, r2, r3, result0, result1;
+    int i, j;
+    uint8 *ref, *out;
+    int dy_8 = 8 - dy;
+    /* vertical first */
+    for (i = 0; i < blkwidth; i += 4)
+    {
+        ref = pRef;
+        out = pOut;
+
+        r0 = ref[0] | (ref[2] << 16);
+        r1 = ref[1] | (ref[3] << 16);
+        ref += srcPitch;
+        for (j = 0; j < blkheight; j++)
+        {
+            result0 = dy_8 * r0 + 0x00040004;
+            r2 = ref[0] | (ref[2] << 16);
+            result0 += dy * r2;
+            result0 >>= 3;
+            result0 &= 0x00FF00FF;
+            r0 = r2;
+
+            result1 = dy_8 * r1 + 0x00040004;
+            r3 = ref[1] | (ref[3] << 16);
+            result1 += dy * r3;
+            result1 >>= 3;
+            result1 &= 0x00FF00FF;
+            r1 = r3;
+            *(int32 *)out = result0 | (result1 << 8);
+            ref += srcPitch;
+            out += predPitch;
+        }
+        pOut += 4;
+        pRef += 4;
+    }
+    return;
+}
+
+void eChromaDiagonalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                             uint8 *pOut,  int predPitch, int blkwidth, int blkheight)
+{
+    (void)(blkwidth);
+
+    int32 r0, r1, temp0, temp1, result;
+    int32 temp[9];
+    int32 *out;
+    int i, r_temp;
+    int dy_8 = 8 - dy;
+
+    /* horizontal first */
+    out = temp;
+    for (i = 0; i < blkheight + 1; i++)
+    {
+        r_temp = pRef[1];
+        temp0 = (pRef[0] << 3) + dx * (r_temp - pRef[0]);
+        temp1 = (r_temp << 3) + dx * (pRef[2] - r_temp);
+        r0 = temp0 | (temp1 << 16);
+        *out++ = r0;
+        pRef += srcPitch;
+    }
+
+    pRef -= srcPitch * (blkheight + 1);
+
+    out = temp;
+
+    r0 = *out++;
+
+    for (i = 0; i < blkheight; i++)
+    {
+        result = dy_8 * r0 + 0x00200020;
+        r1 = *out++;
+        result += dy * r1;
+        result >>= 6;
+        result &= 0x00FF00FF;
+        *(int16 *)pOut = (result >> 8) | (result & 0xFF);
+        r0 = r1;
+        pOut += predPitch;
+    }
+    return;
+}
+
+void eChromaHorizontalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                               uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+    (void)(dy);
+    (void)(blkwidth);
+
+    int i, temp, temp0, temp1;
+
+    /* horizontal first */
+    for (i = 0; i < blkheight; i++)
+    {
+        temp = pRef[1];
+        temp0 = ((pRef[0] << 3) + dx * (temp - pRef[0]) + 4) >> 3;
+        temp1 = ((temp << 3) + dx * (pRef[2] - temp) + 4) >> 3;
+
+        *(int16 *)pOut = temp0 | (temp1 << 8);
+        pRef += srcPitch;
+        pOut += predPitch;
+
+    }
+    return;
+}
+void eChromaVerticalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                             uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+    (void)(dx);
+    (void)(blkwidth);
+
+    int32 r0, r1, result;
+    int i;
+    int dy_8 = 8 - dy;
+    r0 = pRef[0] | (pRef[1] << 16);
+    pRef += srcPitch;
+    for (i = 0; i < blkheight; i++)
+    {
+        result = dy_8 * r0 + 0x00040004;
+        r1 = pRef[0] | (pRef[1] << 16);
+        result += dy * r1;
+        result >>= 3;
+        result &= 0x00FF00FF;
+        *(int16 *)pOut = (result >> 8) | (result & 0xFF);
+        r0 = r1;
+        pRef += srcPitch;
+        pOut += predPitch;
+    }
+    return;
+}
+
+void eChromaFullMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+                        uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+    (void)(dx);
+    (void)(dy);
+
+    int i, j;
+    int offset_in = srcPitch - blkwidth;
+    int offset_out = predPitch - blkwidth;
+    uint16 temp;
+    uint8 byte;
+
+    if (((uint32)pRef)&1)
+    {
+        for (j = blkheight; j > 0; j--)
+        {
+            for (i = blkwidth; i > 0; i -= 2)
+            {
+                temp = *pRef++;
+                byte = *pRef++;
+                temp |= (byte << 8);
+                *((uint16*)pOut) = temp; /* write 2 bytes */
+                pOut += 2;
+            }
+            pOut += offset_out;
+            pRef += offset_in;
+        }
+    }
+    else
+    {
+        for (j = blkheight; j > 0; j--)
+        {
+            for (i = blkwidth; i > 0; i -= 2)
+            {
+                temp = *((uint16*)pRef);
+                *((uint16*)pOut) = temp;
+                pRef += 2;
+                pOut += 2;
+            }
+            pOut += offset_out;
+            pRef += offset_in;
+        }
+    }
+    return ;
+}
diff --git a/media/libstagefright/codecs/avc/enc/src/motion_est.cpp b/media/libstagefright/codecs/avc/enc/src/motion_est.cpp
new file mode 100644
index 0000000..f650ef9
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/motion_est.cpp
@@ -0,0 +1,1774 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+#define MIN_GOP     1   /* minimum size of GOP, 1/23/01, need to be tested */
+
+#define DEFAULT_REF_IDX     0  /* always from the first frame in the reflist */
+
+#define ALL_CAND_EQUAL  10  /*  any number greater than 5 will work */
+
+
+/* from TMN 3.2 */
+#define PREF_NULL_VEC 129   /* zero vector bias */
+#define PREF_16_VEC 129     /* 1MV bias versus 4MVs*/
+#define PREF_INTRA  3024//512       /* bias for INTRA coding */
+
+const static int tab_exclude[9][9] =  // [last_loc][curr_loc]
+{
+    {0, 0, 0, 0, 0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 1, 1, 1, 0, 0},
+    {0, 0, 0, 0, 1, 1, 1, 1, 1},
+    {0, 0, 0, 0, 0, 0, 1, 1, 1},
+    {0, 1, 1, 0, 0, 0, 1, 1, 1},
+    {0, 1, 1, 0, 0, 0, 0, 0, 1},
+    {0, 1, 1, 1, 1, 0, 0, 0, 1},
+    {0, 0, 1, 1, 1, 0, 0, 0, 0},
+    {0, 0, 1, 1, 1, 1, 1, 0, 0}
+}; //to decide whether to continue or compute
+
+const static int refine_next[8][2] =    /* [curr_k][increment] */
+{
+    {0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}
+};
+
+#ifdef _SAD_STAT
+uint32 num_MB = 0;
+uint32 num_cand = 0;
+#endif
+
+/************************************************************************/
+#define TH_INTER_2  100  /* temporary for now */
+
+//#define FIXED_INTERPRED_MODE  AVC_P16
+#define FIXED_REF_IDX   0
+#define FIXED_MVX 0
+#define FIXED_MVY 0
+
+// only use when AVC_P8 or AVC_P8ref0
+#define FIXED_SUBMB_MODE    AVC_4x4
+/*************************************************************************/
+
+/* Initialize arrays necessary for motion search */
+AVCEnc_Status InitMotionSearchModule(AVCHandle *avcHandle)
+{
+    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    int search_range = rateCtrl->mvRange;
+    int number_of_subpel_positions = 4 * (2 * search_range + 3);
+    int max_mv_bits, max_mvd;
+    int temp_bits = 0;
+    uint8 *mvbits;
+    int bits, imax, imin, i;
+    uint8* subpel_pred = (uint8*) encvid->subpel_pred; // all 16 sub-pel positions
+
+
+    while (number_of_subpel_positions > 0)
+    {
+        temp_bits++;
+        number_of_subpel_positions >>= 1;
+    }
+
+    max_mv_bits = 3 + 2 * temp_bits;
+    max_mvd  = (1 << (max_mv_bits >> 1)) - 1;
+
+    encvid->mvbits_array = (uint8*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
+                           sizeof(uint8) * (2 * max_mvd + 1), DEFAULT_ATTR);
+
+    if (encvid->mvbits_array == NULL)
+    {
+        return AVCENC_MEMORY_FAIL;
+    }
+
+    mvbits = encvid->mvbits  = encvid->mvbits_array + max_mvd;
+
+    mvbits[0] = 1;
+    for (bits = 3; bits <= max_mv_bits; bits += 2)
+    {
+        imax = 1    << (bits >> 1);
+        imin = imax >> 1;
+
+        for (i = imin; i < imax; i++)   mvbits[-i] = mvbits[i] = bits;
+    }
+
+    /* initialize half-pel search */
+    encvid->hpel_cand[0] = subpel_pred + REF_CENTER;
+    encvid->hpel_cand[1] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1 ;
+    encvid->hpel_cand[2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
+    encvid->hpel_cand[3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+    encvid->hpel_cand[4] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+    encvid->hpel_cand[5] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
+    encvid->hpel_cand[6] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+    encvid->hpel_cand[7] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+    encvid->hpel_cand[8] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+
+    /* For quarter-pel interpolation around best half-pel result */
+
+    encvid->bilin_base[0][0] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+    encvid->bilin_base[0][1] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
+    encvid->bilin_base[0][2] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+    encvid->bilin_base[0][3] = subpel_pred + REF_CENTER;
+
+
+    encvid->bilin_base[1][0] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+    encvid->bilin_base[1][1] = subpel_pred + REF_CENTER - 24;
+    encvid->bilin_base[1][2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+    encvid->bilin_base[1][3] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
+
+    encvid->bilin_base[2][0] = subpel_pred + REF_CENTER - 24;
+    encvid->bilin_base[2][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
+    encvid->bilin_base[2][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
+    encvid->bilin_base[2][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
+
+    encvid->bilin_base[3][0] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
+    encvid->bilin_base[3][1] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
+    encvid->bilin_base[3][2] = subpel_pred + REF_CENTER;
+    encvid->bilin_base[3][3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+
+    encvid->bilin_base[4][0] = subpel_pred + REF_CENTER;
+    encvid->bilin_base[4][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+    encvid->bilin_base[4][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
+    encvid->bilin_base[4][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+
+    encvid->bilin_base[5][0] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+    encvid->bilin_base[5][1] = subpel_pred + REF_CENTER;
+    encvid->bilin_base[5][2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+    encvid->bilin_base[5][3] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
+
+    encvid->bilin_base[6][0] = subpel_pred + REF_CENTER - 1;
+    encvid->bilin_base[6][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+    encvid->bilin_base[6][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 24;
+    encvid->bilin_base[6][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+
+    encvid->bilin_base[7][0] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE;
+    encvid->bilin_base[7][1] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+    encvid->bilin_base[7][2] = subpel_pred + REF_CENTER - 1;
+    encvid->bilin_base[7][3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+
+    encvid->bilin_base[8][0] = subpel_pred + REF_CENTER - 25;
+    encvid->bilin_base[8][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+    encvid->bilin_base[8][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE;
+    encvid->bilin_base[8][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+
+
+    return AVCENC_SUCCESS;
+}
+
+/* Clean-up memory */
+void CleanMotionSearchModule(AVCHandle *avcHandle)
+{
+    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+
+    if (encvid->mvbits_array)
+    {
+        avcHandle->CBAVC_Free(avcHandle->userData, (int)(encvid->mvbits_array));
+        encvid->mvbits = NULL;
+    }
+
+    return ;
+}
+
+
+bool IntraDecisionABE(int *min_cost, uint8 *cur, int pitch, bool ave)
+{
+    int j;
+    uint8 *out;
+    int temp, SBE;
+    OsclFloat ABE;
+    bool intra = true;
+
+    SBE = 0;
+    /* top neighbor */
+    out = cur - pitch;
+    for (j = 0; j < 16; j++)
+    {
+        temp = out[j] - cur[j];
+        SBE += ((temp >= 0) ? temp : -temp);
+    }
+
+    /* left neighbor */
+    out = cur - 1;
+    out -= pitch;
+    cur -= pitch;
+    for (j = 0; j < 16; j++)
+    {
+        temp = *(out += pitch) - *(cur += pitch);
+        SBE += ((temp >= 0) ? temp : -temp);
+    }
+
+    /* compare mincost/384 and SBE/64 */
+    ABE = SBE / 32.0; //ABE = SBE/64.0; //
+    if (ABE >= *min_cost / 256.0) //if( ABE*0.8 >= min_cost/384.0) //
+    {
+        intra = false; // no possibility of intra, just use inter
+    }
+    else
+    {
+        if (ave == true)
+        {
+            *min_cost = (*min_cost + (int)(SBE * 8)) >> 1; // possibility of intra, averaging the cost
+        }
+        else
+        {
+            *min_cost = (int)(SBE * 8);
+        }
+    }
+
+    return intra;
+}
+
+/******* main function for macroblock prediction for the entire frame ***/
+/* if turns out to be IDR frame, set video->nal_unit_type to AVC_NALTYPE_IDR */
+void AVCMotionEstimation(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    int slice_type = video->slice_type;
+    AVCFrameIO *currInput = encvid->currInput;
+    AVCPictureData *refPic = video->RefPicList0[0];
+    int i, j, k;
+    int mbwidth = video->PicWidthInMbs;
+    int mbheight = video->PicHeightInMbs;
+    int totalMB = video->PicSizeInMbs;
+    int pitch = currInput->pitch;
+    AVCMacroblock *currMB, *mblock = video->mblock;
+    AVCMV *mot_mb_16x16, *mot16x16 = encvid->mot16x16;
+    // AVCMV *mot_mb_16x8, *mot_mb_8x16, *mot_mb_8x8, etc;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    uint8 *intraSearch = encvid->intraSearch;
+    uint FS_en = encvid->fullsearch_enable;
+
+    int NumIntraSearch, start_i, numLoop, incr_i;
+    int mbnum, offset;
+    uint8 *cur, *best_cand[5];
+    int totalSAD = 0;   /* average SAD for rate control */
+    int type_pred;
+    int abe_cost;
+
+#ifdef HTFM
+    /***** HYPOTHESIS TESTING ********/  /* 2/28/01 */
+    int collect = 0;
+    HTFM_Stat htfm_stat;
+    double newvar[16];
+    double exp_lamda[15];
+    /*********************************/
+#endif
+    int hp_guess = 0;
+    uint32 mv_uint32;
+
+    offset = 0;
+
+    if (slice_type == AVC_I_SLICE)
+    {
+        /* cannot do I16 prediction here because it needs full decoding. */
+        for (i = 0; i < totalMB; i++)
+        {
+            encvid->min_cost[i] = 0x7FFFFFFF;  /* max value for int */
+        }
+
+        memset(intraSearch, 1, sizeof(uint8)*totalMB);
+
+        encvid->firstIntraRefreshMBIndx = 0; /* reset this */
+
+        return ;
+    }
+    else   // P_SLICE
+    {
+        for (i = 0; i < totalMB; i++)
+        {
+            mblock[i].mb_intra = 0;
+        }
+        memset(intraSearch, 1, sizeof(uint8)*totalMB);
+    }
+
+    if (refPic->padded == 0)
+    {
+        AVCPaddingEdge(refPic);
+        refPic->padded = 1;
+    }
+    /* Random INTRA update */
+    if (rateCtrl->intraMBRate)
+    {
+        AVCRasterIntraUpdate(encvid, mblock, totalMB, rateCtrl->intraMBRate);
+    }
+
+    encvid->sad_extra_info = NULL;
+#ifdef HTFM
+    /***** HYPOTHESIS TESTING ********/
+    InitHTFM(video, &htfm_stat, newvar, &collect);
+    /*********************************/
+#endif
+
+    if ((rateCtrl->scdEnable == 1)
+            && ((rateCtrl->frame_rate < 5.0) || (video->sliceHdr->frame_num > MIN_GOP)))
+        /* do not try to detect a new scene if low frame rate and too close to previous I-frame */
+    {
+        incr_i = 2;
+        numLoop = 2;
+        start_i = 1;
+        type_pred = 0; /* for initial candidate selection */
+    }
+    else
+    {
+        incr_i = 1;
+        numLoop = 1;
+        start_i = 0;
+        type_pred = 2;
+    }
+
+    /* First pass, loop thru half the macroblock */
+    /* determine scene change */
+    /* Second pass, for the rest of macroblocks */
+    NumIntraSearch = 0; // to be intra searched in the encoding loop.
+    while (numLoop--)
+    {
+        for (j = 0; j < mbheight; j++)
+        {
+            if (incr_i > 1)
+                start_i = (start_i == 0 ? 1 : 0) ; /* toggle 0 and 1 */
+
+            offset = pitch * (j << 4) + (start_i << 4);
+
+            mbnum = j * mbwidth + start_i;
+
+            for (i = start_i; i < mbwidth; i += incr_i)
+            {
+                video->mbNum = mbnum;
+                video->currMB = currMB = mblock + mbnum;
+                mot_mb_16x16 = mot16x16 + mbnum;
+
+                cur = currInput->YCbCr[0] + offset;
+
+                if (currMB->mb_intra == 0) /* for INTER mode */
+                {
+#if defined(HTFM)
+                    HTFMPrepareCurMB_AVC(encvid, &htfm_stat, cur, pitch);
+#else
+                    AVCPrepareCurMB(encvid, cur, pitch);
+#endif
+                    /************************************************************/
+                    /******** full-pel 1MV search **********************/
+
+                    AVCMBMotionSearch(encvid, cur, best_cand, i << 4, j << 4, type_pred,
+                                      FS_en, &hp_guess);
+
+                    abe_cost = encvid->min_cost[mbnum] = mot_mb_16x16->sad;
+
+                    /* set mbMode and MVs */
+                    currMB->mbMode = AVC_P16;
+                    currMB->MBPartPredMode[0][0] = AVC_Pred_L0;
+                    mv_uint32 = ((mot_mb_16x16->y) << 16) | ((mot_mb_16x16->x) & 0xffff);
+                    for (k = 0; k < 32; k += 2)
+                    {
+                        currMB->mvL0[k>>1] = mv_uint32;
+                    }
+
+                    /* make a decision whether it should be tested for intra or not */
+                    if (i != mbwidth - 1 && j != mbheight - 1 && i != 0 && j != 0)
+                    {
+                        if (false == IntraDecisionABE(&abe_cost, cur, pitch, true))
+                        {
+                            intraSearch[mbnum] = 0;
+                        }
+                        else
+                        {
+                            NumIntraSearch++;
+                            rateCtrl->MADofMB[mbnum] = abe_cost;
+                        }
+                    }
+                    else // boundary MBs, always do intra search
+                    {
+                        NumIntraSearch++;
+                    }
+
+                    totalSAD += (int) rateCtrl->MADofMB[mbnum];//mot_mb_16x16->sad;
+                }
+                else    /* INTRA update, use for prediction */
+                {
+                    mot_mb_16x16[0].x = mot_mb_16x16[0].y = 0;
+
+                    /* reset all other MVs to zero */
+                    /* mot_mb_16x8, mot_mb_8x16, mot_mb_8x8, etc. */
+                    abe_cost = encvid->min_cost[mbnum] = 0x7FFFFFFF;  /* max value for int */
+
+                    if (i != mbwidth - 1 && j != mbheight - 1 && i != 0 && j != 0)
+                    {
+                        IntraDecisionABE(&abe_cost, cur, pitch, false);
+
+                        rateCtrl->MADofMB[mbnum] = abe_cost;
+                        totalSAD += abe_cost;
+                    }
+
+                    NumIntraSearch++ ;
+                    /* cannot do I16 prediction here because it needs full decoding. */
+                    // intraSearch[mbnum] = 1;
+
+                }
+
+                mbnum += incr_i;
+                offset += (incr_i << 4);
+
+            } /* for i */
+        } /* for j */
+
+        /* since we cannot do intra/inter decision here, the SCD has to be
+        based on other criteria such as motion vectors coherency or the SAD */
+        if (incr_i > 1 && numLoop) /* scene change on and first loop */
+        {
+            //if(NumIntraSearch > ((totalMB>>3)<<1) + (totalMB>>3)) /* 75% of 50%MBs */
+            if (NumIntraSearch*99 > (48*totalMB)) /* 20% of 50%MBs */
+                /* need to do more investigation about this threshold since the NumIntraSearch
+                only show potential intra MBs, not the actual one */
+            {
+                /* we can choose to just encode I_SLICE without IDR */
+                //video->nal_unit_type = AVC_NALTYPE_IDR;
+                video->nal_unit_type = AVC_NALTYPE_SLICE;
+                video->sliceHdr->slice_type = AVC_I_ALL_SLICE;
+                video->slice_type = AVC_I_SLICE;
+                memset(intraSearch, 1, sizeof(uint8)*totalMB);
+                i = totalMB;
+                while (i--)
+                {
+                    mblock[i].mb_intra = 1;
+                    encvid->min_cost[i] = 0x7FFFFFFF;  /* max value for int */
+                }
+
+                rateCtrl->totalSAD = totalSAD * 2;  /* SAD */
+
+                return ;
+            }
+        }
+        /******** no scene change, continue motion search **********************/
+        start_i = 0;
+        type_pred++; /* second pass */
+    }
+
+    rateCtrl->totalSAD = totalSAD;  /* SAD */
+
+#ifdef HTFM
+    /***** HYPOTHESIS TESTING ********/
+    if (collect)
+    {
+        collect = 0;
+        UpdateHTFM(encvid, newvar, exp_lamda, &htfm_stat);
+    }
+    /*********************************/
+#endif
+
+    return ;
+}
+
+/*=====================================================================
+    Function:   PaddingEdge
+    Date:       09/16/2000
+    Purpose:    Pad edge of a Vop
+=====================================================================*/
+
+void  AVCPaddingEdge(AVCPictureData *refPic)
+{
+    uint8 *src, *dst;
+    int i;
+    int pitch, width, height;
+    uint32 temp1, temp2;
+
+    width = refPic->width;
+    height = refPic->height;
+    pitch = refPic->pitch;
+
+    /* pad top */
+    src = refPic->Sl;
+
+    temp1 = *src; /* top-left corner */
+    temp2 = src[width-1]; /* top-right corner */
+    temp1 |= (temp1 << 8);
+    temp1 |= (temp1 << 16);
+    temp2 |= (temp2 << 8);
+    temp2 |= (temp2 << 16);
+
+    dst = src - (pitch << 4);
+
+    *((uint32*)(dst - 16)) = temp1;
+    *((uint32*)(dst - 12)) = temp1;
+    *((uint32*)(dst - 8)) = temp1;
+    *((uint32*)(dst - 4)) = temp1;
+
+    memcpy(dst, src, width);
+
+    *((uint32*)(dst += width)) = temp2;
+    *((uint32*)(dst + 4)) = temp2;
+    *((uint32*)(dst + 8)) = temp2;
+    *((uint32*)(dst + 12)) = temp2;
+
+    dst = dst - width - 16;
+
+    i = 15;
+    while (i--)
+    {
+        memcpy(dst + pitch, dst, pitch);
+        dst += pitch;
+    }
+
+    /* pad sides */
+    dst += (pitch + 16);
+    src = dst;
+    i = height;
+    while (i--)
+    {
+        temp1 = *src;
+        temp2 = src[width-1];
+        temp1 |= (temp1 << 8);
+        temp1 |= (temp1 << 16);
+        temp2 |= (temp2 << 8);
+        temp2 |= (temp2 << 16);
+
+        *((uint32*)(dst - 16)) = temp1;
+        *((uint32*)(dst - 12)) = temp1;
+        *((uint32*)(dst - 8)) = temp1;
+        *((uint32*)(dst - 4)) = temp1;
+
+        *((uint32*)(dst += width)) = temp2;
+        *((uint32*)(dst + 4)) = temp2;
+        *((uint32*)(dst + 8)) = temp2;
+        *((uint32*)(dst + 12)) = temp2;
+
+        src += pitch;
+        dst = src;
+    }
+
+    /* pad bottom */
+    dst -= 16;
+    i = 16;
+    while (i--)
+    {
+        memcpy(dst, dst - pitch, pitch);
+        dst += pitch;
+    }
+
+
+    return ;
+}
+
+/*===========================================================================
+    Function:   AVCRasterIntraUpdate
+    Date:       2/26/01
+    Purpose:    To raster-scan assign INTRA-update .
+                N macroblocks are updated (also was programmable).
+===========================================================================*/
+void AVCRasterIntraUpdate(AVCEncObject *encvid, AVCMacroblock *mblock, int totalMB, int numRefresh)
+{
+    int indx, i;
+
+    indx = encvid->firstIntraRefreshMBIndx;
+    for (i = 0; i < numRefresh && indx < totalMB; i++)
+    {
+        (mblock + indx)->mb_intra = 1;
+        encvid->intraSearch[indx++] = 1;
+    }
+
+    /* if read the end of frame, reset and loop around */
+    if (indx >= totalMB - 1)
+    {
+        indx = 0;
+        while (i < numRefresh && indx < totalMB)
+        {
+            (mblock + indx)->mb_intra = 1;
+            encvid->intraSearch[indx++] = 1;
+            i++;
+        }
+    }
+
+    encvid->firstIntraRefreshMBIndx = indx; /* update with a new value */
+
+    return ;
+}
+
+
+#ifdef HTFM
+void InitHTFM(VideoEncData *encvid, HTFM_Stat *htfm_stat, double *newvar, int *collect)
+{
+    AVCCommonObj *video = encvid->common;
+    int i;
+    int lx = video->currPic->width; // padding
+    int lx2 = lx << 1;
+    int lx3 = lx2 + lx;
+    int rx = video->currPic->pitch;
+    int rx2 = rx << 1;
+    int rx3 = rx2 + rx;
+
+    int *offset, *offset2;
+
+    /* 4/11/01, collect data every 30 frames, doesn't have to be base layer */
+    if (((int)video->sliceHdr->frame_num) % 30 == 1)
+    {
+
+        *collect = 1;
+
+        htfm_stat->countbreak = 0;
+        htfm_stat->abs_dif_mad_avg = 0;
+
+        for (i = 0; i < 16; i++)
+        {
+            newvar[i] = 0.0;
+        }
+//      encvid->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM_Collect;
+        encvid->functionPointer->SAD_Macroblock = &SAD_MB_HTFM_Collect;
+        encvid->functionPointer->SAD_MB_HalfPel[0] = NULL;
+        encvid->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFM_Collectxh;
+        encvid->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFM_Collectyh;
+        encvid->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFM_Collectxhyh;
+        encvid->sad_extra_info = (void*)(htfm_stat);
+        offset = htfm_stat->offsetArray;
+        offset2 = htfm_stat->offsetRef;
+    }
+    else
+    {
+//      encvid->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM;
+        encvid->functionPointer->SAD_Macroblock = &SAD_MB_HTFM;
+        encvid->functionPointer->SAD_MB_HalfPel[0] = NULL;
+        encvid->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFMxh;
+        encvid->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFMyh;
+        encvid->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFMxhyh;
+        encvid->sad_extra_info = (void*)(encvid->nrmlz_th);
+        offset = encvid->nrmlz_th + 16;
+        offset2 = encvid->nrmlz_th + 32;
+    }
+
+    offset[0] = 0;
+    offset[1] = lx2 + 2;
+    offset[2] = 2;
+    offset[3] = lx2;
+    offset[4] = lx + 1;
+    offset[5] = lx3 + 3;
+    offset[6] = lx + 3;
+    offset[7] = lx3 + 1;
+    offset[8] = lx;
+    offset[9] = lx3 + 2;
+    offset[10] = lx3 ;
+    offset[11] = lx + 2 ;
+    offset[12] = 1;
+    offset[13] = lx2 + 3;
+    offset[14] = lx2 + 1;
+    offset[15] = 3;
+
+    offset2[0] = 0;
+    offset2[1] = rx2 + 2;
+    offset2[2] = 2;
+    offset2[3] = rx2;
+    offset2[4] = rx + 1;
+    offset2[5] = rx3 + 3;
+    offset2[6] = rx + 3;
+    offset2[7] = rx3 + 1;
+    offset2[8] = rx;
+    offset2[9] = rx3 + 2;
+    offset2[10] = rx3 ;
+    offset2[11] = rx + 2 ;
+    offset2[12] = 1;
+    offset2[13] = rx2 + 3;
+    offset2[14] = rx2 + 1;
+    offset2[15] = 3;
+
+    return ;
+}
+
+void UpdateHTFM(AVCEncObject *encvid, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat)
+{
+    if (htfm_stat->countbreak == 0)
+        htfm_stat->countbreak = 1;
+
+    newvar[0] = (double)(htfm_stat->abs_dif_mad_avg) / (htfm_stat->countbreak * 16.);
+
+    if (newvar[0] < 0.001)
+    {
+        newvar[0] = 0.001; /* to prevent floating overflow */
+    }
+    exp_lamda[0] =  1 / (newvar[0] * 1.4142136);
+    exp_lamda[1] = exp_lamda[0] * 1.5825;
+    exp_lamda[2] = exp_lamda[0] * 2.1750;
+    exp_lamda[3] = exp_lamda[0] * 3.5065;
+    exp_lamda[4] = exp_lamda[0] * 3.1436;
+    exp_lamda[5] = exp_lamda[0] * 3.5315;
+    exp_lamda[6] = exp_lamda[0] * 3.7449;
+    exp_lamda[7] = exp_lamda[0] * 4.5854;
+    exp_lamda[8] = exp_lamda[0] * 4.6191;
+    exp_lamda[9] = exp_lamda[0] * 5.4041;
+    exp_lamda[10] = exp_lamda[0] * 6.5974;
+    exp_lamda[11] = exp_lamda[0] * 10.5341;
+    exp_lamda[12] = exp_lamda[0] * 10.0719;
+    exp_lamda[13] = exp_lamda[0] * 12.0516;
+    exp_lamda[14] = exp_lamda[0] * 15.4552;
+
+    CalcThreshold(HTFM_Pf, exp_lamda, encvid->nrmlz_th);
+    return ;
+}
+
+
+void CalcThreshold(double pf, double exp_lamda[], int nrmlz_th[])
+{
+    int i;
+    double temp[15];
+    //  printf("\nLamda: ");
+
+    /* parametric PREMODELling */
+    for (i = 0; i < 15; i++)
+    {
+        //    printf("%g ",exp_lamda[i]);
+        if (pf < 0.5)
+            temp[i] = 1 / exp_lamda[i] * M4VENC_LOG(2 * pf);
+        else
+            temp[i] = -1 / exp_lamda[i] * M4VENC_LOG(2 * (1 - pf));
+    }
+
+    nrmlz_th[15] = 0;
+    for (i = 0; i < 15; i++)        /* scale upto no.pixels */
+        nrmlz_th[i] = (int)(temp[i] * ((i + 1) << 4) + 0.5);
+
+    return ;
+}
+
+void    HTFMPrepareCurMB_AVC(AVCEncObject *encvid, HTFM_Stat *htfm_stat, uint8 *cur, int pitch)
+{
+    AVCCommonObj *video = encvid->common;
+    uint32 *htfmMB = (uint32*)(encvid->currYMB);
+    uint8 *ptr, byte;
+    int *offset;
+    int i;
+    uint32 word;
+
+    if (((int)video->sliceHdr->frame_num) % 30 == 1)
+    {
+        offset = htfm_stat->offsetArray;
+    }
+    else
+    {
+        offset = encvid->nrmlz_th + 16;
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        ptr = cur + offset[i];
+        word = ptr[0];
+        byte = ptr[4];
+        word |= (byte << 8);
+        byte = ptr[8];
+        word |= (byte << 16);
+        byte = ptr[12];
+        word |= (byte << 24);
+        *htfmMB++ = word;
+
+        word = *(ptr += (pitch << 2));
+        byte = ptr[4];
+        word |= (byte << 8);
+        byte = ptr[8];
+        word |= (byte << 16);
+        byte = ptr[12];
+        word |= (byte << 24);
+        *htfmMB++ = word;
+
+        word = *(ptr += (pitch << 2));
+        byte = ptr[4];
+        word |= (byte << 8);
+        byte = ptr[8];
+        word |= (byte << 16);
+        byte = ptr[12];
+        word |= (byte << 24);
+        *htfmMB++ = word;
+
+        word = *(ptr += (pitch << 2));
+        byte = ptr[4];
+        word |= (byte << 8);
+        byte = ptr[8];
+        word |= (byte << 16);
+        byte = ptr[12];
+        word |= (byte << 24);
+        *htfmMB++ = word;
+    }
+
+    return ;
+}
+
+
+#endif // HTFM
+
+void    AVCPrepareCurMB(AVCEncObject *encvid, uint8 *cur, int pitch)
+{
+    void* tmp = (void*)(encvid->currYMB);
+    uint32 *currYMB = (uint32*) tmp;
+    int i;
+
+    cur -= pitch;
+
+    for (i = 0; i < 16; i++)
+    {
+        *currYMB++ = *((uint32*)(cur += pitch));
+        *currYMB++ = *((uint32*)(cur + 4));
+        *currYMB++ = *((uint32*)(cur + 8));
+        *currYMB++ = *((uint32*)(cur + 12));
+    }
+
+    return ;
+}
+
+#ifdef FIXED_INTERPRED_MODE
+
+/* due to the complexity of the predicted motion vector, we may not decide to skip
+a macroblock here just yet. */
+/* We will find the best motion vector and the best intra prediction mode for each block. */
+/* output are
+    currMB->NumMbPart,  currMB->MbPartWidth, currMB->MbPartHeight,
+    currMB->NumSubMbPart[], currMB->SubMbPartWidth[], currMB->SubMbPartHeight,
+    currMB->MBPartPredMode[][] (L0 or L1 or BiPred)
+    currMB->RefIdx[], currMB->ref_idx_L0[],
+    currMB->mvL0[], currMB->mvL1[]
+    */
+
+AVCEnc_Status AVCMBMotionSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum,
+                                int num_pass)
+{
+    AVCCommonObj *video = encvid->common;
+    int mbPartIdx, subMbPartIdx;
+    int16 *mv;
+    int i;
+    int SubMbPartHeight, SubMbPartWidth, NumSubMbPart;
+
+    /* assign value to currMB->MBPartPredMode[][x],subMbMode[],NumSubMbPart[],SubMbPartWidth[],SubMbPartHeight[] */
+
+    currMB->mbMode = FIXED_INTERPRED_MODE;
+    currMB->mb_intra = 0;
+
+    if (currMB->mbMode == AVC_P16)
+    {
+        currMB->NumMbPart = 1;
+        currMB->MbPartWidth = 16;
+        currMB->MbPartHeight = 16;
+        currMB->SubMbPartHeight[0] = 16;
+        currMB->SubMbPartWidth[0] = 16;
+        currMB->NumSubMbPart[0] =  1;
+    }
+    else if (currMB->mbMode == AVC_P16x8)
+    {
+        currMB->NumMbPart = 2;
+        currMB->MbPartWidth = 16;
+        currMB->MbPartHeight = 8;
+        for (i = 0; i < 2; i++)
+        {
+            currMB->SubMbPartWidth[i] = 16;
+            currMB->SubMbPartHeight[i] = 8;
+            currMB->NumSubMbPart[i] = 1;
+        }
+    }
+    else if (currMB->mbMode == AVC_P8x16)
+    {
+        currMB->NumMbPart = 2;
+        currMB->MbPartWidth = 8;
+        currMB->MbPartHeight = 16;
+        for (i = 0; i < 2; i++)
+        {
+            currMB->SubMbPartWidth[i] = 8;
+            currMB->SubMbPartHeight[i] = 16;
+            currMB->NumSubMbPart[i] = 1;
+        }
+    }
+    else if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0)
+    {
+        currMB->NumMbPart = 4;
+        currMB->MbPartWidth = 8;
+        currMB->MbPartHeight = 8;
+        if (FIXED_SUBMB_MODE == AVC_8x8)
+        {
+            SubMbPartHeight = 8;
+            SubMbPartWidth = 8;
+            NumSubMbPart = 1;
+        }
+        else if (FIXED_SUBMB_MODE == AVC_8x4)
+        {
+            SubMbPartHeight = 4;
+            SubMbPartWidth = 8;
+            NumSubMbPart = 2;
+        }
+        else if (FIXED_SUBMB_MODE == AVC_4x8)
+        {
+            SubMbPartHeight = 8;
+            SubMbPartWidth = 4;
+            NumSubMbPart = 2;
+        }
+        else if (FIXED_SUBMB_MODE == AVC_4x4)
+        {
+            SubMbPartHeight = 4;
+            SubMbPartWidth = 4;
+            NumSubMbPart = 4;
+        }
+
+        for (i = 0; i < 4; i++)
+        {
+            currMB->subMbMode[i] = FIXED_SUBMB_MODE;
+            currMB->SubMbPartHeight[i] = SubMbPartHeight;
+            currMB->SubMbPartWidth[i] = SubMbPartWidth;
+            currMB->NumSubMbPart[i] = NumSubMbPart;
+        }
+    }
+    else /* it's probably intra mode */
+    {
+        return AVCENC_SUCCESS;
+    }
+
+    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+    {
+        currMB->MBPartPredMode[mbPartIdx][0]  = AVC_Pred_L0;
+        currMB->ref_idx_L0[mbPartIdx] = FIXED_REF_IDX;
+        currMB->RefIdx[mbPartIdx] = video->RefPicList0[FIXED_REF_IDX]->RefIdx;
+
+        for (subMbPartIdx = 0; subMbPartIdx < 4; subMbPartIdx++)
+        {
+            mv = (int16*)(currMB->mvL0 + (mbPartIdx << 2) + subMbPartIdx);
+
+            *mv++ = FIXED_MVX;
+            *mv = FIXED_MVY;
+        }
+    }
+
+    encvid->min_cost = 0;
+
+    return AVCENC_SUCCESS;
+}
+
+#else /* perform the search */
+
+/* This option #1 search is very similar to PV's MPEG4 motion search algorithm.
+  The search is done in hierarchical manner from 16x16 MB down to smaller and smaller
+  partition. At each level, a decision can be made to stop the search if the expected
+  prediction gain is not worth the computation. The decision can also be made at the finest
+  level for more fullsearch-like behavior with the price of heavier computation. */
+void AVCMBMotionSearch(AVCEncObject *encvid, uint8 *cur, uint8 *best_cand[],
+                       int i0, int j0, int type_pred, int FS_en, int *hp_guess)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCPictureData *currPic = video->currPic;
+    AVCSeqParamSet *currSPS = video->currSeqParams;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    AVCMacroblock *currMB = video->currMB;
+    uint8 *ref, *cand, *ncand;
+    void *extra_info = encvid->sad_extra_info;
+    int mbnum = video->mbNum;
+    int width = currPic->width; /* 6/12/01, must be multiple of 16 */
+    int height = currPic->height;
+    AVCMV *mot16x16 = encvid->mot16x16;
+    int (*SAD_Macroblock)(uint8*, uint8*, int, void*) = encvid->functionPointer->SAD_Macroblock;
+
+    int range = rateCtrl->mvRange;
+
+    int lx = currPic->pitch; /*  padding */
+    int i, j, imin, jmin, ilow, ihigh, jlow, jhigh;
+    int d, dmin, dn[9];
+    int k;
+    int mvx[5], mvy[5];
+    int num_can, center_again;
+    int last_loc, new_loc = 0;
+    int step, max_step = range >> 1;
+    int next;
+
+    int cmvx, cmvy; /* estimated predicted MV */
+    int lev_idx;
+    int lambda_motion = encvid->lambda_motion;
+    uint8 *mvbits = encvid->mvbits;
+    int mvshift = 2;
+    int mvcost;
+
+    int min_sad = 65535;
+
+    ref = video->RefPicList0[DEFAULT_REF_IDX]->Sl; /* origin of actual frame */
+
+    /* have to initialize these params, necessary for interprediction part */
+    currMB->NumMbPart = 1;
+    currMB->SubMbPartHeight[0] = 16;
+    currMB->SubMbPartWidth[0] = 16;
+    currMB->NumSubMbPart[0] = 1;
+    currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] =
+                                currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = DEFAULT_REF_IDX;
+    currMB->ref_idx_L1[0] = currMB->ref_idx_L1[1] =
+                                currMB->ref_idx_L1[2] = currMB->ref_idx_L1[3] = DEFAULT_REF_IDX;
+    currMB->RefIdx[0] = currMB->RefIdx[1] =
+                            currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[DEFAULT_REF_IDX]->RefIdx;
+
+    cur = encvid->currYMB; /* use smaller memory space for current MB */
+
+    /*  find limit of the search (adjusting search range)*/
+    lev_idx = mapLev2Idx[currSPS->level_idc];
+
+    /* we can make this part dynamic based on previous statistics */
+    ilow = i0 - range;
+    if (i0 - ilow > 2047) /* clip to conform with the standard */
+    {
+        ilow = i0 - 2047;
+    }
+    if (ilow < -13)  // change it from -15 to -13 because of 6-tap filter needs extra 2 lines.
+    {
+        ilow = -13;
+    }
+
+    ihigh = i0 + range - 1;
+    if (ihigh - i0 > 2047) /* clip to conform with the standard */
+    {
+        ihigh = i0 + 2047;
+    }
+    if (ihigh > width - 3)
+    {
+        ihigh = width - 3;  // change from width-1 to width-3 for the same reason as above
+    }
+
+    jlow = j0 - range;
+    if (j0 - jlow > MaxVmvR[lev_idx] - 1) /* clip to conform with the standard */
+    {
+        jlow = j0 - MaxVmvR[lev_idx] + 1;
+    }
+    if (jlow < -13)     // same reason as above
+    {
+        jlow = -13;
+    }
+
+    jhigh = j0 + range - 1;
+    if (jhigh - j0 > MaxVmvR[lev_idx] - 1) /* clip to conform with the standard */
+    {
+        jhigh = j0 + MaxVmvR[lev_idx] - 1;
+    }
+    if (jhigh > height - 3) // same reason as above
+    {
+        jhigh = height - 3;
+    }
+
+    /* find initial motion vector & predicted MV*/
+    AVCCandidateSelection(mvx, mvy, &num_can, i0 >> 4, j0 >> 4, encvid, type_pred, &cmvx, &cmvy);
+
+    imin = i0;
+    jmin = j0; /* needed for fullsearch */
+    ncand = ref + i0 + j0 * lx;
+
+    /* for first row of MB, fullsearch can be used */
+    if (FS_en)
+    {
+        *hp_guess = 0; /* no guess for fast half-pel */
+
+        dmin =  AVCFullSearch(encvid, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh, cmvx, cmvy);
+
+        ncand = ref + imin + jmin * lx;
+    }
+    else
+    {   /*       fullsearch the top row to only upto (0,3) MB */
+        /*       upto 30% complexity saving with the same complexity */
+        if (video->PrevRefFrameNum == 0 && j0 == 0 && i0 <= 64 && type_pred != 1)
+        {
+            *hp_guess = 0; /* no guess for fast half-pel */
+            dmin =  AVCFullSearch(encvid, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh, cmvx, cmvy);
+            ncand = ref + imin + jmin * lx;
+        }
+        else
+        {
+            /************** initialize candidate **************************/
+
+            dmin = 65535;
+
+            /* check if all are equal */
+            if (num_can == ALL_CAND_EQUAL)
+            {
+                i = i0 + mvx[0];
+                j = j0 + mvy[0];
+
+                if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+                {
+                    cand = ref + i + j * lx;
+
+                    d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+                    mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
+                    d +=  mvcost;
+
+                    if (d < dmin)
+                    {
+                        dmin = d;
+                        imin = i;
+                        jmin = j;
+                        ncand = cand;
+                        min_sad = d - mvcost; // for rate control
+                    }
+                }
+            }
+            else
+            {
+                /************** evaluate unique candidates **********************/
+                for (k = 0; k < num_can; k++)
+                {
+                    i = i0 + mvx[k];
+                    j = j0 + mvy[k];
+
+                    if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+                    {
+                        cand = ref + i + j * lx;
+                        d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+                        mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
+                        d +=  mvcost;
+
+                        if (d < dmin)
+                        {
+                            dmin = d;
+                            imin = i;
+                            jmin = j;
+                            ncand = cand;
+                            min_sad = d - mvcost; // for rate control
+                        }
+                    }
+                }
+            }
+
+            /******************* local refinement ***************************/
+            center_again = 0;
+            last_loc = new_loc = 0;
+            //          ncand = ref + jmin*lx + imin;  /* center of the search */
+            step = 0;
+            dn[0] = dmin;
+            while (!center_again && step <= max_step)
+            {
+
+                AVCMoveNeighborSAD(dn, last_loc);
+
+                center_again = 1;
+                i = imin;
+                j = jmin - 1;
+                cand = ref + i + j * lx;
+
+                /*  starting from [0,-1] */
+                /* spiral check one step at a time*/
+                for (k = 2; k <= 8; k += 2)
+                {
+                    if (!tab_exclude[last_loc][k]) /* exclude last step computation */
+                    {       /* not already computed */
+                        if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+                        {
+                            d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+                            mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
+                            d += mvcost;
+
+                            dn[k] = d; /* keep it for half pel use */
+
+                            if (d < dmin)
+                            {
+                                ncand = cand;
+                                dmin = d;
+                                imin = i;
+                                jmin = j;
+                                center_again = 0;
+                                new_loc = k;
+                                min_sad = d - mvcost; // for rate control
+                            }
+                        }
+                    }
+                    if (k == 8)  /* end side search*/
+                    {
+                        if (!center_again)
+                        {
+                            k = -1; /* start diagonal search */
+                            cand -= lx;
+                            j--;
+                        }
+                    }
+                    else
+                    {
+                        next = refine_next[k][0];
+                        i += next;
+                        cand += next;
+                        next = refine_next[k][1];
+                        j += next;
+                        cand += lx * next;
+                    }
+                }
+                last_loc = new_loc;
+                step ++;
+            }
+            if (!center_again)
+                AVCMoveNeighborSAD(dn, last_loc);
+
+            *hp_guess = AVCFindMin(dn);
+
+            encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
+        }
+    }
+
+    mot16x16[mbnum].sad = dmin;
+    mot16x16[mbnum].x = (imin - i0) << 2;
+    mot16x16[mbnum].y = (jmin - j0) << 2;
+    best_cand[0] = ncand;
+
+    if (rateCtrl->subPelEnable) // always enable half-pel search
+    {
+        /* find half-pel resolution motion vector */
+        min_sad = AVCFindHalfPelMB(encvid, cur, mot16x16 + mbnum, best_cand[0], i0, j0, *hp_guess, cmvx, cmvy);
+
+        encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
+
+
+        if (encvid->best_qpel_pos == -1)
+        {
+            ncand = encvid->hpel_cand[encvid->best_hpel_pos];
+        }
+        else
+        {
+            ncand = encvid->qpel_cand[encvid->best_qpel_pos];
+        }
+    }
+    else
+    {
+        encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
+    }
+
+    /** do motion comp here for now */
+    ref = currPic->Sl + i0 + j0 * lx;
+    /* copy from the best result to current Picture */
+    for (j = 0; j < 16; j++)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            *ref++ = *ncand++;
+        }
+        ref += (lx - 16);
+        ncand += 8;
+    }
+
+    return ;
+}
+
+#endif
+
+/*===============================================================================
+    Function:   AVCFullSearch
+    Date:       09/16/2000
+    Purpose:    Perform full-search motion estimation over the range of search
+                region in a spiral-outward manner.
+    Input/Output:   VideoEncData, current Vol, previou Vop, pointer to the left corner of
+                current VOP, current coord (also output), boundaries.
+===============================================================================*/
+int AVCFullSearch(AVCEncObject *encvid, uint8 *prev, uint8 *cur,
+                  int *imin, int *jmin, int ilow, int ihigh, int jlow, int jhigh,
+                  int cmvx, int cmvy)
+{
+    int range = encvid->rateCtrl->mvRange;
+    AVCPictureData *currPic = encvid->common->currPic;
+    uint8 *cand;
+    int i, j, k, l;
+    int d, dmin;
+    int i0 = *imin; /* current position */
+    int j0 = *jmin;
+    int (*SAD_Macroblock)(uint8*, uint8*, int, void*) = encvid->functionPointer->SAD_Macroblock;
+    void *extra_info = encvid->sad_extra_info;
+    int lx = currPic->pitch; /* with padding */
+
+    int offset = i0 + j0 * lx;
+
+    int lambda_motion = encvid->lambda_motion;
+    uint8 *mvbits = encvid->mvbits;
+    int mvshift = 2;
+    int mvcost;
+    int min_sad;
+
+    cand = prev + offset;
+
+    dmin  = (*SAD_Macroblock)(cand, cur, (65535 << 16) | lx, (void*)extra_info);
+    mvcost = MV_COST(lambda_motion, mvshift, 0, 0, cmvx, cmvy);
+    min_sad = dmin;
+    dmin += mvcost;
+
+    /* perform spiral search */
+    for (k = 1; k <= range; k++)
+    {
+
+        i = i0 - k;
+        j = j0 - k;
+
+        cand = prev + i + j * lx;
+
+        for (l = 0; l < 8*k; l++)
+        {
+            /* no need for boundary checking again */
+            if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+            {
+                d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, (void*)extra_info);
+                mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
+                d +=  mvcost;
+
+                if (d < dmin)
+                {
+                    dmin = d;
+                    *imin = i;
+                    *jmin = j;
+                    min_sad = d - mvcost;
+                }
+            }
+
+            if (l < (k << 1))
+            {
+                i++;
+                cand++;
+            }
+            else if (l < (k << 2))
+            {
+                j++;
+                cand += lx;
+            }
+            else if (l < ((k << 2) + (k << 1)))
+            {
+                i--;
+                cand--;
+            }
+            else
+            {
+                j--;
+                cand -= lx;
+            }
+        }
+    }
+
+    encvid->rateCtrl->MADofMB[encvid->common->mbNum] = (min_sad / 256.0); // for rate control
+
+    return dmin;
+}
+
+/*===============================================================================
+    Function:   AVCCandidateSelection
+    Date:       09/16/2000
+    Purpose:    Fill up the list of candidate using spatio-temporal correlation
+                among neighboring blocks.
+    Input/Output:   type_pred = 0: first pass, 1: second pass, or no SCD
+    Modified:   , 09/23/01, get rid of redundant candidates before passing back.
+                , 09/11/07, added return for modified predicted MV, this will be
+                    needed for both fast search and fullsearch.
+===============================================================================*/
+
+void AVCCandidateSelection(int *mvx, int *mvy, int *num_can, int imb, int jmb,
+                           AVCEncObject *encvid, int type_pred, int *cmvx, int *cmvy)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCMV *mot16x16 = encvid->mot16x16;
+    AVCMV *pmot;
+    int mbnum = video->mbNum;
+    int mbwidth = video->PicWidthInMbs;
+    int mbheight = video->PicHeightInMbs;
+    int i, j, same, num1;
+
+    /* this part is for predicted MV */
+    int pmvA_x = 0, pmvA_y = 0, pmvB_x = 0, pmvB_y = 0, pmvC_x = 0, pmvC_y = 0;
+    int availA = 0, availB = 0, availC = 0;
+
+    *num_can = 0;
+
+    if (video->PrevRefFrameNum != 0) // previous frame is an IDR frame
+    {
+        /* Spatio-Temporal Candidate (five candidates) */
+        if (type_pred == 0) /* first pass */
+        {
+            pmot = &mot16x16[mbnum]; /* same coordinate previous frame */
+            mvx[(*num_can)] = (pmot->x) >> 2;
+            mvy[(*num_can)++] = (pmot->y) >> 2;
+            if (imb >= (mbwidth >> 1) && imb > 0)  /*left neighbor previous frame */
+            {
+                pmot = &mot16x16[mbnum-1];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+            else if (imb + 1 < mbwidth)   /*right neighbor previous frame */
+            {
+                pmot = &mot16x16[mbnum+1];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+
+            if (jmb < mbheight - 1)  /*bottom neighbor previous frame */
+            {
+                pmot = &mot16x16[mbnum+mbwidth];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+            else if (jmb > 0)   /*upper neighbor previous frame */
+            {
+                pmot = &mot16x16[mbnum-mbwidth];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+
+            if (imb > 0 && jmb > 0)  /* upper-left neighbor current frame*/
+            {
+                pmot = &mot16x16[mbnum-mbwidth-1];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+            if (jmb > 0 && imb < mbheight - 1)  /* upper right neighbor current frame*/
+            {
+                pmot = &mot16x16[mbnum-mbwidth+1];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+        }
+        else    /* second pass */
+            /* original ST1 algorithm */
+        {
+            pmot = &mot16x16[mbnum]; /* same coordinate previous frame */
+            mvx[(*num_can)] = (pmot->x) >> 2;
+            mvy[(*num_can)++] = (pmot->y) >> 2;
+
+            if (imb > 0)  /*left neighbor current frame */
+            {
+                pmot = &mot16x16[mbnum-1];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+            if (jmb > 0)  /*upper neighbor current frame */
+            {
+                pmot = &mot16x16[mbnum-mbwidth];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+            if (imb < mbwidth - 1)  /*right neighbor previous frame */
+            {
+                pmot = &mot16x16[mbnum+1];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+            if (jmb < mbheight - 1)  /*bottom neighbor previous frame */
+            {
+                pmot = &mot16x16[mbnum+mbwidth];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+        }
+
+        /* get predicted MV */
+        if (imb > 0)    /* get MV from left (A) neighbor either on current or previous frame */
+        {
+            availA = 1;
+            pmot = &mot16x16[mbnum-1];
+            pmvA_x = pmot->x;
+            pmvA_y = pmot->y;
+        }
+
+        if (jmb > 0) /* get MV from top (B) neighbor either on current or previous frame */
+        {
+            availB = 1;
+            pmot = &mot16x16[mbnum-mbwidth];
+            pmvB_x = pmot->x;
+            pmvB_y = pmot->y;
+
+            availC = 1;
+
+            if (imb < mbwidth - 1) /* get MV from top-right (C) neighbor of current frame */
+            {
+                pmot = &mot16x16[mbnum-mbwidth+1];
+            }
+            else /* get MV from top-left (D) neighbor of current frame */
+            {
+                pmot = &mot16x16[mbnum-mbwidth-1];
+            }
+            pmvC_x = pmot->x;
+            pmvC_y = pmot->y;
+        }
+
+    }
+    else  /* only Spatial Candidate (four candidates)*/
+    {
+        if (type_pred == 0) /*first pass*/
+        {
+            if (imb > 1)  /* neighbor two blocks away to the left */
+            {
+                pmot = &mot16x16[mbnum-2];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+            if (imb > 0 && jmb > 0)  /* upper-left neighbor */
+            {
+                pmot = &mot16x16[mbnum-mbwidth-1];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+            if (jmb > 0 && imb < mbheight - 1)  /* upper right neighbor */
+            {
+                pmot = &mot16x16[mbnum-mbwidth+1];
+                mvx[(*num_can)] = (pmot->x) >> 2;
+                mvy[(*num_can)++] = (pmot->y) >> 2;
+            }
+
+            /* get predicted MV */
+            if (imb > 1)    /* get MV from 2nd left (A) neighbor either of current frame */
+            {
+                availA = 1;
+                pmot = &mot16x16[mbnum-2];
+                pmvA_x = pmot->x;
+                pmvA_y = pmot->y;
+            }
+
+            if (jmb > 0 && imb > 0) /* get MV from top-left (B) neighbor of current frame */
+            {
+                availB = 1;
+                pmot = &mot16x16[mbnum-mbwidth-1];
+                pmvB_x = pmot->x;
+                pmvB_y = pmot->y;
+            }
+
+            if (jmb > 0 && imb < mbwidth - 1)
+            {
+                availC = 1;
+                pmot = &mot16x16[mbnum-mbwidth+1];
+                pmvC_x = pmot->x;
+                pmvC_y = pmot->y;
+            }
+        }
+//#ifdef SCENE_CHANGE_DETECTION
+        /* second pass (ST2 algorithm)*/
+        else
+        {
+            if (type_pred == 1) /*  4/7/01 */
+            {
+                if (imb > 0)  /*left neighbor current frame */
+                {
+                    pmot = &mot16x16[mbnum-1];
+                    mvx[(*num_can)] = (pmot->x) >> 2;
+                    mvy[(*num_can)++] = (pmot->y) >> 2;
+                }
+                if (jmb > 0)  /*upper neighbor current frame */
+                {
+                    pmot = &mot16x16[mbnum-mbwidth];
+                    mvx[(*num_can)] = (pmot->x) >> 2;
+                    mvy[(*num_can)++] = (pmot->y) >> 2;
+                }
+                if (imb < mbwidth - 1)  /*right neighbor current frame */
+                {
+                    pmot = &mot16x16[mbnum+1];
+                    mvx[(*num_can)] = (pmot->x) >> 2;
+                    mvy[(*num_can)++] = (pmot->y) >> 2;
+                }
+                if (jmb < mbheight - 1)  /*bottom neighbor current frame */
+                {
+                    pmot = &mot16x16[mbnum+mbwidth];
+                    mvx[(*num_can)] = (pmot->x) >> 2;
+                    mvy[(*num_can)++] = (pmot->y) >> 2;
+                }
+            }
+            //#else
+            else /* original ST1 algorithm */
+            {
+                if (imb > 0)  /*left neighbor current frame */
+                {
+                    pmot = &mot16x16[mbnum-1];
+                    mvx[(*num_can)] = (pmot->x) >> 2;
+                    mvy[(*num_can)++] = (pmot->y) >> 2;
+
+                    if (jmb > 0)  /*upper-left neighbor current frame */
+                    {
+                        pmot = &mot16x16[mbnum-mbwidth-1];
+                        mvx[(*num_can)] = (pmot->x) >> 2;
+                        mvy[(*num_can)++] = (pmot->y) >> 2;
+                    }
+
+                }
+                if (jmb > 0)  /*upper neighbor current frame */
+                {
+                    pmot = &mot16x16[mbnum-mbwidth];
+                    mvx[(*num_can)] = (pmot->x) >> 2;
+                    mvy[(*num_can)++] = (pmot->y) >> 2;
+
+                    if (imb < mbheight - 1)  /*upper-right neighbor current frame */
+                    {
+                        pmot = &mot16x16[mbnum-mbwidth+1];
+                        mvx[(*num_can)] = (pmot->x) >> 2;
+                        mvy[(*num_can)++] = (pmot->y) >> 2;
+                    }
+                }
+            }
+
+            /* get predicted MV */
+            if (imb > 0)    /* get MV from left (A) neighbor either on current or previous frame */
+            {
+                availA = 1;
+                pmot = &mot16x16[mbnum-1];
+                pmvA_x = pmot->x;
+                pmvA_y = pmot->y;
+            }
+
+            if (jmb > 0) /* get MV from top (B) neighbor either on current or previous frame */
+            {
+                availB = 1;
+                pmot = &mot16x16[mbnum-mbwidth];
+                pmvB_x = pmot->x;
+                pmvB_y = pmot->y;
+
+                availC = 1;
+
+                if (imb < mbwidth - 1) /* get MV from top-right (C) neighbor of current frame */
+                {
+                    pmot = &mot16x16[mbnum-mbwidth+1];
+                }
+                else /* get MV from top-left (D) neighbor of current frame */
+                {
+                    pmot = &mot16x16[mbnum-mbwidth-1];
+                }
+                pmvC_x = pmot->x;
+                pmvC_y = pmot->y;
+            }
+        }
+//#endif
+    }
+
+    /*  3/23/01, remove redundant candidate (possible k-mean) */
+    num1 = *num_can;
+    *num_can = 1;
+    for (i = 1; i < num1; i++)
+    {
+        same = 0;
+        j = 0;
+        while (!same && j < *num_can)
+        {
+#if (CANDIDATE_DISTANCE==0)
+            if (mvx[i] == mvx[j] && mvy[i] == mvy[j])
+#else
+            // modified k-mean,  3/24/01, shouldn't be greater than 3
+            if (AVC_ABS(mvx[i] - mvx[j]) + AVC_ABS(mvy[i] - mvy[j]) < CANDIDATE_DISTANCE)
+#endif
+                same = 1;
+            j++;
+        }
+        if (!same)
+        {
+            mvx[*num_can] = mvx[i];
+            mvy[*num_can] = mvy[i];
+            (*num_can)++;
+        }
+    }
+
+    if (num1 == 5 && *num_can == 1)
+        *num_can = ALL_CAND_EQUAL; /* all are equal */
+
+    /* calculate predicted MV */
+
+    if (availA && !(availB || availC))
+    {
+        *cmvx = pmvA_x;
+        *cmvy = pmvA_y;
+    }
+    else
+    {
+        *cmvx = AVC_MEDIAN(pmvA_x, pmvB_x, pmvC_x);
+        *cmvy = AVC_MEDIAN(pmvA_y, pmvB_y, pmvC_y);
+    }
+
+    return ;
+}
+
+
+/*************************************************************
+    Function:   AVCMoveNeighborSAD
+    Date:       3/27/01
+    Purpose:    Move neighboring SAD around when center has shifted
+*************************************************************/
+
+void AVCMoveNeighborSAD(int dn[], int new_loc)
+{
+    int tmp[9];
+    tmp[0] = dn[0];
+    tmp[1] = dn[1];
+    tmp[2] = dn[2];
+    tmp[3] = dn[3];
+    tmp[4] = dn[4];
+    tmp[5] = dn[5];
+    tmp[6] = dn[6];
+    tmp[7] = dn[7];
+    tmp[8] = dn[8];
+    dn[0] = dn[1] = dn[2] = dn[3] = dn[4] = dn[5] = dn[6] = dn[7] = dn[8] = 65536;
+
+    switch (new_loc)
+    {
+        case 0:
+            break;
+        case 1:
+            dn[4] = tmp[2];
+            dn[5] = tmp[0];
+            dn[6] = tmp[8];
+            break;
+        case 2:
+            dn[4] = tmp[3];
+            dn[5] = tmp[4];
+            dn[6] = tmp[0];
+            dn[7] = tmp[8];
+            dn[8] = tmp[1];
+            break;
+        case 3:
+            dn[6] = tmp[4];
+            dn[7] = tmp[0];
+            dn[8] = tmp[2];
+            break;
+        case 4:
+            dn[1] = tmp[2];
+            dn[2] = tmp[3];
+            dn[6] = tmp[5];
+            dn[7] = tmp[6];
+            dn[8] = tmp[0];
+            break;
+        case 5:
+            dn[1] = tmp[0];
+            dn[2] = tmp[4];
+            dn[8] = tmp[6];
+            break;
+        case 6:
+            dn[1] = tmp[8];
+            dn[2] = tmp[0];
+            dn[3] = tmp[4];
+            dn[4] = tmp[5];
+            dn[8] = tmp[7];
+            break;
+        case 7:
+            dn[2] = tmp[8];
+            dn[3] = tmp[0];
+            dn[4] = tmp[6];
+            break;
+        case 8:
+            dn[2] = tmp[1];
+            dn[3] = tmp[2];
+            dn[4] = tmp[0];
+            dn[5] = tmp[6];
+            dn[6] = tmp[7];
+            break;
+    }
+    dn[0] = tmp[new_loc];
+
+    return ;
+}
+
+/*  3/28/01, find minimal of dn[9] */
+
+int AVCFindMin(int dn[])
+{
+    int min, i;
+    int dmin;
+
+    dmin = dn[1];
+    min = 1;
+    for (i = 2; i < 9; i++)
+    {
+        if (dn[i] < dmin)
+        {
+            dmin = dn[i];
+            min = i;
+        }
+    }
+
+    return min;
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/rate_control.cpp b/media/libstagefright/codecs/avc/enc/src/rate_control.cpp
new file mode 100644
index 0000000..15b55fb
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/rate_control.cpp
@@ -0,0 +1,981 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include <math.h>
+
+/* rate control variables */
+#define RC_MAX_QUANT 51
+#define RC_MIN_QUANT 0   //cap to 10 to prevent rate fluctuation    
+
+#define MAD_MIN 1 /* handle the case of devision by zero in RC */
+
+
+/* local functions */
+double QP2Qstep(int QP);
+int Qstep2QP(double Qstep);
+
+double ComputeFrameMAD(AVCCommonObj *video, AVCRateControl *rateCtrl);
+
+void targetBitCalculation(AVCEncObject *encvid, AVCCommonObj *video, AVCRateControl *rateCtrl, MultiPass *pMP);
+
+void calculateQuantizer_Multipass(AVCEncObject *encvid, AVCCommonObj *video,
+                                  AVCRateControl *rateCtrl, MultiPass *pMP);
+
+void updateRC_PostProc(AVCRateControl *rateCtrl, MultiPass *pMP);
+
+void AVCSaveRDSamples(MultiPass *pMP, int counter_samples);
+
+void updateRateControl(AVCRateControl *rateControl, int nal_type);
+
+int GetAvgFrameQP(AVCRateControl *rateCtrl)
+{
+    return rateCtrl->Qc;
+}
+
+AVCEnc_Status RCDetermineFrameNum(AVCEncObject *encvid, AVCRateControl *rateCtrl, uint32 modTime, uint *frameNum)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    uint32 modTimeRef = encvid->modTimeRef;
+    int32  currFrameNum ;
+    int  frameInc;
+
+
+    /* check with the buffer fullness to make sure that we have enough bits to encode this frame */
+    /* we can use a threshold to guarantee minimum picture quality */
+    /**********************************/
+
+    /* for now, the default is to encode every frame, To Be Changed */
+    if (rateCtrl->first_frame)
+    {
+        encvid->modTimeRef = modTime;
+        encvid->wrapModTime = 0;
+        encvid->prevFrameNum = 0;
+        encvid->prevProcFrameNum = 0;
+
+        *frameNum = 0;
+
+        /* set frame type to IDR-frame */
+        video->nal_unit_type = AVC_NALTYPE_IDR;
+        sliceHdr->slice_type = AVC_I_ALL_SLICE;
+        video->slice_type = AVC_I_SLICE;
+
+        return AVCENC_SUCCESS;
+    }
+    else
+    {
+        if (modTime < modTimeRef) /* modTime wrapped around */
+        {
+            encvid->wrapModTime += ((uint32)0xFFFFFFFF - modTimeRef) + 1;
+            encvid->modTimeRef = modTimeRef = 0;
+        }
+        modTime += encvid->wrapModTime; /* wrapModTime is non zero after wrap-around */
+
+        currFrameNum = (int32)(((modTime - modTimeRef) * rateCtrl->frame_rate + 200) / 1000); /* add small roundings */
+
+        if (currFrameNum <= (int32)encvid->prevProcFrameNum)
+        {
+            return AVCENC_FAIL;  /* this is a late frame do not encode it */
+        }
+
+        frameInc = currFrameNum - encvid->prevProcFrameNum;
+
+        if (frameInc < rateCtrl->skip_next_frame + 1)
+        {
+            return AVCENC_FAIL;  /* frame skip required to maintain the target bit rate. */
+        }
+
+        RCUpdateBuffer(video, rateCtrl, frameInc - rateCtrl->skip_next_frame);  /* in case more frames dropped */
+
+        *frameNum = currFrameNum;
+
+        /* This part would be similar to DetermineVopType of m4venc */
+        if ((*frameNum >= (uint)rateCtrl->idrPeriod && rateCtrl->idrPeriod > 0) || (*frameNum > video->MaxFrameNum)) /* first frame or IDR*/
+        {
+            /* set frame type to IDR-frame */
+            if (rateCtrl->idrPeriod)
+            {
+                encvid->modTimeRef += (uint32)(rateCtrl->idrPeriod * 1000 / rateCtrl->frame_rate);
+                *frameNum -= rateCtrl->idrPeriod;
+            }
+            else
+            {
+                encvid->modTimeRef += (uint32)(video->MaxFrameNum * 1000 / rateCtrl->frame_rate);
+                *frameNum -= video->MaxFrameNum;
+            }
+
+            video->nal_unit_type = AVC_NALTYPE_IDR;
+            sliceHdr->slice_type = AVC_I_ALL_SLICE;
+            video->slice_type = AVC_I_SLICE;
+            encvid->prevProcFrameNum = *frameNum;
+        }
+        else
+        {
+            video->nal_unit_type = AVC_NALTYPE_SLICE;
+            sliceHdr->slice_type = AVC_P_ALL_SLICE;
+            video->slice_type = AVC_P_SLICE;
+            encvid->prevProcFrameNum = currFrameNum;
+        }
+
+    }
+
+    return AVCENC_SUCCESS;
+}
+
+void RCUpdateBuffer(AVCCommonObj *video, AVCRateControl *rateCtrl, int frameInc)
+{
+    int tmp;
+    MultiPass *pMP = rateCtrl->pMP;
+
+    OSCL_UNUSED_ARG(video);
+
+    if (rateCtrl->rcEnable == TRUE)
+    {
+        if (frameInc > 1)
+        {
+            tmp = rateCtrl->bitsPerFrame * (frameInc - 1);
+            rateCtrl->VBV_fullness -= tmp;
+            pMP->counter_BTsrc += 10 * (frameInc - 1);
+
+            /* Check buffer underflow */
+            if (rateCtrl->VBV_fullness < rateCtrl->low_bound)
+            {
+                rateCtrl->VBV_fullness = rateCtrl->low_bound; // -rateCtrl->Bs/2;
+                rateCtrl->TMN_W = rateCtrl->VBV_fullness - rateCtrl->low_bound;
+                pMP->counter_BTsrc = pMP->counter_BTdst + (int)((OsclFloat)(rateCtrl->Bs / 2 - rateCtrl->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+            }
+        }
+    }
+}
+
+
+AVCEnc_Status InitRateControlModule(AVCHandle *avcHandle)
+{
+    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+    AVCCommonObj *video = encvid->common;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    double L1, L2, L3, bpp;
+    int qp;
+    int i, j;
+
+    rateCtrl->basicUnit = video->PicSizeInMbs;
+
+    rateCtrl->MADofMB = (double*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
+                        video->PicSizeInMbs * sizeof(double), DEFAULT_ATTR);
+
+    if (!rateCtrl->MADofMB)
+    {
+        goto CLEANUP_RC;
+    }
+
+    if (rateCtrl->rcEnable == TRUE)
+    {
+        rateCtrl->pMP = (MultiPass*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, sizeof(MultiPass), DEFAULT_ATTR);
+        if (!rateCtrl->pMP)
+        {
+            goto CLEANUP_RC;
+        }
+        memset(rateCtrl->pMP, 0, sizeof(MultiPass));
+        rateCtrl->pMP->encoded_frames = -1; /* forget about the very first I frame */
+
+        /* RDInfo **pRDSamples */
+        rateCtrl->pMP->pRDSamples = (RDInfo **)avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, (30 * sizeof(RDInfo *)), DEFAULT_ATTR);
+        if (!rateCtrl->pMP->pRDSamples)
+        {
+            goto CLEANUP_RC;
+        }
+
+        for (i = 0; i < 30; i++)
+        {
+            rateCtrl->pMP->pRDSamples[i] = (RDInfo *)avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, (32 * sizeof(RDInfo)), DEFAULT_ATTR);
+            if (!rateCtrl->pMP->pRDSamples[i])
+            {
+                goto CLEANUP_RC;
+            }
+            for (j = 0; j < 32; j++)    memset(&(rateCtrl->pMP->pRDSamples[i][j]), 0, sizeof(RDInfo));
+        }
+        rateCtrl->pMP->frameRange = (int)(rateCtrl->frame_rate * 1.0); /* 1.0s time frame*/
+        rateCtrl->pMP->frameRange = AVC_MAX(rateCtrl->pMP->frameRange, 5);
+        rateCtrl->pMP->frameRange = AVC_MIN(rateCtrl->pMP->frameRange, 30);
+
+        rateCtrl->pMP->framePos = -1;
+
+
+        rateCtrl->bitsPerFrame = (int32)(rateCtrl->bitRate / rateCtrl->frame_rate);
+
+        /* BX rate control */
+        rateCtrl->skip_next_frame = 0; /* must be initialized */
+
+        rateCtrl->Bs = rateCtrl->cpbSize;
+        rateCtrl->TMN_W = 0;
+        rateCtrl->VBV_fullness = (int)(rateCtrl->Bs * 0.5); /* rateCtrl->Bs */
+        rateCtrl->encoded_frames = 0;
+
+        rateCtrl->TMN_TH = rateCtrl->bitsPerFrame;
+
+        rateCtrl->max_BitVariance_num = (int)((OsclFloat)(rateCtrl->Bs - rateCtrl->VBV_fullness) / (rateCtrl->bitsPerFrame / 10.0)) - 5;
+        if (rateCtrl->max_BitVariance_num < 0) rateCtrl->max_BitVariance_num += 5;
+
+        // Set the initial buffer fullness
+        /* According to the spec, the initial buffer fullness needs to be set to 1/3 */
+        rateCtrl->VBV_fullness = (int)(rateCtrl->Bs / 3.0 - rateCtrl->Bs / 2.0); /* the buffer range is [-Bs/2, Bs/2] */
+        rateCtrl->pMP->counter_BTsrc = (int)((rateCtrl->Bs / 2.0 - rateCtrl->Bs / 3.0) / (rateCtrl->bitsPerFrame / 10.0));
+        rateCtrl->TMN_W = (int)(rateCtrl->VBV_fullness + rateCtrl->pMP->counter_BTsrc * (rateCtrl->bitsPerFrame / 10.0));
+
+        rateCtrl->low_bound = -rateCtrl->Bs / 2;
+        rateCtrl->VBV_fullness_offset = 0;
+
+        /* Setting the bitrate and framerate */
+        rateCtrl->pMP->bitrate = rateCtrl->bitRate;
+        rateCtrl->pMP->framerate = rateCtrl->frame_rate;
+        rateCtrl->pMP->target_bits_per_frame = rateCtrl->pMP->bitrate / rateCtrl->pMP->framerate;
+
+        /*compute the initial QP*/
+        bpp = 1.0 * rateCtrl->bitRate / (rateCtrl->frame_rate * (video->PicSizeInMbs << 8));
+        if (video->PicWidthInSamplesL == 176)
+        {
+            L1 = 0.1;
+            L2 = 0.3;
+            L3 = 0.6;
+        }
+        else if (video->PicWidthInSamplesL == 352)
+        {
+            L1 = 0.2;
+            L2 = 0.6;
+            L3 = 1.2;
+        }
+        else
+        {
+            L1 = 0.6;
+            L2 = 1.4;
+            L3 = 2.4;
+        }
+
+        if (rateCtrl->initQP == 0)
+        {
+            if (bpp <= L1)
+                qp = 35;
+            else if (bpp <= L2)
+                qp = 25;
+            else if (bpp <= L3)
+                qp = 20;
+            else
+                qp = 15;
+            rateCtrl->initQP = qp;
+        }
+
+        rateCtrl->Qc = rateCtrl->initQP;
+    }
+
+    return AVCENC_SUCCESS;
+
+CLEANUP_RC:
+
+    CleanupRateControlModule(avcHandle);
+    return AVCENC_MEMORY_FAIL;
+
+}
+
+
+void CleanupRateControlModule(AVCHandle *avcHandle)
+{
+    AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    int i;
+
+    if (rateCtrl->MADofMB)
+    {
+        avcHandle->CBAVC_Free(avcHandle->userData, (int)(rateCtrl->MADofMB));
+    }
+
+    if (rateCtrl->pMP)
+    {
+        if (rateCtrl->pMP->pRDSamples)
+        {
+            for (i = 0; i < 30; i++)
+            {
+                if (rateCtrl->pMP->pRDSamples[i])
+                {
+                    avcHandle->CBAVC_Free(avcHandle->userData, (int)rateCtrl->pMP->pRDSamples[i]);
+                }
+            }
+            avcHandle->CBAVC_Free(avcHandle->userData, (int)rateCtrl->pMP->pRDSamples);
+        }
+        avcHandle->CBAVC_Free(avcHandle->userData, (int)(rateCtrl->pMP));
+    }
+
+    return ;
+}
+
+void RCInitGOP(AVCEncObject *encvid)
+{
+    /* in BX RC, there's no GOP-level RC */
+
+    OSCL_UNUSED_ARG(encvid);
+
+    return ;
+}
+
+
+void RCInitFrameQP(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    AVCPicParamSet *picParam = video->currPicParams;
+    MultiPass *pMP = rateCtrl->pMP;
+
+    if (rateCtrl->rcEnable == TRUE)
+    {
+        /* frame layer rate control */
+        if (rateCtrl->encoded_frames == 0)
+        {
+            video->QPy = rateCtrl->Qc = rateCtrl->initQP;
+        }
+        else
+        {
+            calculateQuantizer_Multipass(encvid, video, rateCtrl, pMP);
+            video->QPy = rateCtrl->Qc;
+        }
+
+        rateCtrl->NumberofHeaderBits = 0;
+        rateCtrl->NumberofTextureBits = 0;
+        rateCtrl->numFrameBits = 0; // reset
+
+        /* update pMP->framePos */
+        if (++pMP->framePos == pMP->frameRange) pMP->framePos = 0;
+
+        if (rateCtrl->T == 0)
+        {
+            pMP->counter_BTdst = (int)(rateCtrl->frame_rate * 7.5 + 0.5); /* 0.75s time frame */
+            pMP->counter_BTdst = AVC_MIN(pMP->counter_BTdst, (int)(rateCtrl->max_BitVariance_num / 2 * 0.40)); /* 0.75s time frame may go beyond VBV buffer if we set the buffer size smaller than 0.75s */
+            pMP->counter_BTdst = AVC_MAX(pMP->counter_BTdst, (int)((rateCtrl->Bs / 2 - rateCtrl->VBV_fullness) * 0.30 / (rateCtrl->TMN_TH / 10.0) + 0.5)); /* At least 30% of VBV buffer size/2 */
+            pMP->counter_BTdst = AVC_MIN(pMP->counter_BTdst, 20); /* Limit the target to be smaller than 3C */
+
+            pMP->target_bits = rateCtrl->T = rateCtrl->TMN_TH = (int)(rateCtrl->TMN_TH * (1.0 + pMP->counter_BTdst * 0.1));
+            pMP->diff_counter = pMP->counter_BTdst;
+        }
+
+        /* collect the necessary data: target bits, actual bits, mad and QP */
+        pMP->target_bits = rateCtrl->T;
+        pMP->QP  = video->QPy;
+
+        pMP->mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs; //ComputeFrameMAD(video, rateCtrl);
+        if (pMP->mad < MAD_MIN) pMP->mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+
+        pMP->bitrate = rateCtrl->bitRate; /* calculated in RCVopQPSetting */
+        pMP->framerate = rateCtrl->frame_rate;
+
+        /* first pass encoding */
+        pMP->nRe_Quantized = 0;
+
+    } // rcEnable
+    else
+    {
+        video->QPy = rateCtrl->initQP;
+    }
+
+//  printf(" %d ",video->QPy);
+
+    if (video->CurrPicNum == 0 && encvid->outOfBandParamSet == FALSE)
+    {
+        picParam->pic_init_qs_minus26 = 0;
+        picParam->pic_init_qp_minus26 = video->QPy - 26;
+    }
+
+    // need this for motion estimation
+    encvid->lambda_mode = QP2QUANT[AVC_MAX(0, video->QPy-SHIFT_QP)];
+    encvid->lambda_motion = LAMBDA_FACTOR(encvid->lambda_mode);
+    return ;
+}
+
+/* Mad based variable bit allocation + QP calculation with a new quadratic method */
+void calculateQuantizer_Multipass(AVCEncObject *encvid, AVCCommonObj *video,
+                                  AVCRateControl *rateCtrl, MultiPass *pMP)
+{
+    int prev_actual_bits = 0, curr_target, /*pos=0,*/i, j;
+    OsclFloat Qstep, prev_QP = 0.625;
+
+    OsclFloat curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;
+
+    /* Mad based variable bit allocation */
+    targetBitCalculation(encvid, video, rateCtrl, pMP);
+
+    if (rateCtrl->T <= 0 || rateCtrl->totalSAD == 0)
+    {
+        if (rateCtrl->T < 0)    rateCtrl->Qc = RC_MAX_QUANT;
+        return;
+    }
+
+    /* ---------------------------------------------------------------------------------------------------*/
+    /* current frame QP estimation */
+    curr_target = rateCtrl->T;
+    curr_mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs;
+    if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+    curr_RD  = (OsclFloat)curr_target / curr_mad;
+
+    if (rateCtrl->skip_next_frame == -1) // previous was skipped
+    {
+        i = pMP->framePos;
+        prev_mad = pMP->pRDSamples[i][0].mad;
+        prev_QP = pMP->pRDSamples[i][0].QP;
+        prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
+    }
+    else
+    {
+        /* Another version of search the optimal point */
+        prev_mad = 0.0;
+        i = 0;
+        while (i < pMP->frameRange && prev_mad < 0.001) /* find first one with nonzero prev_mad */
+        {
+            prev_mad = pMP->pRDSamples[i][0].mad;
+            i++;
+        }
+
+        if (i < pMP->frameRange)
+        {
+            prev_actual_bits = pMP->pRDSamples[i-1][0].actual_bits;
+
+            for (j = 0; i < pMP->frameRange; i++)
+            {
+                if (pMP->pRDSamples[i][0].mad != 0 &&
+                        AVC_ABS(prev_mad - curr_mad) > AVC_ABS(pMP->pRDSamples[i][0].mad - curr_mad))
+                {
+                    prev_mad = pMP->pRDSamples[i][0].mad;
+                    prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
+                    j = i;
+                }
+            }
+            prev_QP = QP2Qstep(pMP->pRDSamples[j][0].QP);
+
+            for (i = 1; i < pMP->samplesPerFrame[j]; i++)
+            {
+                if (AVC_ABS(prev_actual_bits - curr_target) > AVC_ABS(pMP->pRDSamples[j][i].actual_bits - curr_target))
+                {
+                    prev_actual_bits = pMP->pRDSamples[j][i].actual_bits;
+                    prev_QP = QP2Qstep(pMP->pRDSamples[j][i].QP);
+                }
+            }
+        }
+    }
+
+    // quadratic approximation
+    if (prev_mad > 0.001) // only when prev_mad is greater than 0, otherwise keep using the same QP
+    {
+        prev_RD = (OsclFloat)prev_actual_bits / prev_mad;
+        //rateCtrl->Qc = (Int)(prev_QP * sqrt(prev_actual_bits/curr_target) + 0.4);
+        if (prev_QP == 0.625) // added this to allow getting out of QP = 0 easily
+        {
+            Qstep = (int)(prev_RD / curr_RD + 0.5);
+        }
+        else
+        {
+            //      rateCtrl->Qc =(Int)(prev_QP * M4VENC_SQRT(prev_RD/curr_RD) + 0.9);
+
+            if (prev_RD / curr_RD > 0.5 && prev_RD / curr_RD < 2.0)
+                Qstep = (int)(prev_QP * (sqrt(prev_RD / curr_RD) + prev_RD / curr_RD) / 2.0 + 0.9); /* Quadratic and linear approximation */
+            else
+                Qstep = (int)(prev_QP * (sqrt(prev_RD / curr_RD) + pow(prev_RD / curr_RD, 1.0 / 3.0)) / 2.0 + 0.9);
+        }
+        // lower bound on Qc should be a function of curr_mad
+        // When mad is already low, lower bound on Qc doesn't have to be small.
+        // Note, this doesn't work well for low complexity clip encoded at high bit rate
+        // it doesn't hit the target bit rate due to this QP lower bound.
+        /// if((curr_mad < 8) && (rateCtrl->Qc < 12))   rateCtrl->Qc = 12;
+        //  else    if((curr_mad < 128) && (rateCtrl->Qc < 3)) rateCtrl->Qc = 3;
+
+        rateCtrl->Qc = Qstep2QP(Qstep);
+
+        if (rateCtrl->Qc < RC_MIN_QUANT) rateCtrl->Qc = RC_MIN_QUANT;
+        if (rateCtrl->Qc > RC_MAX_QUANT)    rateCtrl->Qc = RC_MAX_QUANT;
+    }
+
+    /* active bit resource protection */
+    aver_QP = (pMP->encoded_frames == 0 ? 0 : pMP->sum_QP / (OsclFloat)pMP->encoded_frames);
+    average_mad = (pMP->encoded_frames == 0 ? 0 : pMP->sum_mad / (OsclFloat)pMP->encoded_frames); /* this function is called from the scond encoded frame*/
+    if (pMP->diff_counter == 0 &&
+            ((OsclFloat)rateCtrl->Qc <= aver_QP*1.1 || curr_mad <= average_mad*1.1) &&
+            pMP->counter_BTsrc <= (pMP->counter_BTdst + (int)(pMP->framerate*1.0 + 0.5)))
+    {
+        rateCtrl->TMN_TH -= (int)(pMP->target_bits_per_frame / 10.0);
+        rateCtrl->T = rateCtrl->TMN_TH - rateCtrl->TMN_W;
+        pMP->counter_BTsrc++;
+        pMP->diff_counter--;
+    }
+
+}
+
+void targetBitCalculation(AVCEncObject *encvid, AVCCommonObj *video, AVCRateControl *rateCtrl, MultiPass *pMP)
+{
+    OSCL_UNUSED_ARG(encvid);
+    OsclFloat curr_mad;//, average_mad;
+    int diff_counter_BTsrc, diff_counter_BTdst, prev_counter_diff, curr_counter_diff, bound;
+    /* BT = Bit Transfer, for pMP->counter_BTsrc, pMP->counter_BTdst */
+
+    /* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/
+    updateRC_PostProc(rateCtrl, pMP);
+
+    /* update pMP->counter_BTsrc and pMP->counter_BTdst to avoid interger overflow */
+    if (pMP->counter_BTsrc > 1000 && pMP->counter_BTdst > 1000)
+    {
+        pMP->counter_BTsrc -= 1000;
+        pMP->counter_BTdst -= 1000;
+    }
+
+    /* ---------------------------------------------------------------------------------------------------*/
+    /* target calculation */
+    curr_mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs;
+    if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+    diff_counter_BTsrc = diff_counter_BTdst = 0;
+    pMP->diff_counter = 0;
+
+
+    /*1.calculate average mad */
+    pMP->sum_mad += curr_mad;
+    //average_mad = (pMP->encoded_frames < 1 ? curr_mad : pMP->sum_mad/(OsclFloat)(pMP->encoded_frames+1)); /* this function is called from the scond encoded frame*/
+    //pMP->aver_mad = average_mad;
+    if (pMP->encoded_frames >= 0) /* pMP->encoded_frames is set to -1 initially, so forget about the very first I frame */
+        pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames + curr_mad) / (pMP->encoded_frames + 1);
+
+    if (pMP->overlapped_win_size > 0 && pMP->encoded_frames_prev >= 0)
+        pMP->aver_mad_prev = (pMP->aver_mad_prev * pMP->encoded_frames_prev + curr_mad) / (pMP->encoded_frames_prev + 1);
+
+    /*2.average_mad, mad ==> diff_counter_BTsrc, diff_counter_BTdst */
+    if (pMP->overlapped_win_size == 0)
+    {
+        /* original verison */
+        if (curr_mad > pMP->aver_mad*1.1)
+        {
+            if (curr_mad / (pMP->aver_mad + 0.0001) > 2)
+                diff_counter_BTdst = (int)(sqrt(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.4) - 10;
+            //diff_counter_BTdst = (int)((sqrt(curr_mad/pMP->aver_mad)*2+curr_mad/pMP->aver_mad)/(3*0.1) + 0.4) - 10;
+            else
+                diff_counter_BTdst = (int)(curr_mad / (pMP->aver_mad + 0.0001) * 10 + 0.4) - 10;
+        }
+        else /* curr_mad <= average_mad*1.1 */
+            //diff_counter_BTsrc = 10 - (int)((sqrt(curr_mad/pMP->aver_mad) + pow(curr_mad/pMP->aver_mad, 1.0/3.0))/(2.0*0.1) + 0.4);
+            diff_counter_BTsrc = 10 - (int)(sqrt(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.5);
+
+        /* actively fill in the possible gap */
+        if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
+                curr_mad <= pMP->aver_mad*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
+            diff_counter_BTsrc = 1;
+
+    }
+    else if (pMP->overlapped_win_size > 0)
+    {
+        /* transition time: use previous average mad "pMP->aver_mad_prev" instead of the current average mad "pMP->aver_mad" */
+        if (curr_mad > pMP->aver_mad_prev*1.1)
+        {
+            if (curr_mad / pMP->aver_mad_prev > 2)
+                diff_counter_BTdst = (int)(sqrt(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.4) - 10;
+            //diff_counter_BTdst = (int)((M4VENC_SQRT(curr_mad/pMP->aver_mad_prev)*2+curr_mad/pMP->aver_mad_prev)/(3*0.1) + 0.4) - 10;
+            else
+                diff_counter_BTdst = (int)(curr_mad / (pMP->aver_mad_prev + 0.0001) * 10 + 0.4) - 10;
+        }
+        else /* curr_mad <= average_mad*1.1 */
+            //diff_counter_BTsrc = 10 - (Int)((sqrt(curr_mad/pMP->aver_mad_prev) + pow(curr_mad/pMP->aver_mad_prev, 1.0/3.0))/(2.0*0.1) + 0.4);
+            diff_counter_BTsrc = 10 - (int)(sqrt(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.5);
+
+        /* actively fill in the possible gap */
+        if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
+                curr_mad <= pMP->aver_mad_prev*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
+            diff_counter_BTsrc = 1;
+
+        if (--pMP->overlapped_win_size <= 0)    pMP->overlapped_win_size = 0;
+    }
+
+
+    /* if difference is too much, do clipping */
+    /* First, set the upper bound for current bit allocation variance: 80% of available buffer */
+    bound = (int)((rateCtrl->Bs / 2 - rateCtrl->VBV_fullness) * 0.6 / (pMP->target_bits_per_frame / 10)); /* rateCtrl->Bs */
+    diff_counter_BTsrc =  AVC_MIN(diff_counter_BTsrc, bound);
+    diff_counter_BTdst =  AVC_MIN(diff_counter_BTdst, bound);
+
+    /* Second, set another upper bound for current bit allocation: 4-5*bitrate/framerate */
+    bound = 50;
+//  if(video->encParams->RC_Type == CBR_LOWDELAY)
+//  not necessary       bound = 10;  -- For Low delay */
+
+    diff_counter_BTsrc =  AVC_MIN(diff_counter_BTsrc, bound);
+    diff_counter_BTdst =  AVC_MIN(diff_counter_BTdst, bound);
+
+
+    /* Third, check the buffer */
+    prev_counter_diff = pMP->counter_BTdst - pMP->counter_BTsrc;
+    curr_counter_diff = prev_counter_diff + (diff_counter_BTdst - diff_counter_BTsrc);
+
+    if (AVC_ABS(prev_counter_diff) >= rateCtrl->max_BitVariance_num || AVC_ABS(curr_counter_diff) >= rateCtrl->max_BitVariance_num)
+    {   //diff_counter_BTsrc = diff_counter_BTdst = 0;
+
+        if (curr_counter_diff > rateCtrl->max_BitVariance_num && diff_counter_BTdst)
+        {
+            diff_counter_BTdst = (rateCtrl->max_BitVariance_num - prev_counter_diff) + diff_counter_BTsrc;
+            if (diff_counter_BTdst < 0) diff_counter_BTdst = 0;
+        }
+
+        else if (curr_counter_diff < -rateCtrl->max_BitVariance_num && diff_counter_BTsrc)
+        {
+            diff_counter_BTsrc = diff_counter_BTdst - (-rateCtrl->max_BitVariance_num - prev_counter_diff);
+            if (diff_counter_BTsrc < 0) diff_counter_BTsrc = 0;
+        }
+    }
+
+
+    /*3.diff_counter_BTsrc, diff_counter_BTdst ==> TMN_TH */
+    rateCtrl->TMN_TH = (int)(pMP->target_bits_per_frame);
+    pMP->diff_counter = 0;
+
+    if (diff_counter_BTsrc)
+    {
+        rateCtrl->TMN_TH -= (int)(pMP->target_bits_per_frame * diff_counter_BTsrc * 0.1);
+        pMP->diff_counter = -diff_counter_BTsrc;
+    }
+    else if (diff_counter_BTdst)
+    {
+        rateCtrl->TMN_TH += (int)(pMP->target_bits_per_frame * diff_counter_BTdst * 0.1);
+        pMP->diff_counter = diff_counter_BTdst;
+    }
+
+
+    /*4.update pMP->counter_BTsrc, pMP->counter_BTdst */
+    pMP->counter_BTsrc += diff_counter_BTsrc;
+    pMP->counter_BTdst += diff_counter_BTdst;
+
+
+    /*5.target bit calculation */
+    rateCtrl->T = rateCtrl->TMN_TH - rateCtrl->TMN_W;
+
+    return ;
+}
+
+void updateRC_PostProc(AVCRateControl *rateCtrl, MultiPass *pMP)
+{
+    if (rateCtrl->skip_next_frame > 0) /* skip next frame */
+    {
+        pMP->counter_BTsrc += 10 * rateCtrl->skip_next_frame;
+
+    }
+    else if (rateCtrl->skip_next_frame == -1) /* skip current frame */
+    {
+        pMP->counter_BTdst -= pMP->diff_counter;
+        pMP->counter_BTsrc += 10;
+
+        pMP->sum_mad -= pMP->mad;
+        pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames - pMP->mad) / (pMP->encoded_frames - 1 + 0.0001);
+        pMP->sum_QP  -= pMP->QP;
+        pMP->encoded_frames --;
+    }
+    /* some stuff in update VBV_fullness remains here */
+    //if(rateCtrl->VBV_fullness < -rateCtrl->Bs/2) /* rateCtrl->Bs */
+    if (rateCtrl->VBV_fullness < rateCtrl->low_bound)
+    {
+        rateCtrl->VBV_fullness = rateCtrl->low_bound; // -rateCtrl->Bs/2;
+        rateCtrl->TMN_W = rateCtrl->VBV_fullness - rateCtrl->low_bound;
+        pMP->counter_BTsrc = pMP->counter_BTdst + (int)((OsclFloat)(rateCtrl->Bs / 2 - rateCtrl->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+    }
+}
+
+
+void RCInitChromaQP(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCMacroblock *currMB = video->currMB;
+    int q_bits;
+
+    /* we have to do the same thing for AVC_CLIP3(0,51,video->QSy) */
+
+    video->QPy_div_6 = (currMB->QPy * 43) >> 8;
+    video->QPy_mod_6 = currMB->QPy - 6 * video->QPy_div_6;
+    currMB->QPc = video->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, currMB->QPy + video->currPicParams->chroma_qp_index_offset)];
+    video->QPc_div_6 = (video->QPc * 43) >> 8;
+    video->QPc_mod_6 = video->QPc - 6 * video->QPc_div_6;
+
+    /* pre-calculate this to save computation */
+    q_bits = 4 + video->QPy_div_6;
+    if (video->slice_type == AVC_I_SLICE)
+    {
+        encvid->qp_const = 682 << q_bits;       // intra
+    }
+    else
+    {
+        encvid->qp_const = 342 << q_bits;       // inter
+    }
+
+    q_bits = 4 + video->QPc_div_6;
+    if (video->slice_type == AVC_I_SLICE)
+    {
+        encvid->qp_const_c = 682 << q_bits;    // intra
+    }
+    else
+    {
+        encvid->qp_const_c = 342 << q_bits;    // inter
+    }
+
+    encvid->lambda_mode = QP2QUANT[AVC_MAX(0, currMB->QPy-SHIFT_QP)];
+    encvid->lambda_motion = LAMBDA_FACTOR(encvid->lambda_mode);
+
+    return ;
+}
+
+
+void RCInitMBQP(AVCEncObject *encvid)
+{
+    AVCCommonObj *video =  encvid->common;
+    AVCMacroblock *currMB = video->currMB;
+
+    currMB->QPy = video->QPy; /* set to previous value or picture level */
+
+    RCInitChromaQP(encvid);
+
+}
+
+void RCPostMB(AVCCommonObj *video, AVCRateControl *rateCtrl, int num_header_bits, int num_texture_bits)
+{
+    OSCL_UNUSED_ARG(video);
+    rateCtrl->numMBHeaderBits = num_header_bits;
+    rateCtrl->numMBTextureBits = num_texture_bits;
+    rateCtrl->NumberofHeaderBits += rateCtrl->numMBHeaderBits;
+    rateCtrl->NumberofTextureBits += rateCtrl->numMBTextureBits;
+}
+
+void RCRestoreQP(AVCMacroblock *currMB, AVCCommonObj *video, AVCEncObject *encvid)
+{
+    currMB->QPy = video->QPy; /* use previous QP */
+    RCInitChromaQP(encvid);
+
+    return ;
+}
+
+
+void RCCalculateMAD(AVCEncObject *encvid, AVCMacroblock *currMB, uint8 *orgL, int orgPitch)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    uint32 dmin_lx;
+
+    if (rateCtrl->rcEnable == TRUE)
+    {
+        if (currMB->mb_intra)
+        {
+            if (currMB->mbMode == AVC_I16)
+            {
+                dmin_lx = (0xFFFF << 16) | orgPitch;
+                rateCtrl->MADofMB[video->mbNum] = AVCSAD_Macroblock_C(orgL,
+                                                  encvid->pred_i16[currMB->i16Mode], dmin_lx, NULL);
+            }
+            else /* i4 */
+            {
+                rateCtrl->MADofMB[video->mbNum] = encvid->i4_sad / 256.;
+            }
+        }
+        /* for INTER, we have already saved it with the MV search */
+    }
+
+    return ;
+}
+
+
+
+AVCEnc_Status RCUpdateFrame(AVCEncObject *encvid)
+{
+    AVCCommonObj *video = encvid->common;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    MultiPass *pMP = rateCtrl->pMP;
+    int diff_BTCounter;
+    int nal_type = video->nal_unit_type;
+
+    /* update the complexity weight of I, P, B frame */
+
+    if (rateCtrl->rcEnable == TRUE)
+    {
+        pMP->actual_bits = rateCtrl->numFrameBits;
+        pMP->mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs; //ComputeFrameMAD(video, rateCtrl);
+
+        AVCSaveRDSamples(pMP, 0);
+
+        pMP->encoded_frames++;
+
+        /* for pMP->samplesPerFrame */
+        pMP->samplesPerFrame[pMP->framePos] = 0;
+
+        pMP->sum_QP += pMP->QP;
+
+        /* update pMP->counter_BTsrc, pMP->counter_BTdst */
+        /* re-allocate the target bit again and then stop encoding */
+        diff_BTCounter = (int)((OsclFloat)(rateCtrl->TMN_TH - rateCtrl->TMN_W - pMP->actual_bits) /
+                               (pMP->bitrate / (pMP->framerate + 0.0001) + 0.0001) / 0.1);
+        if (diff_BTCounter >= 0)
+            pMP->counter_BTsrc += diff_BTCounter; /* pMP->actual_bits is smaller */
+        else
+            pMP->counter_BTdst -= diff_BTCounter; /* pMP->actual_bits is bigger */
+
+        rateCtrl->TMN_TH -= (int)((OsclFloat)pMP->bitrate / (pMP->framerate + 0.0001) * (diff_BTCounter * 0.1));
+        rateCtrl->T = pMP->target_bits = rateCtrl->TMN_TH - rateCtrl->TMN_W;
+        pMP->diff_counter -= diff_BTCounter;
+
+        rateCtrl->Rc = rateCtrl->numFrameBits;  /* Total Bits for current frame */
+        rateCtrl->Hc = rateCtrl->NumberofHeaderBits;    /* Total Bits in Header and Motion Vector */
+
+        /* BX_RC */
+        updateRateControl(rateCtrl, nal_type);
+        if (rateCtrl->skip_next_frame == -1) // skip current frame
+        {
+            status = AVCENC_SKIPPED_PICTURE;
+        }
+    }
+
+    rateCtrl->first_frame = 0;  // reset here after we encode the first frame.
+
+    return status;
+}
+
+void AVCSaveRDSamples(MultiPass *pMP, int counter_samples)
+{
+    /* for pMP->pRDSamples */
+    pMP->pRDSamples[pMP->framePos][counter_samples].QP    = pMP->QP;
+    pMP->pRDSamples[pMP->framePos][counter_samples].actual_bits = pMP->actual_bits;
+    pMP->pRDSamples[pMP->framePos][counter_samples].mad   = pMP->mad;
+    pMP->pRDSamples[pMP->framePos][counter_samples].R_D = (OsclFloat)pMP->actual_bits / (pMP->mad + 0.0001);
+
+    return ;
+}
+
+void updateRateControl(AVCRateControl *rateCtrl, int nal_type)
+{
+    int  frame_bits;
+    MultiPass *pMP = rateCtrl->pMP;
+
+    /* BX rate contro\l */
+    frame_bits = (int)(rateCtrl->bitRate / rateCtrl->frame_rate);
+    rateCtrl->TMN_W += (rateCtrl->Rc - rateCtrl->TMN_TH);
+    rateCtrl->VBV_fullness += (rateCtrl->Rc - frame_bits); //rateCtrl->Rp);
+    //if(rateCtrl->VBV_fullness < 0) rateCtrl->VBV_fullness = -1;
+
+    rateCtrl->encoded_frames++;
+
+    /* frame dropping */
+    rateCtrl->skip_next_frame = 0;
+
+    if ((rateCtrl->VBV_fullness > rateCtrl->Bs / 2) && nal_type != AVC_NALTYPE_IDR) /* skip the current frame */ /* rateCtrl->Bs */
+    {
+        rateCtrl->TMN_W -= (rateCtrl->Rc - rateCtrl->TMN_TH);
+        rateCtrl->VBV_fullness -= rateCtrl->Rc;
+        rateCtrl->skip_next_frame = -1;
+    }
+    else if ((OsclFloat)(rateCtrl->VBV_fullness - rateCtrl->VBV_fullness_offset) > (rateCtrl->Bs / 2 - rateCtrl->VBV_fullness_offset)*0.95) /* skip next frame */
+    {
+        rateCtrl->VBV_fullness -= frame_bits; //rateCtrl->Rp;
+        rateCtrl->skip_next_frame = 1;
+        pMP->counter_BTsrc -= (int)((OsclFloat)(rateCtrl->Bs / 2 - rateCtrl->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+        /* BX_1, skip more than 1 frames  */
+        //while(rateCtrl->VBV_fullness > rateCtrl->Bs*0.475)
+        while ((rateCtrl->VBV_fullness - rateCtrl->VBV_fullness_offset) > (rateCtrl->Bs / 2 - rateCtrl->VBV_fullness_offset)*0.95)
+        {
+            rateCtrl->VBV_fullness -= frame_bits; //rateCtrl->Rp;
+            rateCtrl->skip_next_frame++;
+            pMP->counter_BTsrc -= (int)((OsclFloat)(rateCtrl->Bs / 2 - rateCtrl->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+        }
+
+        /* END BX_1 */
+    }
+}
+
+
+double ComputeFrameMAD(AVCCommonObj *video, AVCRateControl *rateCtrl)
+{
+    double TotalMAD;
+    int i;
+    TotalMAD = 0.0;
+    for (i = 0; i < (int)video->PicSizeInMbs; i++)
+        TotalMAD += rateCtrl->MADofMB[i];
+    TotalMAD /= video->PicSizeInMbs;
+    return TotalMAD;
+}
+
+
+
+
+
+/* convert from QP to Qstep */
+double QP2Qstep(int QP)
+{
+    int i;
+    double Qstep;
+    static const double QP2QSTEP[6] = { 0.625, 0.6875, 0.8125, 0.875, 1.0, 1.125 };
+
+    Qstep = QP2QSTEP[QP % 6];
+    for (i = 0; i < (QP / 6); i++)
+        Qstep *= 2;
+
+    return Qstep;
+}
+
+/* convert from step size to QP */
+int Qstep2QP(double Qstep)
+{
+    int q_per = 0, q_rem = 0;
+
+    //  assert( Qstep >= QP2Qstep(0) && Qstep <= QP2Qstep(51) );
+    if (Qstep < QP2Qstep(0))
+        return 0;
+    else if (Qstep > QP2Qstep(51))
+        return 51;
+
+    while (Qstep > QP2Qstep(5))
+    {
+        Qstep /= 2;
+        q_per += 1;
+    }
+
+    if (Qstep <= (0.625 + 0.6875) / 2)
+    {
+        Qstep = 0.625;
+        q_rem = 0;
+    }
+    else if (Qstep <= (0.6875 + 0.8125) / 2)
+    {
+        Qstep = 0.6875;
+        q_rem = 1;
+    }
+    else if (Qstep <= (0.8125 + 0.875) / 2)
+    {
+        Qstep = 0.8125;
+        q_rem = 2;
+    }
+    else if (Qstep <= (0.875 + 1.0) / 2)
+    {
+        Qstep = 0.875;
+        q_rem = 3;
+    }
+    else if (Qstep <= (1.0 + 1.125) / 2)
+    {
+        Qstep = 1.0;
+        q_rem = 4;
+    }
+    else
+    {
+        Qstep = 1.125;
+        q_rem = 5;
+    }
+
+    return (q_per * 6 + q_rem);
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/residual.cpp b/media/libstagefright/codecs/avc/enc/src/residual.cpp
new file mode 100644
index 0000000..42eb910
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/residual.cpp
@@ -0,0 +1,389 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+AVCEnc_Status EncodeIntraPCM(AVCEncObject *encvid)
+{
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    AVCCommonObj *video = encvid->common;
+    AVCFrameIO  *currInput = encvid->currInput;
+    AVCEncBitstream *stream = encvid->bitstream;
+    int x_position = (video->mb_x << 4);
+    int y_position = (video->mb_y << 4);
+    int orgPitch = currInput->pitch;
+    int offset1 = y_position * orgPitch + x_position;
+    int i, j;
+    int offset;
+    uint8 *pDst, *pSrc;
+    uint code;
+
+    ue_v(stream, 25);
+
+    i = stream->bit_left & 0x7;
+    if (i) /* not byte-aligned */
+    {
+        BitstreamWriteBits(stream, 0, i);
+    }
+
+    pSrc = currInput->YCbCr[0] + offset1;
+    pDst = video->currPic->Sl + offset1;
+    offset = video->PicWidthInSamplesL - 16;
+
+    /* at this point bitstream is byte-aligned */
+    j = 16;
+    while (j > 0)
+    {
+#if (WORD_SIZE==32)
+        for (i = 0; i < 4; i++)
+        {
+            code = *((uint*)pSrc);
+            pSrc += 4;
+            *((uint*)pDst) = code;
+            pDst += 4;
+            status = BitstreamWriteBits(stream, 32, code);
+        }
+#else
+        for (i = 0; i < 8; i++)
+        {
+            code = *((uint*)pSrc);
+            pSrc += 2;
+            *((uint*)pDst) = code;
+            pDst += 2;
+            status = BitstreamWriteBits(stream, 16, code);
+        }
+#endif
+        pDst += offset;
+        pSrc += offset;
+        j--;
+    }
+    if (status != AVCENC_SUCCESS)  /* check only once per line */
+        return status;
+
+    pDst = video->currPic->Scb + ((offset1 + x_position) >> 2);
+    pSrc = currInput->YCbCr[1] + ((offset1 + x_position) >> 2);
+    offset >>= 1;
+
+    j = 8;
+    while (j > 0)
+    {
+#if (WORD_SIZE==32)
+        for (i = 0; i < 2; i++)
+        {
+            code = *((uint*)pSrc);
+            pSrc += 4;
+            *((uint*)pDst) = code;
+            pDst += 4;
+            status = BitstreamWriteBits(stream, 32, code);
+        }
+#else
+        for (i = 0; i < 4; i++)
+        {
+            code = *((uint*)pSrc);
+            pSrc += 2;
+            *((uint*)pDst) = code;
+            pDst += 2;
+            status = BitstreamWriteBits(stream, 16, code);
+        }
+#endif
+        pDst += offset;
+        pSrc += offset;
+        j--;
+    }
+
+    if (status != AVCENC_SUCCESS)  /* check only once per line */
+        return status;
+
+    pDst = video->currPic->Scr + ((offset1 + x_position) >> 2);
+    pSrc = currInput->YCbCr[2] + ((offset1 + x_position) >> 2);
+
+    j = 8;
+    while (j > 0)
+    {
+#if (WORD_SIZE==32)
+        for (i = 0; i < 2; i++)
+        {
+            code = *((uint*)pSrc);
+            pSrc += 4;
+            *((uint*)pDst) = code;
+            pDst += 4;
+            status = BitstreamWriteBits(stream, 32, code);
+        }
+#else
+        for (i = 0; i < 4; i++)
+        {
+            code = *((uint*)pSrc);
+            pSrc += 2;
+            *((uint*)pDst) = code;
+            pDst += 2;
+            status = BitstreamWriteBits(stream, 16, code);
+        }
+#endif
+        pDst += offset;
+        pSrc += offset;
+        j--;
+    }
+
+    return status;
+}
+
+
+AVCEnc_Status enc_residual_block(AVCEncObject *encvid, AVCResidualType type, int cindx, AVCMacroblock *currMB)
+{
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    AVCCommonObj *video = encvid->common;
+    int i, maxNumCoeff, nC;
+    int cdc = 0, cac = 0;
+    int TrailingOnes;
+    AVCEncBitstream *stream = encvid->bitstream;
+    uint trailing_ones_sign_flag;
+    int zerosLeft;
+    int *level, *run;
+    int TotalCoeff;
+    const static int incVlc[] = {0, 3, 6, 12, 24, 48, 32768};  // maximum vlc = 6
+    int escape, numPrefix, sufmask, suffix, shift, sign, value, absvalue, vlcnum, level_two_or_higher;
+    int bindx = blkIdx2blkXY[cindx>>2][cindx&3] ; // raster scan index
+
+    switch (type)
+    {
+        case AVC_Luma:
+            maxNumCoeff = 16;
+            level = encvid->level[cindx];
+            run = encvid->run[cindx];
+            TotalCoeff = currMB->nz_coeff[bindx];
+            break;
+        case AVC_Intra16DC:
+            maxNumCoeff = 16;
+            level = encvid->leveldc;
+            run = encvid->rundc;
+            TotalCoeff = cindx; /* special case */
+            bindx = 0;
+            cindx = 0;
+            break;
+        case AVC_Intra16AC:
+            maxNumCoeff = 15;
+            level = encvid->level[cindx];
+            run = encvid->run[cindx];
+            TotalCoeff = currMB->nz_coeff[bindx];
+            break;
+        case AVC_ChromaDC:  /* how to differentiate Cb from Cr */
+            maxNumCoeff = 4;
+            cdc = 1;
+            if (cindx >= 8)
+            {
+                level = encvid->levelcdc + 4;
+                run = encvid->runcdc + 4;
+                TotalCoeff = cindx - 8;  /* special case */
+            }
+            else
+            {
+                level = encvid->levelcdc;
+                run = encvid->runcdc;
+                TotalCoeff = cindx;  /* special case */
+            }
+            break;
+        case AVC_ChromaAC:
+            maxNumCoeff = 15;
+            cac = 1;
+            level = encvid->level[cindx];
+            run = encvid->run[cindx];
+            cindx -= 16;
+            bindx = 16 + blkIdx2blkXY[cindx>>2][cindx&3];
+            cindx += 16;
+            TotalCoeff = currMB->nz_coeff[bindx];
+            break;
+        default:
+            return AVCENC_FAIL;
+    }
+
+
+    /* find TrailingOnes */
+    TrailingOnes = 0;
+    zerosLeft = 0;
+    i = TotalCoeff - 1;
+    nC = 1;
+    while (i >= 0)
+    {
+        zerosLeft += run[i];
+        if (nC && (level[i] == 1 || level[i] == -1))
+        {
+            TrailingOnes++;
+        }
+        else
+        {
+            nC = 0;
+        }
+        i--;
+    }
+    if (TrailingOnes > 3)
+    {
+        TrailingOnes = 3; /* clip it */
+    }
+
+    if (!cdc)
+    {
+        if (!cac)  /* not chroma */
+        {
+            nC = predict_nnz(video, bindx & 3, bindx >> 2);
+        }
+        else /* chroma ac but not chroma dc */
+        {
+            nC = predict_nnz_chroma(video, bindx & 3, bindx >> 2);
+        }
+
+        status = ce_TotalCoeffTrailingOnes(stream, TrailingOnes, TotalCoeff, nC);
+    }
+    else
+    {
+        nC = -1; /* Chroma DC level */
+        status = ce_TotalCoeffTrailingOnesChromaDC(stream, TrailingOnes, TotalCoeff);
+    }
+
+    /* This part is done quite differently in ReadCoef4x4_CAVLC() */
+    if (TotalCoeff > 0)
+    {
+
+        i = TotalCoeff - 1;
+
+        if (TrailingOnes) /* keep reading the sign of those trailing ones */
+        {
+            nC = TrailingOnes;
+            trailing_ones_sign_flag = 0;
+            while (nC)
+            {
+                trailing_ones_sign_flag <<= 1;
+                trailing_ones_sign_flag |= ((uint32)level[i--] >> 31); /* 0 or positive, 1 for negative */
+                nC--;
+            }
+
+            /* instead of writing one bit at a time, read the whole thing at once */
+            status = BitstreamWriteBits(stream, TrailingOnes, trailing_ones_sign_flag);
+        }
+
+        level_two_or_higher = 1;
+        if (TotalCoeff > 3 && TrailingOnes == 3)
+        {
+            level_two_or_higher = 0;
+        }
+
+        if (TotalCoeff > 10 && TrailingOnes < 3)
+        {
+            vlcnum = 1;
+        }
+        else
+        {
+            vlcnum = 0;
+        }
+
+        /* then do this TotalCoeff-TrailingOnes times */
+        for (i = TotalCoeff - TrailingOnes - 1; i >= 0; i--)
+        {
+            value = level[i];
+            absvalue = (value >= 0) ? value : -value;
+
+            if (level_two_or_higher)
+            {
+                if (value > 0) value--;
+                else    value++;
+                level_two_or_higher = 0;
+            }
+
+            if (value >= 0)
+            {
+                sign = 0;
+            }
+            else
+            {
+                sign = 1;
+                value = -value;
+            }
+
+            if (vlcnum == 0) // VLC1
+            {
+                if (value < 8)
+                {
+                    status = BitstreamWriteBits(stream, value * 2 + sign - 1, 1);
+                }
+                else if (value < 8 + 8)
+                {
+                    status = BitstreamWriteBits(stream, 14 + 1 + 4, (1 << 4) | ((value - 8) << 1) | sign);
+                }
+                else
+                {
+                    status = BitstreamWriteBits(stream, 14 + 2 + 12, (1 << 12) | ((value - 16) << 1) | sign) ;
+                }
+            }
+            else  // VLCN
+            {
+                shift = vlcnum - 1;
+                escape = (15 << shift) + 1;
+                numPrefix = (value - 1) >> shift;
+                sufmask = ~((0xffffffff) << shift);
+                suffix = (value - 1) & sufmask;
+                if (value < escape)
+                {
+                    status = BitstreamWriteBits(stream, numPrefix + vlcnum + 1, (1 << (shift + 1)) | (suffix << 1) | sign);
+                }
+                else
+                {
+                    status = BitstreamWriteBits(stream, 28, (1 << 12) | ((value - escape) << 1) | sign);
+                }
+
+            }
+
+            if (absvalue > incVlc[vlcnum])
+                vlcnum++;
+
+            if (i == TotalCoeff - TrailingOnes - 1 && absvalue > 3)
+                vlcnum = 2;
+        }
+
+        if (status != AVCENC_SUCCESS)  /* occasionally check the bitstream */
+        {
+            return status;
+        }
+        if (TotalCoeff < maxNumCoeff)
+        {
+            if (!cdc)
+            {
+                ce_TotalZeros(stream, zerosLeft, TotalCoeff);
+            }
+            else
+            {
+                ce_TotalZerosChromaDC(stream, zerosLeft, TotalCoeff);
+            }
+        }
+        else
+        {
+            zerosLeft = 0;
+        }
+
+        i = TotalCoeff - 1;
+        while (i > 0) /* don't do the last one */
+        {
+            if (zerosLeft > 0)
+            {
+                ce_RunBefore(stream, run[i], zerosLeft);
+            }
+
+            zerosLeft = zerosLeft - run[i];
+            i--;
+        }
+    }
+
+    return status;
+}
diff --git a/media/libstagefright/codecs/avc/enc/src/sad.cpp b/media/libstagefright/codecs/avc/enc/src/sad.cpp
new file mode 100644
index 0000000..ae7acd2
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad.cpp
@@ -0,0 +1,290 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include "sad_inline.h"
+
+#define Cached_lx 176
+
+#ifdef _SAD_STAT
+uint32 num_sad_MB = 0;
+uint32 num_sad_Blk = 0;
+uint32 num_sad_MB_call = 0;
+uint32 num_sad_Blk_call = 0;
+
+#define NUM_SAD_MB_CALL()       num_sad_MB_call++
+#define NUM_SAD_MB()            num_sad_MB++
+#define NUM_SAD_BLK_CALL()      num_sad_Blk_call++
+#define NUM_SAD_BLK()           num_sad_Blk++
+
+#else
+
+#define NUM_SAD_MB_CALL()
+#define NUM_SAD_MB()
+#define NUM_SAD_BLK_CALL()
+#define NUM_SAD_BLK()
+
+#endif
+
+
+/* consist of
+int AVCSAD_Macroblock_C(uint8 *ref,uint8 *blk,int dmin,int lx,void *extra_info)
+int AVCSAD_MB_HTFM_Collect(uint8 *ref,uint8 *blk,int dmin,int lx,void *extra_info)
+int AVCSAD_MB_HTFM(uint8 *ref,uint8 *blk,int dmin,int lx,void *extra_info)
+*/
+
+
+/*==================================================================
+    Function:   SAD_Macroblock
+    Date:       09/07/2000
+    Purpose:    Compute SAD 16x16 between blk and ref.
+    To do:      Uniform subsampling will be inserted later!
+                Hypothesis Testing Fast Matching to be used later!
+    Changes:
+    11/7/00:    implemented MMX
+    1/24/01:    implemented SSE
+==================================================================*/
+/********** C ************/
+int AVCSAD_Macroblock_C(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info)
+{
+    (void)(extra_info);
+
+    int32 x10;
+    int dmin = (uint32)dmin_lx >> 16;
+    int lx = dmin_lx & 0xFFFF;
+
+    NUM_SAD_MB_CALL();
+
+    x10 = simd_sad_mb(ref, blk, dmin, lx);
+
+    return x10;
+}
+
+#ifdef HTFM   /* HTFM with uniform subsampling implementation 2/28/01 */
+/*===============================================================
+    Function:   AVCAVCSAD_MB_HTFM_Collect and AVCSAD_MB_HTFM
+    Date:       3/2/1
+    Purpose:    Compute the SAD on a 16x16 block using
+                uniform subsampling and hypothesis testing fast matching
+                for early dropout. SAD_MB_HP_HTFM_Collect is to collect
+                the statistics to compute the thresholds to be used in
+                SAD_MB_HP_HTFM.
+    Input/Output:
+    Changes:
+  ===============================================================*/
+
+int AVCAVCSAD_MB_HTFM_Collect(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info)
+{
+    int i;
+    int sad = 0;
+    uint8 *p1;
+    int lx4 = (dmin_lx << 2) & 0x3FFFC;
+    uint32 cur_word;
+    int saddata[16], tmp, tmp2;    /* used when collecting flag (global) is on */
+    int difmad;
+    int madstar;
+    HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+    int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+    uint *countbreak = &(htfm_stat->countbreak);
+    int *offsetRef = htfm_stat->offsetRef;
+
+    madstar = (uint32)dmin_lx >> 20;
+
+    NUM_SAD_MB_CALL();
+
+    blk -= 4;
+    for (i = 0; i < 16; i++)
+    {
+        p1 = ref + offsetRef[i];
+        cur_word = *((uint32*)(blk += 4));
+        tmp = p1[12];
+        tmp2 = (cur_word >> 24) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[8];
+        tmp2 = (cur_word >> 16) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[4];
+        tmp2 = (cur_word >> 8) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[0];
+        p1 += lx4;
+        tmp2 = (cur_word & 0xFF);
+        sad = SUB_SAD(sad, tmp, tmp2);
+
+        cur_word = *((uint32*)(blk += 4));
+        tmp = p1[12];
+        tmp2 = (cur_word >> 24) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[8];
+        tmp2 = (cur_word >> 16) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[4];
+        tmp2 = (cur_word >> 8) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[0];
+        p1 += lx4;
+        tmp2 = (cur_word & 0xFF);
+        sad = SUB_SAD(sad, tmp, tmp2);
+
+        cur_word = *((uint32*)(blk += 4));
+        tmp = p1[12];
+        tmp2 = (cur_word >> 24) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[8];
+        tmp2 = (cur_word >> 16) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[4];
+        tmp2 = (cur_word >> 8) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[0];
+        p1 += lx4;
+        tmp2 = (cur_word & 0xFF);
+        sad = SUB_SAD(sad, tmp, tmp2);
+
+        cur_word = *((uint32*)(blk += 4));
+        tmp = p1[12];
+        tmp2 = (cur_word >> 24) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[8];
+        tmp2 = (cur_word >> 16) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[4];
+        tmp2 = (cur_word >> 8) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[0];
+        p1 += lx4;
+        tmp2 = (cur_word & 0xFF);
+        sad = SUB_SAD(sad, tmp, tmp2);
+
+        NUM_SAD_MB();
+
+        saddata[i] = sad;
+
+        if (i > 0)
+        {
+            if ((uint32)sad > ((uint32)dmin_lx >> 16))
+            {
+                difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+                (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+                (*countbreak)++;
+                return sad;
+            }
+        }
+    }
+
+    difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+    (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+    (*countbreak)++;
+    return sad;
+}
+
+int AVCSAD_MB_HTFM(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info)
+{
+    int sad = 0;
+    uint8 *p1;
+
+    int i;
+    int tmp, tmp2;
+    int lx4 = (dmin_lx << 2) & 0x3FFFC;
+    int sadstar = 0, madstar;
+    int *nrmlz_th = (int*) extra_info;
+    int *offsetRef = (int*) extra_info + 32;
+    uint32 cur_word;
+
+    madstar = (uint32)dmin_lx >> 20;
+
+    NUM_SAD_MB_CALL();
+
+    blk -= 4;
+    for (i = 0; i < 16; i++)
+    {
+        p1 = ref + offsetRef[i];
+        cur_word = *((uint32*)(blk += 4));
+        tmp = p1[12];
+        tmp2 = (cur_word >> 24) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[8];
+        tmp2 = (cur_word >> 16) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[4];
+        tmp2 = (cur_word >> 8) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[0];
+        p1 += lx4;
+        tmp2 = (cur_word & 0xFF);
+        sad = SUB_SAD(sad, tmp, tmp2);
+
+        cur_word = *((uint32*)(blk += 4));
+        tmp = p1[12];
+        tmp2 = (cur_word >> 24) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[8];
+        tmp2 = (cur_word >> 16) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[4];
+        tmp2 = (cur_word >> 8) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[0];
+        p1 += lx4;
+        tmp2 = (cur_word & 0xFF);
+        sad = SUB_SAD(sad, tmp, tmp2);
+
+        cur_word = *((uint32*)(blk += 4));
+        tmp = p1[12];
+        tmp2 = (cur_word >> 24) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[8];
+        tmp2 = (cur_word >> 16) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[4];
+        tmp2 = (cur_word >> 8) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[0];
+        p1 += lx4;
+        tmp2 = (cur_word & 0xFF);
+        sad = SUB_SAD(sad, tmp, tmp2);
+
+        cur_word = *((uint32*)(blk += 4));
+        tmp = p1[12];
+        tmp2 = (cur_word >> 24) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[8];
+        tmp2 = (cur_word >> 16) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[4];
+        tmp2 = (cur_word >> 8) & 0xFF;
+        sad = SUB_SAD(sad, tmp, tmp2);
+        tmp = p1[0];
+        p1 += lx4;
+        tmp2 = (cur_word & 0xFF);
+        sad = SUB_SAD(sad, tmp, tmp2);
+
+        NUM_SAD_MB();
+
+        sadstar += madstar;
+        if (((uint32)sad <= ((uint32)dmin_lx >> 16)) && (sad <= (sadstar - *nrmlz_th++)))
+            ;
+        else
+            return 65536;
+    }
+
+    return sad;
+}
+#endif /* HTFM */
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/sad_halfpel.cpp b/media/libstagefright/codecs/avc/enc/src/sad_halfpel.cpp
new file mode 100644
index 0000000..faf2198
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad_halfpel.cpp
@@ -0,0 +1,629 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/* contains
+int AVCHalfPel1_SAD_MB(uint8 *ref,uint8 *blk,int dmin,int width,int ih,int jh)
+int AVCHalfPel2_SAD_MB(uint8 *ref,uint8 *blk,int dmin,int width)
+int AVCHalfPel1_SAD_Blk(uint8 *ref,uint8 *blk,int dmin,int width,int ih,int jh)
+int AVCHalfPel2_SAD_Blk(uint8 *ref,uint8 *blk,int dmin,int width)
+
+int AVCSAD_MB_HalfPel_C(uint8 *ref,uint8 *blk,int dmin,int width,int rx,int xh,int yh,void *extra_info)
+int AVCSAD_MB_HP_HTFM_Collect(uint8 *ref,uint8 *blk,int dmin,int width,int rx,int xh,int yh,void *extra_info)
+int AVCSAD_MB_HP_HTFM(uint8 *ref,uint8 *blk,int dmin,int width,int rx,int xh,int yh,void *extra_info)
+int AVCSAD_Blk_HalfPel_C(uint8 *ref,uint8 *blk,int dmin,int width,int rx,int xh,int yh,void *extra_info)
+*/
+
+#include "avcenc_lib.h"
+#include "sad_halfpel_inline.h"
+
+#ifdef _SAD_STAT
+uint32 num_sad_HP_MB = 0;
+uint32 num_sad_HP_Blk = 0;
+uint32 num_sad_HP_MB_call = 0;
+uint32 num_sad_HP_Blk_call = 0;
+#define NUM_SAD_HP_MB_CALL()    num_sad_HP_MB_call++
+#define NUM_SAD_HP_MB()         num_sad_HP_MB++
+#define NUM_SAD_HP_BLK_CALL()   num_sad_HP_Blk_call++
+#define NUM_SAD_HP_BLK()        num_sad_HP_Blk++
+#else
+#define NUM_SAD_HP_MB_CALL()
+#define NUM_SAD_HP_MB()
+#define NUM_SAD_HP_BLK_CALL()
+#define NUM_SAD_HP_BLK()
+#endif
+
+
+
+/*===============================================================
+    Function:   SAD_MB_HalfPel
+    Date:       09/17/2000
+    Purpose:    Compute the SAD on the half-pel resolution
+    Input/Output:   hmem is assumed to be a pointer to the starting
+                point of the search in the 33x33 matrix search region
+    Changes:
+    11/7/00:    implemented MMX
+  ===============================================================*/
+/*==================================================================
+    Function:   AVCSAD_MB_HalfPel_C
+    Date:       04/30/2001
+    Purpose:    Compute SAD 16x16 between blk and ref in halfpel
+                resolution,
+    Changes:
+  ==================================================================*/
+/* One component is half-pel */
+int AVCSAD_MB_HalfPel_Cxhyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    (void)(extra_info);
+
+    int i, j;
+    int sad = 0;
+    uint8 *kk, *p1, *p2, *p3, *p4;
+//  int sumref=0;
+    int temp;
+    int rx = dmin_rx & 0xFFFF;
+
+    NUM_SAD_HP_MB_CALL();
+
+    p1 = ref;
+    p2 = ref + 1;
+    p3 = ref + rx;
+    p4 = ref + rx + 1;
+    kk  = blk;
+
+    for (i = 0; i < 16; i++)
+    {
+        for (j = 0; j < 16; j++)
+        {
+
+            temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - *kk++;
+            sad += AVC_ABS(temp);
+        }
+
+        NUM_SAD_HP_MB();
+
+        if (sad > (int)((uint32)dmin_rx >> 16))
+            return sad;
+
+        p1 += rx;
+        p3 += rx;
+        p2 += rx;
+        p4 += rx;
+    }
+    return sad;
+}
+
+int AVCSAD_MB_HalfPel_Cyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    (void)(extra_info);
+
+    int i, j;
+    int sad = 0;
+    uint8 *kk, *p1, *p2;
+//  int sumref=0;
+    int temp;
+    int rx = dmin_rx & 0xFFFF;
+
+    NUM_SAD_HP_MB_CALL();
+
+    p1 = ref;
+    p2 = ref + rx; /* either left/right or top/bottom pixel */
+    kk  = blk;
+
+    for (i = 0; i < 16; i++)
+    {
+        for (j = 0; j < 16; j++)
+        {
+
+            temp = ((p1[j] + p2[j] + 1) >> 1) - *kk++;
+            sad += AVC_ABS(temp);
+        }
+
+        NUM_SAD_HP_MB();
+
+        if (sad > (int)((uint32)dmin_rx >> 16))
+            return sad;
+        p1 += rx;
+        p2 += rx;
+    }
+    return sad;
+}
+
+int AVCSAD_MB_HalfPel_Cxh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    (void)(extra_info);
+
+    int i, j;
+    int sad = 0;
+    uint8 *kk, *p1;
+    int temp;
+    int rx = dmin_rx & 0xFFFF;
+
+    NUM_SAD_HP_MB_CALL();
+
+    p1 = ref;
+    kk  = blk;
+
+    for (i = 0; i < 16; i++)
+    {
+        for (j = 0; j < 16; j++)
+        {
+
+            temp = ((p1[j] + p1[j+1] + 1) >> 1) - *kk++;
+            sad += AVC_ABS(temp);
+        }
+
+        NUM_SAD_HP_MB();
+
+        if (sad > (int)((uint32)dmin_rx >> 16))
+            return sad;
+        p1 += rx;
+    }
+    return sad;
+}
+
+#ifdef HTFM  /* HTFM with uniform subsampling implementation,  2/28/01 */
+
+//Checheck here
+int AVCAVCSAD_MB_HP_HTFM_Collectxhyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    int i, j;
+    int sad = 0;
+    uint8 *p1, *p2;
+    int rx = dmin_rx & 0xFFFF;
+    int refwx4 = rx << 2;
+    int saddata[16];      /* used when collecting flag (global) is on */
+    int difmad, tmp, tmp2;
+    int madstar;
+    HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+    int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+    UInt *countbreak = &(htfm_stat->countbreak);
+    int *offsetRef = htfm_stat->offsetRef;
+    uint32 cur_word;
+
+    madstar = (uint32)dmin_rx >> 20;
+
+    NUM_SAD_HP_MB_CALL();
+
+    blk -= 4;
+
+    for (i = 0; i < 16; i++) /* 16 stages */
+    {
+        p1 = ref + offsetRef[i];
+        p2 = p1 + rx;
+
+        j = 4;/* 4 lines */
+        do
+        {
+            cur_word = *((uint32*)(blk += 4));
+            tmp = p1[12] + p2[12];
+            tmp2 = p1[13] + p2[13];
+            tmp += tmp2;
+            tmp2 = (cur_word >> 24) & 0xFF;
+            tmp += 2;
+            sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[8] + p2[8];
+            tmp2 = p1[9] + p2[9];
+            tmp += tmp2;
+            tmp2 = (cur_word >> 16) & 0xFF;
+            tmp += 2;
+            sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[4] + p2[4];
+            tmp2 = p1[5] + p2[5];
+            tmp += tmp2;
+            tmp2 = (cur_word >> 8) & 0xFF;
+            tmp += 2;
+            sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+            tmp2 = p1[1] + p2[1];
+            tmp = p1[0] + p2[0];
+            p1 += refwx4;
+            p2 += refwx4;
+            tmp += tmp2;
+            tmp2 = (cur_word & 0xFF);
+            tmp += 2;
+            sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+        }
+        while (--j);
+
+        NUM_SAD_HP_MB();
+
+        saddata[i] = sad;
+
+        if (i > 0)
+        {
+            if (sad > ((uint32)dmin_rx >> 16))
+            {
+                difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+                (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+                (*countbreak)++;
+                return sad;
+            }
+        }
+    }
+    difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+    (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+    (*countbreak)++;
+
+    return sad;
+}
+
+int AVCAVCSAD_MB_HP_HTFM_Collectyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    int i, j;
+    int sad = 0;
+    uint8 *p1, *p2;
+    int rx = dmin_rx & 0xFFFF;
+    int refwx4 = rx << 2;
+    int saddata[16];      /* used when collecting flag (global) is on */
+    int difmad, tmp, tmp2;
+    int madstar;
+    HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+    int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+    UInt *countbreak = &(htfm_stat->countbreak);
+    int *offsetRef = htfm_stat->offsetRef;
+    uint32 cur_word;
+
+    madstar = (uint32)dmin_rx >> 20;
+
+    NUM_SAD_HP_MB_CALL();
+
+    blk -= 4;
+
+    for (i = 0; i < 16; i++) /* 16 stages */
+    {
+        p1 = ref + offsetRef[i];
+        p2 = p1 + rx;
+        j = 4;
+        do
+        {
+            cur_word = *((uint32*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = p2[12];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 24) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[8];
+            tmp2 = p2[8];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 16) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[4];
+            tmp2 = p2[4];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 8) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[0];
+            p1 += refwx4;
+            tmp2 = p2[0];
+            p2 += refwx4;
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word & 0xFF);
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+        }
+        while (--j);
+
+        NUM_SAD_HP_MB();
+
+        saddata[i] = sad;
+
+        if (i > 0)
+        {
+            if (sad > ((uint32)dmin_rx >> 16))
+            {
+                difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+                (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+                (*countbreak)++;
+                return sad;
+            }
+        }
+    }
+    difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+    (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+    (*countbreak)++;
+
+    return sad;
+}
+
+int AVCAVCSAD_MB_HP_HTFM_Collectxh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    int i, j;
+    int sad = 0;
+    uint8 *p1;
+    int rx = dmin_rx & 0xFFFF;
+    int refwx4 = rx << 2;
+    int saddata[16];      /* used when collecting flag (global) is on */
+    int difmad, tmp, tmp2;
+    int madstar;
+    HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+    int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+    UInt *countbreak = &(htfm_stat->countbreak);
+    int *offsetRef = htfm_stat->offsetRef;
+    uint32 cur_word;
+
+    madstar = (uint32)dmin_rx >> 20;
+
+    NUM_SAD_HP_MB_CALL();
+
+    blk -= 4;
+
+    for (i = 0; i < 16; i++) /* 16 stages */
+    {
+        p1 = ref + offsetRef[i];
+
+        j = 4; /* 4 lines */
+        do
+        {
+            cur_word = *((uint32*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = p1[13];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 24) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[8];
+            tmp2 = p1[9];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 16) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[4];
+            tmp2 = p1[5];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 8) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[0];
+            tmp2 = p1[1];
+            p1 += refwx4;
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word & 0xFF);
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+        }
+        while (--j);
+
+        NUM_SAD_HP_MB();
+
+        saddata[i] = sad;
+
+        if (i > 0)
+        {
+            if (sad > ((uint32)dmin_rx >> 16))
+            {
+                difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+                (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+                (*countbreak)++;
+                return sad;
+            }
+        }
+    }
+    difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+    (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+    (*countbreak)++;
+
+    return sad;
+}
+
+int AVCSAD_MB_HP_HTFMxhyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    int i, j;
+    int sad = 0, tmp, tmp2;
+    uint8 *p1, *p2;
+    int rx = dmin_rx & 0xFFFF;
+    int refwx4 = rx << 2;
+    int sadstar = 0, madstar;
+    int *nrmlz_th = (int*) extra_info;
+    int *offsetRef = nrmlz_th + 32;
+    uint32 cur_word;
+
+    madstar = (uint32)dmin_rx >> 20;
+
+    NUM_SAD_HP_MB_CALL();
+
+    blk -= 4;
+
+    for (i = 0; i < 16; i++) /* 16 stages */
+    {
+        p1 = ref + offsetRef[i];
+        p2 = p1 + rx;
+
+        j = 4; /* 4 lines */
+        do
+        {
+            cur_word = *((uint32*)(blk += 4));
+            tmp = p1[12] + p2[12];
+            tmp2 = p1[13] + p2[13];
+            tmp += tmp2;
+            tmp2 = (cur_word >> 24) & 0xFF;
+            tmp += 2;
+            sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[8] + p2[8];
+            tmp2 = p1[9] + p2[9];
+            tmp += tmp2;
+            tmp2 = (cur_word >> 16) & 0xFF;
+            tmp += 2;
+            sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[4] + p2[4];
+            tmp2 = p1[5] + p2[5];
+            tmp += tmp2;
+            tmp2 = (cur_word >> 8) & 0xFF;
+            tmp += 2;
+            sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+            tmp2 = p1[1] + p2[1];
+            tmp = p1[0] + p2[0];
+            p1 += refwx4;
+            p2 += refwx4;
+            tmp += tmp2;
+            tmp2 = (cur_word & 0xFF);
+            tmp += 2;
+            sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+        }
+        while (--j);
+
+        NUM_SAD_HP_MB();
+
+        sadstar += madstar;
+        if (sad > sadstar - nrmlz_th[i] || sad > ((uint32)dmin_rx >> 16))
+        {
+            return 65536;
+        }
+    }
+
+    return sad;
+}
+
+int AVCSAD_MB_HP_HTFMyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    int i, j;
+    int sad = 0, tmp, tmp2;
+    uint8 *p1, *p2;
+    int rx = dmin_rx & 0xFFFF;
+    int refwx4 = rx << 2;
+    int sadstar = 0, madstar;
+    int *nrmlz_th = (int*) extra_info;
+    int *offsetRef = nrmlz_th + 32;
+    uint32 cur_word;
+
+    madstar = (uint32)dmin_rx >> 20;
+
+    NUM_SAD_HP_MB_CALL();
+
+    blk -= 4;
+
+    for (i = 0; i < 16; i++) /* 16 stages */
+    {
+        p1 = ref + offsetRef[i];
+        p2 = p1 + rx;
+        j = 4;
+        do
+        {
+            cur_word = *((uint32*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = p2[12];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 24) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[8];
+            tmp2 = p2[8];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 16) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[4];
+            tmp2 = p2[4];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 8) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[0];
+            p1 += refwx4;
+            tmp2 = p2[0];
+            p2 += refwx4;
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word & 0xFF);
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+        }
+        while (--j);
+
+        NUM_SAD_HP_MB();
+        sadstar += madstar;
+        if (sad > sadstar - nrmlz_th[i] || sad > ((uint32)dmin_rx >> 16))
+        {
+            return 65536;
+        }
+    }
+
+    return sad;
+}
+
+int AVCSAD_MB_HP_HTFMxh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+    int i, j;
+    int sad = 0, tmp, tmp2;
+    uint8 *p1;
+    int rx = dmin_rx & 0xFFFF;
+    int refwx4 = rx << 2;
+    int sadstar = 0, madstar;
+    int *nrmlz_th = (int*) extra_info;
+    int *offsetRef = nrmlz_th + 32;
+    uint32 cur_word;
+
+    madstar = (uint32)dmin_rx >> 20;
+
+    NUM_SAD_HP_MB_CALL();
+
+    blk -= 4;
+
+    for (i = 0; i < 16; i++) /* 16 stages */
+    {
+        p1 = ref + offsetRef[i];
+
+        j = 4;/* 4 lines */
+        do
+        {
+            cur_word = *((uint32*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = p1[13];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 24) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[8];
+            tmp2 = p1[9];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 16) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[4];
+            tmp2 = p1[5];
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word >> 8) & 0xFF;
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            tmp = p1[0];
+            tmp2 = p1[1];
+            p1 += refwx4;
+            tmp++;
+            tmp2 += tmp;
+            tmp = (cur_word & 0xFF);
+            sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+        }
+        while (--j);
+
+        NUM_SAD_HP_MB();
+
+        sadstar += madstar;
+        if (sad > sadstar - nrmlz_th[i] || sad > ((uint32)dmin_rx >> 16))
+        {
+            return 65536;
+        }
+    }
+
+    return sad;
+}
+
+#endif /* HTFM */
+
+
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/sad_halfpel_inline.h b/media/libstagefright/codecs/avc/enc/src/sad_halfpel_inline.h
new file mode 100644
index 0000000..3a21647
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad_halfpel_inline.h
@@ -0,0 +1,96 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _SAD_HALFPEL_INLINE_H_
+#define _SAD_HALFPEL_INLINE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER  */
+
+    __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        tmp = (tmp2 >> 1) - tmp;
+        if (tmp > 0) sad += tmp;
+        else sad -= tmp;
+
+        return sad;
+    }
+
+    __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        tmp = (tmp >> 2) - tmp2;
+        if (tmp > 0) sad += tmp;
+        else sad -= tmp;
+
+        return sad;
+    }
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+    __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        __asm
+        {
+            rsbs    tmp, tmp, tmp2, asr #1 ;
+            rsbmi   tmp, tmp, #0 ;
+            add     sad, sad, tmp ;
+        }
+
+        return sad;
+    }
+
+    __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        __asm
+        {
+            rsbs    tmp, tmp2, tmp, asr #2 ;
+            rsbmi   tmp, tmp, #0 ;
+            add     sad, sad, tmp ;
+        }
+
+        return sad;
+    }
+
+#elif defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER  */
+
+    __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+__asm__ volatile("rsbs	%1, %1, %2, asr #1\n\trsbmi %1, %1, #0\n\tadd  %0, %0, %1": "=r"(sad), "=r"(tmp): "r"(tmp2));
+
+        return sad;
+    }
+
+    __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+__asm__ volatile("rsbs	%1, %2, %1, asr #2\n\trsbmi %1, %1, #0\n\tadd	%0, %0, %1": "=r"(sad), "=r"(tmp): "r"(tmp2));
+
+        return sad;
+    }
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_SAD_HALFPEL_INLINE_H_
+
diff --git a/media/libstagefright/codecs/avc/enc/src/sad_inline.h b/media/libstagefright/codecs/avc/enc/src/sad_inline.h
new file mode 100644
index 0000000..f39794f
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad_inline.h
@@ -0,0 +1,488 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _SAD_INLINE_H_
+#define _SAD_INLINE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER  */
+
+    __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        tmp = tmp - tmp2;
+        if (tmp > 0) sad += tmp;
+        else sad -= tmp;
+
+        return sad;
+    }
+
+    __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+    {
+        int32 x7;
+
+        x7 = src2 ^ src1;       /* check odd/even combination */
+        if ((uint32)src2 >= (uint32)src1)
+        {
+            src1 = src2 - src1;     /* subs */
+        }
+        else
+        {
+            src1 = src1 - src2;
+        }
+        x7 = x7 ^ src1;     /* only odd bytes need to add carry */
+        x7 = mask & ((uint32)x7 >> 1);
+        x7 = (x7 << 8) - x7;
+        src1 = src1 + (x7 >> 7); /* add 0xFF to the negative byte, add back carry */
+        src1 = src1 ^(x7 >> 7);   /* take absolute value of negative byte */
+
+        return src1;
+    }
+
+#define NUMBER 3
+#define SHIFT 24
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#include "sad_mb_offset.h"
+
+
+    __inline int32 simd_sad_mb(uint8 *ref, uint8 *blk, int dmin, int lx)
+    {
+        int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+        x9 = 0x80808080; /* const. */
+
+        x8 = (uint32)ref & 0x3;
+        if (x8 == 3)
+            goto SadMBOffset3;
+        if (x8 == 2)
+            goto SadMBOffset2;
+        if (x8 == 1)
+            goto SadMBOffset1;
+
+//  x5 = (x4<<8)-x4; /* x5 = x4*255; */
+        x4 = x5 = 0;
+
+        x6 = 0xFFFF00FF;
+
+        ref -= lx;
+        blk -= 16;
+
+        x8 = 16;
+
+LOOP_SAD0:
+        /****** process 8 pixels ******/
+        x10 = *((uint32*)(ref += lx));
+        x11 = *((uint32*)(ref + 4));
+        x12 = *((uint32*)(blk += 16));
+        x14 = *((uint32*)(blk + 4));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10; /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8);  /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****** process 8 pixels ******/
+        x10 = *((uint32*)(ref + 8));
+        x11 = *((uint32*)(ref + 12));
+        x12 = *((uint32*)(blk + 8));
+        x14 = *((uint32*)(blk + 12));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****************/
+        x10 = x5 - (x4 << 8); /* extract low bytes */
+        x10 = x10 + x4;     /* add with high bytes */
+        x10 = x10 + (x10 << 16); /* add with lower half word */
+
+        if ((int)((uint32)x10 >> 16) <= dmin) /* compare with dmin */
+        {
+            if (--x8)
+            {
+                goto LOOP_SAD0;
+            }
+
+        }
+
+        return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+        return sad_mb_offset3(ref, blk, lx, dmin);
+
+SadMBOffset2:
+
+        return sad_mb_offset2(ref, blk, lx, dmin);
+
+SadMBOffset1:
+
+        return sad_mb_offset1(ref, blk, lx, dmin);
+
+    }
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+    __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        __asm
+        {
+            rsbs    tmp, tmp, tmp2 ;
+            rsbmi   tmp, tmp, #0 ;
+            add     sad, sad, tmp ;
+        }
+
+        return sad;
+    }
+
+    __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+    {
+        int32 x7;
+
+        __asm
+        {
+            EOR     x7, src2, src1;     /* check odd/even combination */
+            SUBS    src1, src2, src1;
+            EOR     x7, x7, src1;
+            AND     x7, mask, x7, lsr #1;
+            ORRCC   x7, x7, #0x80000000;
+            RSB     x7, x7, x7, lsl #8;
+            ADD     src1, src1, x7, asr #7;   /* add 0xFF to the negative byte, add back carry */
+            EOR     src1, src1, x7, asr #7;   /* take absolute value of negative byte */
+        }
+
+        return src1;
+    }
+
+    __inline int32 sad_4pixelN(int32 src1, int32 src2, int32 mask)
+    {
+        int32 x7;
+
+        __asm
+        {
+            EOR      x7, src2, src1;        /* check odd/even combination */
+            ADDS     src1, src2, src1;
+            EOR      x7, x7, src1;      /* only odd bytes need to add carry */
+            ANDS     x7, mask, x7, rrx;
+            RSB      x7, x7, x7, lsl #8;
+            SUB      src1, src1, x7, asr #7;  /* add 0xFF to the negative byte, add back carry */
+            EOR      src1, src1, x7, asr #7; /* take absolute value of negative byte */
+        }
+
+        return src1;
+    }
+
+#define sum_accumulate  __asm{      SBC      x5, x5, x10;  /* accumulate low bytes */ \
+        BIC      x10, x6, x10;   /* x10 & 0xFF00FF00 */ \
+        ADD      x4, x4, x10,lsr #8;   /* accumulate high bytes */ \
+        SBC      x5, x5, x11;    /* accumulate low bytes */ \
+        BIC      x11, x6, x11;   /* x11 & 0xFF00FF00 */ \
+        ADD      x4, x4, x11,lsr #8; } /* accumulate high bytes */
+
+
+#define NUMBER 3
+#define SHIFT 24
+#define INC_X8 0x08000001
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#undef INC_X8
+#define INC_X8 0x10000001
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#undef INC_X8
+#define INC_X8 0x08000001
+#include "sad_mb_offset.h"
+
+
+    __inline int32 simd_sad_mb(uint8 *ref, uint8 *blk, int dmin, int lx)
+    {
+        int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+        x9 = 0x80808080; /* const. */
+        x4 = x5 = 0;
+
+        __asm
+        {
+            MOVS    x8, ref, lsl #31 ;
+            BHI     SadMBOffset3;
+            BCS     SadMBOffset2;
+            BMI     SadMBOffset1;
+
+            MVN     x6, #0xFF00;
+        }
+LOOP_SAD0:
+        /****** process 8 pixels ******/
+        x11 = *((int32*)(ref + 12));
+        x10 = *((int32*)(ref + 8));
+        x14 = *((int32*)(blk + 12));
+        x12 = *((int32*)(blk + 8));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        __asm
+        {
+            /****** process 8 pixels ******/
+            LDR     x11, [ref, #4];
+            LDR     x10, [ref], lx ;
+            LDR     x14, [blk, #4];
+            LDR     x12, [blk], #16 ;
+        }
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****************/
+        x10 = x5 - (x4 << 8); /* extract low bytes */
+        x10 = x10 + x4;     /* add with high bytes */
+        x10 = x10 + (x10 << 16); /* add with lower half word */
+
+        __asm
+        {
+            /****************/
+            RSBS    x11, dmin, x10, lsr #16;
+            ADDLSS  x8, x8, #0x10000001;
+            BLS     LOOP_SAD0;
+        }
+
+        return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+        return sad_mb_offset3(ref, blk, lx, dmin, x8);
+
+SadMBOffset2:
+
+        return sad_mb_offset2(ref, blk, lx, dmin, x8);
+
+SadMBOffset1:
+
+        return sad_mb_offset1(ref, blk, lx, dmin, x8);
+    }
+
+
+#elif defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER  */
+
+    __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+__asm__ volatile("rsbs	%1, %1, %2\n\trsbmi %1, %1, #0\n\tadd	%0, %0, %1": "=r"(sad): "r"(tmp), "r"(tmp2));
+        return sad;
+    }
+
+    __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+    {
+        int32 x7;
+
+__asm__ volatile("EOR	%1, %2, %0\n\tSUBS  %0, %2, %0\n\tEOR	%1, %1, %0\n\tAND  %1, %3, %1, lsr #1\n\tORRCC	%1, %1, #0x80000000\n\tRSB  %1, %1, %1, lsl #8\n\tADD  %0, %0, %1, asr #7\n\tEOR  %0, %0, %1, asr #7": "=r"(src1), "=&r"(x7): "r"(src2), "r"(mask));
+
+        return src1;
+    }
+
+    __inline int32 sad_4pixelN(int32 src1, int32 src2, int32 mask)
+    {
+        int32 x7;
+
+__asm__ volatile("EOR	%1, %2, %0\n\tADDS  %0, %2, %0\n\tEOR  %1, %1, %0\n\tANDS  %1, %3, %1, rrx\n\tRSB  %1, %1, %1, lsl #8\n\tSUB	%0, %0, %1, asr #7\n\tEOR   %0, %0, %1, asr #7": "=r"(src1), "=&r"(x7): "r"(src2), "r"(mask));
+
+        return src1;
+    }
+
+#define sum_accumulate  __asm__ volatile("SBC  %0, %0, %1\n\tBIC   %1, %4, %1\n\tADD   %2, %2, %1, lsr #8\n\tSBC   %0, %0, %3\n\tBIC   %3, %4, %3\n\tADD   %2, %2, %3, lsr #8": "=&r" (x5), "=&r" (x10), "=&r" (x4), "=&r" (x11): "r" (x6));
+
+#define NUMBER 3
+#define SHIFT 24
+#define INC_X8 0x08000001
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#undef INC_X8
+#define INC_X8 0x10000001
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#undef INC_X8
+#define INC_X8 0x08000001
+#include "sad_mb_offset.h"
+
+
+    __inline int32 simd_sad_mb(uint8 *ref, uint8 *blk, int dmin, int lx)
+    {
+        int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+        x9 = 0x80808080; /* const. */
+        x4 = x5 = 0;
+
+        x8 = (uint32)ref & 0x3;
+        if (x8 == 3)
+            goto SadMBOffset3;
+        if (x8 == 2)
+            goto SadMBOffset2;
+        if (x8 == 1)
+            goto SadMBOffset1;
+
+        x8 = 16;
+///
+__asm__ volatile("MVN	%0, #0xFF00": "=r"(x6));
+
+LOOP_SAD0:
+        /****** process 8 pixels ******/
+        x11 = *((int32*)(ref + 12));
+        x10 = *((int32*)(ref + 8));
+        x14 = *((int32*)(blk + 12));
+        x12 = *((int32*)(blk + 8));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****** process 8 pixels ******/
+        x11 = *((int32*)(ref + 4));
+__asm__ volatile("LDR	%0, [%1], %2": "=&r"(x10), "=r"(ref): "r"(lx));
+        //x10 = *((int32*)ref); ref+=lx;
+        x14 = *((int32*)(blk + 4));
+__asm__ volatile("LDR	%0, [%1], #16": "=&r"(x12), "=r"(blk));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****************/
+        x10 = x5 - (x4 << 8); /* extract low bytes */
+        x10 = x10 + x4;     /* add with high bytes */
+        x10 = x10 + (x10 << 16); /* add with lower half word */
+
+        /****************/
+
+        if (((uint32)x10 >> 16) <= dmin) /* compare with dmin */
+        {
+            if (--x8)
+            {
+                goto LOOP_SAD0;
+            }
+
+        }
+
+        return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+        return sad_mb_offset3(ref, blk, lx, dmin);
+
+SadMBOffset2:
+
+        return sad_mb_offset2(ref, blk, lx, dmin);
+
+SadMBOffset1:
+
+        return sad_mb_offset1(ref, blk, lx, dmin);
+    }
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _SAD_INLINE_H_
+
diff --git a/media/libstagefright/codecs/avc/enc/src/sad_mb_offset.h b/media/libstagefright/codecs/avc/enc/src/sad_mb_offset.h
new file mode 100644
index 0000000..d5d4a42
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad_mb_offset.h
@@ -0,0 +1,311 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+#if defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER  */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(uint8 *ref, uint8 *blk, int lx, int dmin)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(uint8 *ref, uint8 *blk, int lx, int dmin)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(uint8 *ref, uint8 *blk, int lx, int dmin)
+#endif
+{
+    int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+    //  x5 = (x4<<8) - x4;
+    x4 = x5 = 0;
+    x6 = 0xFFFF00FF;
+    x9 = 0x80808080; /* const. */
+    ref -= NUMBER; /* bic ref, ref, #3 */
+    ref -= lx;
+    blk -= 16;
+    x8 = 16;
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+    /****** process 8 pixels ******/
+    x10 = *((uint32*)(ref += lx)); /* D C B A */
+    x11 = *((uint32*)(ref + 4));    /* H G F E */
+    x12 = *((uint32*)(ref + 8));    /* L K J I */
+
+    x10 = ((uint32)x10 >> SHIFT); /* 0 0 0 D */
+    x10 = x10 | (x11 << (32 - SHIFT));        /* G F E D */
+    x11 = ((uint32)x11 >> SHIFT); /* 0 0 0 H */
+    x11 = x11 | (x12 << (32 - SHIFT));        /* K J I H */
+
+    x12 = *((uint32*)(blk += 16));
+    x14 = *((uint32*)(blk + 4));
+
+    /* process x11 & x14 */
+    x11 = sad_4pixel(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixel(x10, x12, x9);
+
+    x5 = x5 + x10; /* accumulate low bytes */
+    x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+    x4 = x4 + ((uint32)x10 >> 8);  /* accumulate high bytes */
+    x5 = x5 + x11;  /* accumulate low bytes */
+    x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+    x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+    /****** process 8 pixels ******/
+    x10 = *((uint32*)(ref + 8)); /* D C B A */
+    x11 = *((uint32*)(ref + 12));   /* H G F E */
+    x12 = *((uint32*)(ref + 16));   /* L K J I */
+
+    x10 = ((uint32)x10 >> SHIFT); /* mvn x10, x10, lsr #24  = 0xFF 0xFF 0xFF ~D */
+    x10 = x10 | (x11 << (32 - SHIFT));        /* bic x10, x10, x11, lsl #8 = ~G ~F ~E ~D */
+    x11 = ((uint32)x11 >> SHIFT); /* 0xFF 0xFF 0xFF ~H */
+    x11 = x11 | (x12 << (32 - SHIFT));        /* ~K ~J ~I ~H */
+
+    x12 = *((uint32*)(blk + 8));
+    x14 = *((uint32*)(blk + 12));
+
+    /* process x11 & x14 */
+    x11 = sad_4pixel(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixel(x10, x12, x9);
+
+    x5 = x5 + x10; /* accumulate low bytes */
+    x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+    x4 = x4 + ((uint32)x10 >> 8);  /* accumulate high bytes */
+    x5 = x5 + x11;  /* accumulate low bytes */
+    x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+    x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+    /****************/
+    x10 = x5 - (x4 << 8); /* extract low bytes */
+    x10 = x10 + x4;     /* add with high bytes */
+    x10 = x10 + (x10 << 16); /* add with lower half word */
+
+    if ((int)((uint32)x10 >> 16) <= dmin) /* compare with dmin */
+    {
+        if (--x8)
+        {
+#if (NUMBER==3)
+            goto         LOOP_SAD3;
+#elif (NUMBER==2)
+            goto         LOOP_SAD2;
+#elif (NUMBER==1)
+            goto         LOOP_SAD1;
+#endif
+        }
+
+    }
+
+    return ((uint32)x10 >> 16);
+}
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(uint8 *ref, uint8 *blk, int lx, int dmin, int32 x8)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(uint8 *ref, uint8 *blk, int lx, int dmin, int32 x8)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(uint8 *ref, uint8 *blk, int lx, int dmin, int32 x8)
+#endif
+{
+    int32 x4, x5, x6, x9, x10, x11, x12, x14;
+
+    x9 = 0x80808080; /* const. */
+    x4 = x5 = 0;
+
+    __asm{
+        MVN      x6, #0xff0000;
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+        BIC      ref, ref, #3;
+    }
+    /****** process 8 pixels ******/
+    x11 = *((int32*)(ref + 12));
+    x12 = *((int32*)(ref + 16));
+    x10 = *((int32*)(ref + 8));
+    x14 = *((int32*)(blk + 12));
+
+    __asm{
+        MVN      x10, x10, lsr #SHIFT;
+        BIC      x10, x10, x11, lsl #(32-SHIFT);
+        MVN      x11, x11, lsr #SHIFT;
+        BIC      x11, x11, x12, lsl #(32-SHIFT);
+
+        LDR      x12, [blk, #8];
+    }
+
+    /* process x11 & x14 */
+    x11 = sad_4pixelN(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixelN(x10, x12, x9);
+
+    sum_accumulate;
+
+    __asm{
+        /****** process 8 pixels ******/
+        LDR      x11, [ref, #4];
+        LDR      x12, [ref, #8];
+        LDR  x10, [ref], lx ;
+        LDR  x14, [blk, #4];
+
+        MVN      x10, x10, lsr #SHIFT;
+        BIC      x10, x10, x11, lsl #(32-SHIFT);
+        MVN      x11, x11, lsr #SHIFT;
+        BIC      x11, x11, x12, lsl #(32-SHIFT);
+
+        LDR      x12, [blk], #16;
+    }
+
+    /* process x11 & x14 */
+    x11 = sad_4pixelN(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixelN(x10, x12, x9);
+
+    sum_accumulate;
+
+    /****************/
+    x10 = x5 - (x4 << 8); /* extract low bytes */
+    x10 = x10 + x4;     /* add with high bytes */
+    x10 = x10 + (x10 << 16); /* add with lower half word */
+
+    __asm{
+        RSBS     x11, dmin, x10, lsr #16
+        ADDLSS   x8, x8, #INC_X8
+#if (NUMBER==3)
+        BLS      LOOP_SAD3;
+#elif (NUMBER==2)
+BLS      LOOP_SAD2;
+#elif (NUMBER==1)
+BLS      LOOP_SAD1;
+#endif
+    }
+
+    return ((uint32)x10 >> 16);
+}
+
+#elif defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER  */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(uint8 *ref, uint8 *blk, int lx, int dmin)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(uint8 *ref, uint8 *blk, int lx, int dmin)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(uint8 *ref, uint8 *blk, int lx, int dmin)
+#endif
+{
+    int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+    x9 = 0x80808080; /* const. */
+    x4 = x5 = 0;
+    x8 = 16; //<<===========*******
+
+__asm__ volatile("MVN	%0, #0xFF0000": "=r"(x6));
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+__asm__ volatile("BIC  %0, %0, #3": "=r"(ref));
+    /****** process 8 pixels ******/
+    x11 = *((int32*)(ref + 12));
+    x12 = *((int32*)(ref + 16));
+    x10 = *((int32*)(ref + 8));
+    x14 = *((int32*)(blk + 12));
+
+#if (SHIFT==8)
+__asm__ volatile("MVN   %0, %0, lsr #8\n\tBIC   %0, %0, %1,lsl #24\n\tMVN   %1, %1,lsr #8\n\tBIC   %1, %1, %2,lsl #24": "=&r"(x10), "=&r"(x11): "r"(x12));
+#elif (SHIFT==16)
+__asm__ volatile("MVN   %0, %0, lsr #16\n\tBIC   %0, %0, %1,lsl #16\n\tMVN   %1, %1,lsr #16\n\tBIC   %1, %1, %2,lsl #16": "=&r"(x10), "=&r"(x11): "r"(x12));
+#elif (SHIFT==24)
+__asm__ volatile("MVN   %0, %0, lsr #24\n\tBIC   %0, %0, %1,lsl #8\n\tMVN   %1, %1,lsr #24\n\tBIC   %1, %1, %2,lsl #8": "=&r"(x10), "=&r"(x11): "r"(x12));
+#endif
+
+    x12 = *((int32*)(blk + 8));
+
+    /* process x11 & x14 */
+    x11 = sad_4pixelN(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixelN(x10, x12, x9);
+
+    sum_accumulate;
+
+    /****** process 8 pixels ******/
+    x11 = *((int32*)(ref + 4));
+    x12 = *((int32*)(ref + 8));
+    x10 = *((int32*)ref); ref += lx;
+    x14 = *((int32*)(blk + 4));
+
+#if (SHIFT==8)
+__asm__ volatile("MVN   %0, %0, lsr #8\n\tBIC   %0, %0, %1,lsl #24\n\tMVN   %1, %1,lsr #8\n\tBIC   %1, %1, %2,lsl #24": "=&r"(x10), "=&r"(x11): "r"(x12));
+#elif (SHIFT==16)
+__asm__ volatile("MVN   %0, %0, lsr #16\n\tBIC   %0, %0, %1,lsl #16\n\tMVN   %1, %1,lsr #16\n\tBIC   %1, %1, %2,lsl #16": "=&r"(x10), "=&r"(x11): "r"(x12));
+#elif (SHIFT==24)
+__asm__ volatile("MVN   %0, %0, lsr #24\n\tBIC   %0, %0, %1,lsl #8\n\tMVN   %1, %1,lsr #24\n\tBIC   %1, %1, %2,lsl #8": "=&r"(x10), "=&r"(x11): "r"(x12));
+#endif
+__asm__ volatile("LDR   %0, [%1], #16": "=&r"(x12), "=r"(blk));
+
+    /* process x11 & x14 */
+    x11 = sad_4pixelN(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixelN(x10, x12, x9);
+
+    sum_accumulate;
+
+    /****************/
+    x10 = x5 - (x4 << 8); /* extract low bytes */
+    x10 = x10 + x4;     /* add with high bytes */
+    x10 = x10 + (x10 << 16); /* add with lower half word */
+
+    if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+    {
+        if (--x8)
+        {
+#if (NUMBER==3)
+            goto         LOOP_SAD3;
+#elif (NUMBER==2)
+goto         LOOP_SAD2;
+#elif (NUMBER==1)
+goto         LOOP_SAD1;
+#endif
+        }
+
+    }
+
+    return ((uint32)x10 >> 16);
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/avc/enc/src/slice.cpp b/media/libstagefright/codecs/avc/enc/src/slice.cpp
new file mode 100644
index 0000000..f6d066e
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/slice.cpp
@@ -0,0 +1,1025 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+
+AVCEnc_Status AVCEncodeSlice(AVCEncObject *encvid)
+{
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    AVCCommonObj *video = encvid->common;
+    AVCPicParamSet *pps = video->currPicParams;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    AVCMacroblock *currMB ;
+    AVCEncBitstream *stream = encvid->bitstream;
+    uint slice_group_id;
+    int CurrMbAddr, slice_type;
+
+    slice_type = video->slice_type;
+
+    /* set the first mb in slice */
+    video->mbNum = CurrMbAddr = sliceHdr->first_mb_in_slice;// * (1+video->MbaffFrameFlag);
+    slice_group_id = video->MbToSliceGroupMap[CurrMbAddr];
+
+    video->mb_skip_run = 0;
+
+    /* while loop , see subclause 7.3.4 */
+    while (1)
+    {
+        video->mbNum = CurrMbAddr;
+        currMB = video->currMB = &(video->mblock[CurrMbAddr]);
+        currMB->slice_id = video->slice_id;  // for deblocking
+
+        video->mb_x = CurrMbAddr % video->PicWidthInMbs;
+        video->mb_y = CurrMbAddr / video->PicWidthInMbs;
+
+        /* initialize QP for this MB here*/
+        /* calculate currMB->QPy */
+        RCInitMBQP(encvid);
+
+        /* check the availability of neighboring macroblocks */
+        InitNeighborAvailability(video, CurrMbAddr);
+
+        /* Assuming that InitNeighborAvailability has been called prior to this function */
+        video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
+        /* this is necessary for all subsequent intra search */
+
+        if (!video->currPicParams->constrained_intra_pred_flag)
+        {
+            video->intraAvailA = video->mbAvailA;
+            video->intraAvailB = video->mbAvailB;
+            video->intraAvailC = video->mbAvailC;
+            video->intraAvailD = video->mbAvailD;
+        }
+        else
+        {
+            if (video->mbAvailA)
+            {
+                video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
+            }
+            if (video->mbAvailB)
+            {
+                video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
+            }
+            if (video->mbAvailC)
+            {
+                video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
+            }
+            if (video->mbAvailD)
+            {
+                video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
+            }
+        }
+
+        /* encode_one_macroblock() */
+        status = EncodeMB(encvid);
+        if (status != AVCENC_SUCCESS)
+        {
+            break;
+        }
+
+        /* go to next MB */
+        CurrMbAddr++;
+
+        while ((uint)video->MbToSliceGroupMap[CurrMbAddr] != slice_group_id &&
+                (uint)CurrMbAddr < video->PicSizeInMbs)
+        {
+            CurrMbAddr++;
+        }
+
+        if ((uint)CurrMbAddr >= video->PicSizeInMbs)
+        {
+            /* end of slice, return, but before that check to see if there are other slices
+            to be encoded. */
+            encvid->currSliceGroup++;
+            if (encvid->currSliceGroup > (int)pps->num_slice_groups_minus1) /* no more slice group */
+            {
+                status = AVCENC_PICTURE_READY;
+                break;
+            }
+            else
+            {
+                /* find first_mb_num for the next slice */
+                CurrMbAddr = 0;
+                while (video->MbToSliceGroupMap[CurrMbAddr] != encvid->currSliceGroup &&
+                        (uint)CurrMbAddr < video->PicSizeInMbs)
+                {
+                    CurrMbAddr++;
+                }
+                if ((uint)CurrMbAddr >= video->PicSizeInMbs)
+                {
+                    status = AVCENC_SLICE_EMPTY; /* error, one slice group has no MBs in it */
+                }
+
+                video->mbNum = CurrMbAddr;
+                status = AVCENC_SUCCESS;
+                break;
+            }
+        }
+    }
+
+    if (video->mb_skip_run > 0)
+    {
+        /* write skip_run */
+        if (slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE)
+        {
+            ue_v(stream, video->mb_skip_run);
+            video->mb_skip_run = 0;
+        }
+        else    /* shouldn't happen */
+        {
+            status = AVCENC_FAIL;
+        }
+    }
+
+    return status;
+}
+
+
+AVCEnc_Status EncodeMB(AVCEncObject *encvid)
+{
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    AVCCommonObj *video = encvid->common;
+    AVCPictureData *currPic = video->currPic;
+    AVCFrameIO  *currInput = encvid->currInput;
+    AVCMacroblock *currMB = video->currMB;
+    AVCMacroblock *MB_A, *MB_B;
+    AVCEncBitstream *stream = encvid->bitstream;
+    AVCRateControl *rateCtrl = encvid->rateCtrl;
+    uint8 *cur, *curL, *curCb, *curCr;
+    uint8 *orgL, *orgCb, *orgCr, *org4;
+    int CurrMbAddr = video->mbNum;
+    int picPitch = currPic->pitch;
+    int orgPitch = currInput->pitch;
+    int x_position = (video->mb_x << 4);
+    int y_position = (video->mb_y << 4);
+    int offset;
+    int b8, b4, blkidx;
+    AVCResidualType  resType;
+    int slice_type;
+    int numcoeff; /* output from residual_block_cavlc */
+    int cost16, cost8;
+
+    int num_bits, start_mb_bits, start_text_bits;
+
+    slice_type = video->slice_type;
+
+    /* now, point to the reconstructed frame */
+    offset = y_position * picPitch + x_position;
+    curL = currPic->Sl + offset;
+    orgL = currInput->YCbCr[0] + offset;
+    offset = (offset + x_position) >> 2;
+    curCb = currPic->Scb + offset;
+    curCr = currPic->Scr + offset;
+    orgCb = currInput->YCbCr[1] + offset;
+    orgCr = currInput->YCbCr[2] + offset;
+
+    if (orgPitch != picPitch)
+    {
+        offset = y_position * (orgPitch - picPitch);
+        orgL += offset;
+        offset >>= 2;
+        orgCb += offset;
+        orgCr += offset;
+    }
+
+    /******* determine MB prediction mode *******/
+    if (encvid->intraSearch[CurrMbAddr])
+    {
+        MBIntraSearch(encvid, CurrMbAddr, curL, picPitch);
+    }
+    /******* This part should be determined somehow ***************/
+    if (currMB->mbMode == AVC_I_PCM)
+    {
+        /* write down mb_type and PCM data */
+        /* and copy from currInput to currPic */
+        status = EncodeIntraPCM(encvid);
+
+
+        return status;
+    }
+
+    /****** for intra prediction, pred is already done *******/
+    /****** for I4, the recon is ready and Xfrm coefs are ready to be encoded *****/
+
+    //RCCalculateMAD(encvid,currMB,orgL,orgPitch); // no need to re-calculate MAD for Intra
+    // not used since totalSAD is used instead
+
+    /* compute the prediction */
+    /* output is video->pred_block */
+    if (!currMB->mb_intra)
+    {
+        AVCMBMotionComp(encvid, video); /* perform prediction and residue calculation */
+        /* we can do the loop here and call dct_luma */
+        video->pred_pitch = picPitch;
+        currMB->CBP = 0;
+        cost16 = 0;
+        cur = curL;
+        org4 = orgL;
+
+        for (b8 = 0; b8 < 4; b8++)
+        {
+            cost8 = 0;
+
+            for (b4 = 0; b4 < 4; b4++)
+            {
+                blkidx = blkIdx2blkXY[b8][b4];
+                video->pred_block = cur;
+                numcoeff = dct_luma(encvid, blkidx, cur, org4, &cost8);
+                currMB->nz_coeff[blkidx] = numcoeff;
+                if (numcoeff)
+                {
+                    video->cbp4x4 |= (1 << blkidx);
+                    currMB->CBP |= (1 << b8);
+                }
+
+                if (b4&1)
+                {
+                    cur += ((picPitch << 2) - 4);
+                    org4 += ((orgPitch << 2) - 4);
+                }
+                else
+                {
+                    cur += 4;
+                    org4 += 4;
+                }
+            }
+
+            /* move the IDCT part out of dct_luma to accommodate the check
+               for coeff_cost. */
+
+            if ((currMB->CBP&(1 << b8)) && (cost8 <= _LUMA_COEFF_COST_))
+            {
+                cost8 = 0; // reset it
+
+                currMB->CBP ^= (1 << b8);
+                blkidx = blkIdx2blkXY[b8][0];
+
+                currMB->nz_coeff[blkidx] = 0;
+                currMB->nz_coeff[blkidx+1] = 0;
+                currMB->nz_coeff[blkidx+4] = 0;
+                currMB->nz_coeff[blkidx+5] = 0;
+            }
+
+            cost16 += cost8;
+
+            if (b8&1)
+            {
+                cur -= 8;
+                org4 -= 8;
+            }
+            else
+            {
+                cur += (8 - (picPitch << 3));
+                org4 += (8 - (orgPitch << 3));
+            }
+        }
+
+        /* after the whole MB, we do another check for coeff_cost */
+        if ((currMB->CBP&0xF) && (cost16 <= _LUMA_MB_COEFF_COST_))
+        {
+            currMB->CBP = 0;  // reset it to zero
+            memset(currMB->nz_coeff, 0, sizeof(uint8)*16);
+        }
+
+        // now we do IDCT
+        MBInterIdct(video, curL, currMB, picPitch);
+
+//      video->pred_block = video->pred + 256;
+    }
+    else    /* Intra prediction */
+    {
+        encvid->numIntraMB++;
+
+        if (currMB->mbMode == AVC_I16) /* do prediction for the whole macroblock */
+        {
+            currMB->CBP = 0;
+            /* get the prediction from encvid->pred_i16 */
+            dct_luma_16x16(encvid, curL, orgL);
+        }
+        video->pred_block = encvid->pred_ic[currMB->intra_chroma_pred_mode];
+    }
+
+    /* chrominance */
+    /* not need to do anything, the result is in encvid->pred_ic
+    chroma dct must be aware that prediction block can come from either intra or inter. */
+
+    dct_chroma(encvid, curCb, orgCb, 0);
+
+    dct_chroma(encvid, curCr, orgCr, 1);
+
+
+    /* 4.1 if there's nothing in there, video->mb_skip_run++ */
+    /* 4.2 if coded, check if there is a run of skipped MB, encodes it,
+            set video->QPyprev = currMB->QPy; */
+
+    /* 5. vlc encode */
+
+    /* check for skipped macroblock, INTER only */
+    if (!currMB->mb_intra)
+    {
+        /* decide whether this MB (for inter MB) should be skipped if there's nothing left. */
+        if (!currMB->CBP && currMB->NumMbPart == 1 && currMB->QPy == video->QPy)
+        {
+            if (currMB->MBPartPredMode[0][0] == AVC_Pred_L0 && currMB->ref_idx_L0[0] == 0)
+            {
+                MB_A = &video->mblock[video->mbAddrA];
+                MB_B = &video->mblock[video->mbAddrB];
+
+                if (!video->mbAvailA || !video->mbAvailB)
+                {
+                    if (currMB->mvL0[0] == 0) /* both mv components are zeros.*/
+                    {
+                        currMB->mbMode = AVC_SKIP;
+                        video->mvd_l0[0][0][0] = 0;
+                        video->mvd_l0[0][0][1] = 0;
+                    }
+                }
+                else
+                {
+                    if ((MB_A->ref_idx_L0[1] == 0 && MB_A->mvL0[3] == 0) ||
+                            (MB_B->ref_idx_L0[2] == 0 && MB_B->mvL0[12] == 0))
+                    {
+                        if (currMB->mvL0[0] == 0) /* both mv components are zeros.*/
+                        {
+                            currMB->mbMode = AVC_SKIP;
+                            video->mvd_l0[0][0][0] = 0;
+                            video->mvd_l0[0][0][1] = 0;
+                        }
+                    }
+                    else if (video->mvd_l0[0][0][0] == 0 && video->mvd_l0[0][0][1] == 0)
+                    {
+                        currMB->mbMode = AVC_SKIP;
+                    }
+                }
+            }
+
+            if (currMB->mbMode == AVC_SKIP)
+            {
+                video->mb_skip_run++;
+
+                /* set parameters */
+                /* not sure whether we need the followings */
+                if (slice_type == AVC_P_SLICE)
+                {
+                    currMB->mbMode = AVC_SKIP;
+                    currMB->MbPartWidth = currMB->MbPartHeight = 16;
+                    currMB->MBPartPredMode[0][0] = AVC_Pred_L0;
+                    currMB->NumMbPart = 1;
+                    currMB->NumSubMbPart[0] = currMB->NumSubMbPart[1] =
+                                                  currMB->NumSubMbPart[2] = currMB->NumSubMbPart[3] = 1;
+                    currMB->SubMbPartWidth[0] = currMB->SubMbPartWidth[1] =
+                                                    currMB->SubMbPartWidth[2] = currMB->SubMbPartWidth[3] = currMB->MbPartWidth;
+                    currMB->SubMbPartHeight[0] = currMB->SubMbPartHeight[1] =
+                                                     currMB->SubMbPartHeight[2] = currMB->SubMbPartHeight[3] = currMB->MbPartHeight;
+
+                }
+                else if (slice_type == AVC_B_SLICE)
+                {
+                    currMB->mbMode = AVC_SKIP;
+                    currMB->MbPartWidth = currMB->MbPartHeight = 8;
+                    currMB->MBPartPredMode[0][0] = AVC_Direct;
+                    currMB->NumMbPart = -1;
+                }
+
+                /* for skipped MB, always look at the first entry in RefPicList */
+                currMB->RefIdx[0] = currMB->RefIdx[1] =
+                                        currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[0]->RefIdx;
+
+                /* do not return yet, need to do some copies */
+            }
+        }
+    }
+    /* non-skipped MB */
+
+
+    /************* START ENTROPY CODING *************************/
+
+    start_mb_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
+
+    /* encode mb_type, mb_pred, sub_mb_pred, CBP */
+    if (slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE && currMB->mbMode != AVC_SKIP)
+    {
+        //if(!pps->entropy_coding_mode_flag)  ALWAYS true
+        {
+            ue_v(stream, video->mb_skip_run);
+            video->mb_skip_run = 0;
+        }
+    }
+
+    if (currMB->mbMode != AVC_SKIP)
+    {
+        status = EncodeMBHeader(currMB, encvid);
+        if (status != AVCENC_SUCCESS)
+        {
+            return status;
+        }
+    }
+
+    start_text_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
+
+    /**** now decoding part *******/
+    resType = AVC_Luma;
+
+    /* DC transform for luma I16 mode */
+    if (currMB->mbMode == AVC_I16)
+    {
+        /* vlc encode level/run */
+        status = enc_residual_block(encvid, AVC_Intra16DC, encvid->numcoefdc, currMB);
+        if (status != AVCENC_SUCCESS)
+        {
+            return status;
+        }
+        resType = AVC_Intra16AC;
+    }
+
+    /* VLC encoding for luma */
+    for (b8 = 0; b8 < 4; b8++)
+    {
+        if (currMB->CBP&(1 << b8))
+        {
+            for (b4 = 0; b4 < 4; b4++)
+            {
+                /* vlc encode level/run */
+                status = enc_residual_block(encvid, resType, (b8 << 2) + b4, currMB);
+                if (status != AVCENC_SUCCESS)
+                {
+                    return status;
+                }
+            }
+        }
+    }
+
+    /* chroma */
+    if (currMB->CBP & (3 << 4)) /* chroma DC residual present */
+    {
+        for (b8 = 0; b8 < 2; b8++) /* for iCbCr */
+        {
+            /* vlc encode level/run */
+            status = enc_residual_block(encvid, AVC_ChromaDC, encvid->numcoefcdc[b8] + (b8 << 3), currMB);
+            if (status != AVCENC_SUCCESS)
+            {
+                return status;
+            }
+        }
+    }
+
+    if (currMB->CBP & (2 << 4))
+    {
+        /* AC part */
+        for (b8 = 0; b8 < 2; b8++) /* for iCbCr */
+        {
+            for (b4 = 0; b4 < 4; b4++)  /* for each block inside Cb or Cr */
+            {
+                /* vlc encode level/run */
+                status = enc_residual_block(encvid, AVC_ChromaAC, 16 + (b8 << 2) + b4, currMB);
+                if (status != AVCENC_SUCCESS)
+                {
+                    return status;
+                }
+            }
+        }
+    }
+
+
+    num_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
+
+    RCPostMB(video, rateCtrl, start_text_bits - start_mb_bits,
+             num_bits - start_text_bits);
+
+//  num_bits -= start_mb_bits;
+//  fprintf(fdebug,"MB #%d: %d bits\n",CurrMbAddr,num_bits);
+//  fclose(fdebug);
+    return status;
+}
+
+/* copy the content from predBlock back to the reconstructed YUV frame */
+void Copy_MB(uint8 *curL, uint8 *curCb, uint8 *curCr, uint8 *predBlock, int picPitch)
+{
+    int j, offset;
+    uint32 *dst, *dst2, *src;
+
+    dst = (uint32*)curL;
+    src = (uint32*)predBlock;
+
+    offset = (picPitch - 16) >> 2;
+
+    for (j = 0; j < 16; j++)
+    {
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst++ = *src++;
+
+        dst += offset;
+    }
+
+    dst = (uint32*)curCb;
+    dst2 = (uint32*)curCr;
+    offset >>= 1;
+
+    for (j = 0; j < 8; j++)
+    {
+        *dst++ = *src++;
+        *dst++ = *src++;
+        *dst2++ = *src++;
+        *dst2++ = *src++;
+
+        dst += offset;
+        dst2 += offset;
+    }
+    return ;
+}
+
+/* encode mb_type, mb_pred, sub_mb_pred, CBP */
+/* decide whether this MB (for inter MB) should be skipped */
+AVCEnc_Status EncodeMBHeader(AVCMacroblock *currMB, AVCEncObject *encvid)
+{
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    uint mb_type;
+    AVCCommonObj *video = encvid->common;
+    AVCEncBitstream *stream = encvid->bitstream;
+
+    if (currMB->CBP > 47)   /* chroma CBP is 11 */
+    {
+        currMB->CBP -= 16;  /* remove the 5th bit from the right */
+    }
+
+    mb_type = InterpretMBType(currMB, video->slice_type);
+
+    status = ue_v(stream, mb_type);
+
+    if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0)
+    {
+        status = sub_mb_pred(video, currMB, stream);
+    }
+    else
+    {
+        status = mb_pred(video, currMB, stream) ;
+    }
+
+    if (currMB->mbMode != AVC_I16)
+    {
+        /* decode coded_block_pattern */
+        status = EncodeCBP(currMB, stream);
+    }
+
+    /* calculate currMB->mb_qp_delta = currMB->QPy - video->QPyprev */
+    if (currMB->CBP > 0 || currMB->mbMode == AVC_I16)
+    {
+        status = se_v(stream, currMB->QPy - video->QPy);
+        video->QPy = currMB->QPy; /* = (video->QPyprev + currMB->mb_qp_delta + 52)%52; */
+        // no need video->QPc = currMB->QPc;
+    }
+    else
+    {
+        if (currMB->QPy != video->QPy) // current QP is not the same as previous QP
+        {
+            /* restore these values */
+            RCRestoreQP(currMB, video, encvid);
+        }
+    }
+
+    return status;
+}
+
+
+/* inputs are mbMode, mb_intra, i16Mode, CBP, NumMbPart, MbPartWidth, MbPartHeight */
+uint InterpretMBType(AVCMacroblock *currMB, int slice_type)
+{
+    int CBP_chrom;
+    int mb_type;// part1, part2, part3;
+//  const static int MapParts2Type[2][3][3]={{{4,8,12},{10,6,14},{16,18,20}},
+//  {{5,9,13},{11,7,15},{17,19,21}}};
+
+    if (currMB->mb_intra)
+    {
+        if (currMB->mbMode == AVC_I4)
+        {
+            mb_type = 0;
+        }
+        else if (currMB->mbMode == AVC_I16)
+        {
+            CBP_chrom = (currMB->CBP & 0x30);
+            if (currMB->CBP&0xF)
+            {
+                currMB->CBP |= 0xF;  /* either 0x0 or 0xF */
+                mb_type = 13;
+            }
+            else
+            {
+                mb_type = 1;
+            }
+            mb_type += (CBP_chrom >> 2) + currMB->i16Mode;
+        }
+        else /* if(currMB->mbMode == AVC_I_PCM) */
+        {
+            mb_type = 25;
+        }
+    }
+    else
+    {  /* P-MB *//* note that the order of the enum AVCMBMode cannot be changed
+        since we use it here. */
+        mb_type = currMB->mbMode - AVC_P16;
+    }
+
+    if (slice_type == AVC_P_SLICE)
+    {
+        if (currMB->mb_intra)
+        {
+            mb_type += 5;
+        }
+    }
+    // following codes have not been tested yet, not needed.
+    /*  else if(slice_type == AVC_B_SLICE)
+        {
+            if(currMB->mbMode == AVC_BDirect16)
+            {
+                mb_type = 0;
+            }
+            else if(currMB->mbMode == AVC_P16)
+            {
+                mb_type = currMB->MBPartPredMode[0][0] + 1; // 1 or 2
+            }
+            else if(currMB->mbMode == AVC_P8)
+            {
+                mb_type = 26;
+            }
+            else if(currMB->mbMode == AVC_P8ref0)
+            {
+                mb_type = 27;
+            }
+            else
+            {
+                part1 = currMB->mbMode - AVC_P16x8;
+                part2 = currMB->MBPartPredMode[0][0];
+                part3 = currMB->MBPartPredMode[1][0];
+                mb_type = MapParts2Type[part1][part2][part3];
+            }
+        }
+
+        if(slice_type == AVC_SI_SLICE)
+        {
+            mb_type++;
+        }
+    */
+    return (uint)mb_type;
+}
+
+//const static int mbPart2raster[3][4] = {{0,0,0,0},{1,1,0,0},{1,0,1,0}};
+
+/* see subclause 7.3.5.1 */
+AVCEnc_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
+{
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    int mbPartIdx;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    int max_ref_idx;
+    uint code;
+
+    if (currMB->mbMode == AVC_I4 || currMB->mbMode == AVC_I16)
+    {
+        if (currMB->mbMode == AVC_I4)
+        {
+            /* perform prediction to get the actual intra 4x4 pred mode */
+            EncodeIntra4x4Mode(video, currMB, stream);
+            /* output will be in currMB->i4Mode[4][4] */
+        }
+
+        /* assume already set from MBPrediction() */
+        status = ue_v(stream, currMB->intra_chroma_pred_mode);
+    }
+    else if (currMB->MBPartPredMode[0][0] != AVC_Direct)
+    {
+
+        memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
+
+        /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+        max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
+        /*      if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+                    max_ref_idx = 2*sliceHdr->num_ref_idx_l0_active_minus1 + 1;
+        */
+        /* decode ref index for L0 */
+        if (sliceHdr->num_ref_idx_l0_active_minus1 > 0)
+        {
+            for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+            {
+                if (/*(sliceHdr->num_ref_idx_l0_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
+                    currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
+                {
+                    code = currMB->ref_idx_L0[mbPartIdx];
+                    status = te_v(stream, code, max_ref_idx);
+                }
+            }
+        }
+
+        /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+        max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
+        /*      if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+                    max_ref_idx = 2*sliceHdr->num_ref_idx_l1_active_minus1 + 1;
+        */
+        /* decode ref index for L1 */
+        if (sliceHdr->num_ref_idx_l1_active_minus1 > 0)
+        {
+            for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+            {
+                if (/*(sliceHdr->num_ref_idx_l1_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
+                    currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
+                {
+                    status = te_v(stream, currMB->ref_idx_L1[mbPartIdx], max_ref_idx);
+                }
+            }
+        }
+
+        /* encode mvd_l0 */
+        for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+        {
+            if (currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
+            {
+                status = se_v(stream, video->mvd_l0[mbPartIdx][0][0]);
+                status = se_v(stream, video->mvd_l0[mbPartIdx][0][1]);
+            }
+        }
+        /* encode mvd_l1 */
+        for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+        {
+            if (currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
+            {
+                status = se_v(stream, video->mvd_l1[mbPartIdx][0][0]);
+                status = se_v(stream, video->mvd_l1[mbPartIdx][0][1]);
+            }
+        }
+    }
+
+    return status;
+}
+
+/* see subclause 7.3.5.2 */
+AVCEnc_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
+{
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    int mbPartIdx, subMbPartIdx;
+    AVCSliceHeader *sliceHdr = video->sliceHdr;
+    uint max_ref_idx;
+    uint slice_type = video->slice_type;
+    uint sub_mb_type[4];
+
+    /* this should move somewhere else where we don't have to make this check */
+    if (currMB->mbMode == AVC_P8ref0)
+    {
+        memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
+    }
+
+    /* we have to check the values to make sure they are valid  */
+    /* assign values to currMB->sub_mb_type[] */
+    if (slice_type == AVC_P_SLICE)
+    {
+        InterpretSubMBTypeP(currMB, sub_mb_type);
+    }
+    /* no need to check for B-slice
+        else if(slice_type == AVC_B_SLICE)
+        {
+            InterpretSubMBTypeB(currMB,sub_mb_type);
+        }*/
+
+    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+    {
+        status = ue_v(stream, sub_mb_type[mbPartIdx]);
+    }
+
+    /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+    max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
+    /*  if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+            max_ref_idx = 2*sliceHdr->num_ref_idx_l0_active_minus1 + 1; */
+
+    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+    {
+        if ((sliceHdr->num_ref_idx_l0_active_minus1 > 0 /*|| currMB->mb_field_decoding_flag*/) &&
+                currMB->mbMode != AVC_P8ref0 && /*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
+                currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
+        {
+            status = te_v(stream, currMB->ref_idx_L0[mbPartIdx], max_ref_idx);
+        }
+        /* used in deblocking */
+        currMB->RefIdx[mbPartIdx] = video->RefPicList0[currMB->ref_idx_L0[mbPartIdx]]->RefIdx;
+    }
+    /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+    max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
+    /*  if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+            max_ref_idx = 2*sliceHdr->num_ref_idx_l1_active_minus1 + 1;*/
+
+    if (sliceHdr->num_ref_idx_l1_active_minus1 > 0)
+    {
+        for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+        {
+            if (/*(sliceHdr->num_ref_idx_l1_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
+                /*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
+                currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
+            {
+                status = te_v(stream, currMB->ref_idx_L1[mbPartIdx], max_ref_idx);
+            }
+        }
+    }
+
+    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+    {
+        if (/*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
+            currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
+        {
+            for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+            {
+                status = se_v(stream, video->mvd_l0[mbPartIdx][subMbPartIdx][0]);
+                status = se_v(stream, video->mvd_l0[mbPartIdx][subMbPartIdx][1]);
+            }
+        }
+    }
+
+    for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+    {
+        if (/*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
+            currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
+        {
+            for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+            {
+                status = se_v(stream, video->mvd_l1[mbPartIdx][subMbPartIdx][0]);
+                status = se_v(stream, video->mvd_l1[mbPartIdx][subMbPartIdx][1]);
+            }
+        }
+    }
+
+    return status;
+}
+
+/* input is mblock->sub_mb_type[] */
+void InterpretSubMBTypeP(AVCMacroblock *mblock, uint *sub_mb_type)
+{
+    int i;
+    /* see enum AVCMBType declaration */
+    /*const static AVCSubMBMode map2subMbMode[4] = {AVC_8x8,AVC_8x4,AVC_4x8,AVC_4x4};
+    const static int map2subPartWidth[4] = {8,8,4,4};
+    const static int map2subPartHeight[4] = {8,4,8,4};
+    const static int map2numSubPart[4] = {1,2,2,4};*/
+
+    for (i = 0; i < 4 ; i++)
+    {
+        sub_mb_type[i] = mblock->subMbMode[i] - AVC_8x8;
+    }
+
+    return ;
+}
+
+void InterpretSubMBTypeB(AVCMacroblock *mblock, uint *sub_mb_type)
+{
+    int i;
+    /* see enum AVCMBType declaration */
+    /*  const static AVCSubMBMode map2subMbMode[13] = {AVC_BDirect8,AVC_8x8,AVC_8x8,
+            AVC_8x8,AVC_8x4,AVC_4x8,AVC_8x4,AVC_4x8,AVC_8x4,AVC_4x8,AVC_4x4,AVC_4x4,AVC_4x4};
+        const static int map2subPartWidth[13] = {4,8,8,8,8,4,8,4,8,4,4,4,4};
+        const static int map2subPartHeight[13] = {4,8,8,8,4,8,4,8,4,8,4,4,4};
+        const static int map2numSubPart[13] = {4,1,1,1,2,2,2,2,2,2,4,4,4};
+        const static int map2predMode[13] = {3,0,1,2,0,0,1,1,2,2,0,1,2};*/
+
+    for (i = 0; i < 4 ; i++)
+    {
+        if (mblock->subMbMode[i] == AVC_BDirect8)
+        {
+            sub_mb_type[i] = 0;
+        }
+        else if (mblock->subMbMode[i] == AVC_8x8)
+        {
+            sub_mb_type[i] = 1 + mblock->MBPartPredMode[i][0];
+        }
+        else if (mblock->subMbMode[i] == AVC_4x4)
+        {
+            sub_mb_type[i] = 10 + mblock->MBPartPredMode[i][0];
+        }
+        else
+        {
+            sub_mb_type[i] = 4 + (mblock->MBPartPredMode[i][0] << 1) + (mblock->subMbMode[i] - AVC_8x4);
+        }
+    }
+
+    return ;
+}
+
+/* see subclause 8.3.1 */
+AVCEnc_Status EncodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
+{
+    int intra4x4PredModeA = 0;
+    int intra4x4PredModeB, predIntra4x4PredMode;
+    int component, SubBlock_indx, block_x, block_y;
+    int dcOnlyPredictionFlag;
+    uint    flag;
+    int     rem = 0;
+    int     mode;
+    int bindx = 0;
+
+    for (component = 0; component < 4; component++) /* partition index */
+    {
+        block_x = ((component & 1) << 1);
+        block_y = ((component >> 1) << 1);
+
+        for (SubBlock_indx = 0; SubBlock_indx < 4; SubBlock_indx++) /* sub-partition index */
+        {
+            dcOnlyPredictionFlag = 0;
+            if (block_x > 0)
+            {
+                intra4x4PredModeA = currMB->i4Mode[(block_y << 2) + block_x - 1 ];
+            }
+            else
+            {
+                if (video->intraAvailA)
+                {
+                    if (video->mblock[video->mbAddrA].mbMode == AVC_I4)
+                    {
+                        intra4x4PredModeA = video->mblock[video->mbAddrA].i4Mode[(block_y << 2) + 3];
+                    }
+                    else
+                    {
+                        intra4x4PredModeA = AVC_I4_DC;
+                    }
+                }
+                else
+                {
+                    dcOnlyPredictionFlag = 1;
+                }
+            }
+
+            if (block_y > 0)
+            {
+                intra4x4PredModeB = currMB->i4Mode[((block_y-1) << 2) + block_x];
+            }
+            else
+            {
+                if (video->intraAvailB)
+                {
+                    if (video->mblock[video->mbAddrB].mbMode == AVC_I4)
+                    {
+                        intra4x4PredModeB = video->mblock[video->mbAddrB].i4Mode[(3 << 2) + block_x];
+                    }
+                    else
+                    {
+                        intra4x4PredModeB = AVC_I4_DC;
+                    }
+                }
+                else
+                {
+                    dcOnlyPredictionFlag = 1;
+                }
+            }
+
+            if (dcOnlyPredictionFlag)
+            {
+                intra4x4PredModeA = intra4x4PredModeB = AVC_I4_DC;
+            }
+
+            predIntra4x4PredMode = AVC_MIN(intra4x4PredModeA, intra4x4PredModeB);
+
+            flag = 0;
+            mode = currMB->i4Mode[(block_y<<2)+block_x];
+
+            if (mode == (AVCIntra4x4PredMode)predIntra4x4PredMode)
+            {
+                flag = 1;
+            }
+            else if (mode < predIntra4x4PredMode)
+            {
+                rem = mode;
+            }
+            else
+            {
+                rem = mode - 1;
+            }
+
+            BitstreamWrite1Bit(stream, flag);
+
+            if (!flag)
+            {
+                BitstreamWriteBits(stream, 3, rem);
+            }
+
+            bindx++;
+            block_y += (SubBlock_indx & 1) ;
+            block_x += (1 - 2 * (SubBlock_indx & 1)) ;
+        }
+    }
+
+    return AVCENC_SUCCESS;
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/vlc_encode.cpp b/media/libstagefright/codecs/avc/enc/src/vlc_encode.cpp
new file mode 100644
index 0000000..222e709
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/vlc_encode.cpp
@@ -0,0 +1,336 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+/**
+See algorithm in subclause 9.1, Table 9-1, Table 9-2. */
+AVCEnc_Status ue_v(AVCEncBitstream *bitstream, uint codeNum)
+{
+    if (AVCENC_SUCCESS != SetEGBitstring(bitstream, codeNum))
+        return AVCENC_FAIL;
+
+    return AVCENC_SUCCESS;
+}
+
+/**
+See subclause 9.1.1, Table 9-3 */
+AVCEnc_Status  se_v(AVCEncBitstream *bitstream, int value)
+{
+    uint codeNum;
+    AVCEnc_Status status;
+
+    if (value <= 0)
+    {
+        codeNum = -value * 2;
+    }
+    else
+    {
+        codeNum = value * 2 - 1;
+    }
+
+    status = ue_v(bitstream, codeNum);
+
+    return status;
+}
+
+AVCEnc_Status te_v(AVCEncBitstream *bitstream, uint value, uint range)
+{
+    AVCEnc_Status status;
+
+    if (range > 1)
+    {
+        return ue_v(bitstream, value);
+    }
+    else
+    {
+        status = BitstreamWrite1Bit(bitstream, 1 - value);
+        return status;
+    }
+}
+
+/**
+See subclause 9.1, Table 9-1, 9-2. */
+// compute leadingZeros and inforbits
+//codeNum = (1<<leadingZeros)-1+infobits;
+AVCEnc_Status SetEGBitstring(AVCEncBitstream *bitstream, uint codeNum)
+{
+    AVCEnc_Status status;
+    int leadingZeros;
+    int infobits;
+
+    if (!codeNum)
+    {
+        status = BitstreamWrite1Bit(bitstream, 1);
+        return status;
+    }
+
+    /* calculate leadingZeros and infobits */
+    leadingZeros = 1;
+    while ((uint)(1 << leadingZeros) < codeNum + 2)
+    {
+        leadingZeros++;
+    }
+    leadingZeros--;
+    infobits = codeNum - (1 << leadingZeros) + 1;
+
+    status = BitstreamWriteBits(bitstream, leadingZeros, 0);
+    infobits |= (1 << leadingZeros);
+    status = BitstreamWriteBits(bitstream, leadingZeros + 1, infobits);
+    return status;
+}
+
+/* see Table 9-4 assignment of codeNum to values of coded_block_pattern. */
+const static uint8 MapCBP2code[48][2] =
+{
+    {3, 0}, {29, 2}, {30, 3}, {17, 7}, {31, 4}, {18, 8}, {37, 17}, {8, 13}, {32, 5}, {38, 18}, {19, 9}, {9, 14},
+    {20, 10}, {10, 15}, {11, 16}, {2, 11}, {16, 1}, {33, 32}, {34, 33}, {21, 36}, {35, 34}, {22, 37}, {39, 44}, {4, 40},
+    {36, 35}, {40, 45}, {23, 38}, {5, 41}, {24, 39}, {6, 42}, {7, 43}, {1, 19}, {41, 6}, {42, 24}, {43, 25}, {25, 20},
+    {44, 26}, {26, 21}, {46, 46}, {12, 28}, {45, 27}, {47, 47}, {27, 22}, {13, 29}, {28, 23}, {14, 30}, {15, 31}, {0, 12}
+};
+
+AVCEnc_Status EncodeCBP(AVCMacroblock *currMB, AVCEncBitstream *stream)
+{
+    AVCEnc_Status status;
+    uint codeNum;
+
+    if (currMB->mbMode == AVC_I4)
+    {
+        codeNum = MapCBP2code[currMB->CBP][0];
+    }
+    else
+    {
+        codeNum = MapCBP2code[currMB->CBP][1];
+    }
+
+    status = ue_v(stream, codeNum);
+
+    return status;
+}
+
+AVCEnc_Status ce_TotalCoeffTrailingOnes(AVCEncBitstream *stream, int TrailingOnes, int TotalCoeff, int nC)
+{
+    const static uint8 totCoeffTrailOne[3][4][17][2] =
+    {
+        {   // 0702
+            {{1, 1}, {6, 5}, {8, 7}, {9, 7}, {10, 7}, {11, 7}, {13, 15}, {13, 11}, {13, 8}, {14, 15}, {14, 11}, {15, 15}, {15, 11}, {16, 15}, {16, 11}, {16, 7}, {16, 4}},
+            {{0, 0}, {2, 1}, {6, 4}, {8, 6}, {9, 6}, {10, 6}, {11, 6}, {13, 14}, {13, 10}, {14, 14}, {14, 10}, {15, 14}, {15, 10}, {15, 1}, {16, 14}, {16, 10}, {16, 6}},
+            {{0, 0}, {0, 0}, {3, 1}, {7, 5}, {8, 5}, {9, 5}, {10, 5}, {11, 5}, {13, 13}, {13, 9}, {14, 13}, {14, 9}, {15, 13}, {15, 9}, {16, 13}, {16, 9}, {16, 5}},
+            {{0, 0}, {0, 0}, {0, 0}, {5, 3}, {6, 3}, {7, 4}, {8, 4}, {9, 4}, {10, 4}, {11, 4}, {13, 12}, {14, 12}, {14, 8}, {15, 12}, {15, 8}, {16, 12}, {16, 8}},
+        },
+        {
+            {{2, 3}, {6, 11}, {6, 7}, {7, 7}, {8, 7}, {8, 4}, {9, 7}, {11, 15}, {11, 11}, {12, 15}, {12, 11}, {12, 8}, {13, 15}, {13, 11}, {13, 7}, {14, 9}, {14, 7}},
+            {{0, 0}, {2, 2}, {5, 7}, {6, 10}, {6, 6}, {7, 6}, {8, 6}, {9, 6}, {11, 14}, {11, 10}, {12, 14}, {12, 10}, {13, 14}, {13, 10}, {14, 11}, {14, 8}, {14, 6}},
+            {{0, 0}, {0, 0}, {3, 3}, {6, 9}, {6, 5}, {7, 5}, {8, 5}, {9, 5}, {11, 13}, {11, 9}, {12, 13}, {12, 9}, {13, 13}, {13, 9}, {13, 6}, {14, 10}, {14, 5}},
+            {{0, 0}, {0, 0}, {0, 0}, {4, 5}, {4, 4}, {5, 6}, {6, 8}, {6, 4}, {7, 4}, {9, 4}, {11, 12}, {11, 8}, {12, 12}, {13, 12}, {13, 8}, {13, 1}, {14, 4}},
+        },
+        {
+            {{4, 15}, {6, 15}, {6, 11}, {6, 8}, {7, 15}, {7, 11}, {7, 9}, {7, 8}, {8, 15}, {8, 11}, {9, 15}, {9, 11}, {9, 8}, {10, 13}, {10, 9}, {10, 5}, {10, 1}},
+            {{0, 0}, {4, 14}, {5, 15}, {5, 12}, {5, 10}, {5, 8}, {6, 14}, {6, 10}, {7, 14}, {8, 14}, {8, 10}, {9, 14}, {9, 10}, {9, 7}, {10, 12}, {10, 8}, {10, 4}},
+            {{0, 0}, {0, 0}, {4, 13}, {5, 14}, {5, 11}, {5, 9}, {6, 13}, {6, 9}, {7, 13}, {7, 10}, {8, 13}, {8, 9}, {9, 13}, {9, 9}, {10, 11}, {10, 7}, {10, 3}},
+            {{0, 0}, {0, 0}, {0, 0}, {4, 12}, {4, 11}, {4, 10}, {4, 9}, {4, 8}, {5, 13}, {6, 12}, {7, 12}, {8, 12}, {8, 8}, {9, 12}, {10, 10}, {10, 6}, {10, 2}}
+        }
+    };
+
+
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    uint code, len;
+    int vlcnum;
+
+    if (TrailingOnes > 3)
+    {
+        return AVCENC_TRAILINGONES_FAIL;
+    }
+
+    if (nC >= 8)
+    {
+        if (TotalCoeff)
+        {
+            code = ((TotalCoeff - 1) << 2) | (TrailingOnes);
+        }
+        else
+        {
+            code = 3;
+        }
+        status = BitstreamWriteBits(stream, 6, code);
+    }
+    else
+    {
+        if (nC < 2)
+        {
+            vlcnum = 0;
+        }
+        else if (nC < 4)
+        {
+            vlcnum = 1;
+        }
+        else
+        {
+            vlcnum = 2;
+        }
+
+        len = totCoeffTrailOne[vlcnum][TrailingOnes][TotalCoeff][0];
+        code = totCoeffTrailOne[vlcnum][TrailingOnes][TotalCoeff][1];
+        status = BitstreamWriteBits(stream, len, code);
+    }
+
+    return status;
+}
+
+AVCEnc_Status ce_TotalCoeffTrailingOnesChromaDC(AVCEncBitstream *stream, int TrailingOnes, int TotalCoeff)
+{
+    const static uint8 totCoeffTrailOneChrom[4][5][2] =
+    {
+        { {2, 1}, {6, 7}, {6, 4}, {6, 3}, {6, 2}},
+        { {0, 0}, {1, 1}, {6, 6}, {7, 3}, {8, 3}},
+        { {0, 0}, {0, 0}, {3, 1}, {7, 2}, {8, 2}},
+        { {0, 0}, {0, 0}, {0, 0}, {6, 5}, {7, 0}},
+    };
+
+    AVCEnc_Status status = AVCENC_SUCCESS;
+    uint code, len;
+
+    len = totCoeffTrailOneChrom[TrailingOnes][TotalCoeff][0];
+    code = totCoeffTrailOneChrom[TrailingOnes][TotalCoeff][1];
+    status = BitstreamWriteBits(stream, len, code);
+
+    return status;
+}
+
+/* see Table 9-7 and 9-8 */
+AVCEnc_Status ce_TotalZeros(AVCEncBitstream *stream, int total_zeros, int TotalCoeff)
+{
+    const static uint8 lenTotalZeros[15][16] =
+    {
+        { 1, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9},
+        { 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6},
+        { 4, 3, 3, 3, 4, 4, 3, 3, 4, 5, 5, 6, 5, 6},
+        { 5, 3, 4, 4, 3, 3, 3, 4, 3, 4, 5, 5, 5},
+        { 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 4, 5},
+        { 6, 5, 3, 3, 3, 3, 3, 3, 4, 3, 6},
+        { 6, 5, 3, 3, 3, 2, 3, 4, 3, 6},
+        { 6, 4, 5, 3, 2, 2, 3, 3, 6},
+        { 6, 6, 4, 2, 2, 3, 2, 5},
+        { 5, 5, 3, 2, 2, 2, 4},
+        { 4, 4, 3, 3, 1, 3},
+        { 4, 4, 2, 1, 3},
+        { 3, 3, 1, 2},
+        { 2, 2, 1},
+        { 1, 1},
+    };
+
+    const static uint8 codTotalZeros[15][16] =
+    {
+        {1, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 1},
+        {7, 6, 5, 4, 3, 5, 4, 3, 2, 3, 2, 3, 2, 1, 0},
+        {5, 7, 6, 5, 4, 3, 4, 3, 2, 3, 2, 1, 1, 0},
+        {3, 7, 5, 4, 6, 5, 4, 3, 3, 2, 2, 1, 0},
+        {5, 4, 3, 7, 6, 5, 4, 3, 2, 1, 1, 0},
+        {1, 1, 7, 6, 5, 4, 3, 2, 1, 1, 0},
+        {1, 1, 5, 4, 3, 3, 2, 1, 1, 0},
+        {1, 1, 1, 3, 3, 2, 2, 1, 0},
+        {1, 0, 1, 3, 2, 1, 1, 1, },
+        {1, 0, 1, 3, 2, 1, 1, },
+        {0, 1, 1, 2, 1, 3},
+        {0, 1, 1, 1, 1},
+        {0, 1, 1, 1},
+        {0, 1, 1},
+        {0, 1},
+    };
+    int len, code;
+    AVCEnc_Status status;
+
+    len = lenTotalZeros[TotalCoeff-1][total_zeros];
+    code = codTotalZeros[TotalCoeff-1][total_zeros];
+
+    status = BitstreamWriteBits(stream, len, code);
+
+    return status;
+}
+
+/* see Table 9-9 */
+AVCEnc_Status ce_TotalZerosChromaDC(AVCEncBitstream *stream, int total_zeros, int TotalCoeff)
+{
+    const static uint8 lenTotalZerosChromaDC[3][4] =
+    {
+        { 1, 2, 3, 3, },
+        { 1, 2, 2, 0, },
+        { 1, 1, 0, 0, },
+    };
+
+    const static uint8 codTotalZerosChromaDC[3][4] =
+    {
+        { 1, 1, 1, 0, },
+        { 1, 1, 0, 0, },
+        { 1, 0, 0, 0, },
+    };
+
+    int len, code;
+    AVCEnc_Status status;
+
+    len = lenTotalZerosChromaDC[TotalCoeff-1][total_zeros];
+    code = codTotalZerosChromaDC[TotalCoeff-1][total_zeros];
+
+    status = BitstreamWriteBits(stream, len, code);
+
+    return status;
+}
+
+/* see Table 9-10 */
+AVCEnc_Status ce_RunBefore(AVCEncBitstream *stream, int run_before, int zerosLeft)
+{
+    const static uint8 lenRunBefore[7][16] =
+    {
+        {1, 1},
+        {1, 2, 2},
+        {2, 2, 2, 2},
+        {2, 2, 2, 3, 3},
+        {2, 2, 3, 3, 3, 3},
+        {2, 3, 3, 3, 3, 3, 3},
+        {3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11},
+    };
+
+    const static uint8 codRunBefore[7][16] =
+    {
+        {1, 0},
+        {1, 1, 0},
+        {3, 2, 1, 0},
+        {3, 2, 1, 1, 0},
+        {3, 2, 3, 2, 1, 0},
+        {3, 0, 1, 3, 2, 5, 4},
+        {7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+    };
+
+    int len, code;
+    AVCEnc_Status status;
+
+    if (zerosLeft <= 6)
+    {
+        len = lenRunBefore[zerosLeft-1][run_before];
+        code = codRunBefore[zerosLeft-1][run_before];
+    }
+    else
+    {
+        len = lenRunBefore[6][run_before];
+        code = codRunBefore[6][run_before];
+    }
+
+    status = BitstreamWriteBits(stream, len, code);
+
+
+    return status;
+}
diff --git a/media/libstagefright/codecs/common/Android.mk b/media/libstagefright/codecs/common/Android.mk
new file mode 100644
index 0000000..fffb2ad
--- /dev/null
+++ b/media/libstagefright/codecs/common/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES := cmnMemory.c
+
+LOCAL_MODULE := libstagefright_enc_common
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_C_INCLUDES := \
+	$(LOCAL_PATH)/include
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+ifeq ($(VOTT), v5)
+LOCAL_CFLAGS += -DARM -DASM_OPT
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_CFLAGS += -DARM -DARMV7 -DASM_OPT
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+
diff --git a/media/libstagefright/codecs/common/Config.mk b/media/libstagefright/codecs/common/Config.mk
new file mode 100644
index 0000000..27a17c1
--- /dev/null
+++ b/media/libstagefright/codecs/common/Config.mk
@@ -0,0 +1,24 @@
+# 

+# This configure file is just for Linux projects against Android

+#

+

+VOPRJ := 

+VONJ :=

+

+# WARNING:

+# Using v7 breaks generic build

+ifeq ($(TARGET_ARCH),arm)

+VOTT := v5

+else

+VOTT := pc

+endif

+

+# Do we also need to check on ARCH_ARM_HAVE_ARMV7A? - probably not

+ifeq ($(ARCH_ARM_HAVE_NEON),true)

+VOTT := v7

+endif

+

+VOTEST := 0

+

+VO_CFLAGS:=-DLINUX 

+

diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/libstagefright/codecs/common/cmnMemory.c
new file mode 100644
index 0000000..c17264c
--- /dev/null
+++ b/media/libstagefright/codecs/common/cmnMemory.c
@@ -0,0 +1,73 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		cmnMemory.c

+

+	Content:	sample code for memory operator implementation

+

+*******************************************************************************/

+#include "cmnMemory.h"

+

+#include <malloc.h>

+#if defined LINUX

+#include <string.h>

+#endif

+

+//VO_MEM_OPERATOR		g_memOP;

+

+VO_U32 cmnMemAlloc (VO_S32 uID,  VO_MEM_INFO * pMemInfo)

+{

+	if (!pMemInfo)

+		return VO_ERR_INVALID_ARG;

+

+	pMemInfo->VBuffer = malloc (pMemInfo->Size);

+	return 0;

+}

+

+VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem)

+{

+	free (pMem);

+	return 0;

+}

+

+VO_U32	cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize)

+{

+	memset (pBuff, uValue, uSize);

+	return 0;

+}

+

+VO_U32	cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)

+{

+	memcpy (pDest, pSource, uSize);

+	return 0;

+}

+

+VO_U32	cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize)

+{

+	return 0;

+}

+

+VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize)

+{

+	return memcmp(pBuffer1, pBuffer2, uSize);

+}

+

+VO_U32	cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)

+{

+	memmove (pDest, pSource, uSize);

+	return 0;

+}

+

diff --git a/media/libstagefright/codecs/common/include/cmnMemory.h b/media/libstagefright/codecs/common/include/cmnMemory.h
new file mode 100644
index 0000000..9315600
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/cmnMemory.h
@@ -0,0 +1,106 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		cmnMemory.h

+

+	Content:	memory operator implementation header file

+

+*******************************************************************************/

+

+#ifndef __cmnMemory_H__

+#define __cmnMemory_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif /* __cplusplus */

+

+#include <voMem.h>

+

+//extern VO_MEM_OPERATOR	g_memOP;

+

+/**

+ * Allocate memory

+ * \param uID [in] module ID

+ * \param uSize [in] size of memory

+ * \return value is the allocated memory address. NULL is failed.

+ */

+VO_U32	cmnMemAlloc (VO_S32 uID,  VO_MEM_INFO * pMemInfo);

+

+/**

+ * Free up memory

+ * \param uID [in] module ID

+ * \param pMem [in] address of memory

+ * \return value 0, if succeeded.

+ */

+VO_U32	cmnMemFree (VO_S32 uID, VO_PTR pBuffer);

+

+/**

+ * memory set function

+ * \param uID [in] module ID

+ * \param pBuff [in/out] address of memory

+ * \param uValue [in] the value to be set

+ * \param uSize [in] the size to be set

+ * \return value 0, if succeeded.

+ */

+VO_U32	cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize);

+

+/**

+ * memory copy function

+ * \param uID [in] module ID

+ * \param pDest [in/out] address of destination memory

+ * \param pSource [in] address of source memory

+ * \param uSize [in] the size to be copied

+ * \return value 0, if succeeded.

+ */

+VO_U32	cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize);

+

+/**

+ * memory check function

+ * \param uID [in] module ID

+ * \param pBuff [in] address of buffer to be checked

+ * \param uSize [in] the size to be checked

+ * \return value 0, if succeeded.

+ */

+VO_U32	cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize);

+

+/**

+ * memory compare function

+ * \param uID [in] module ID

+ * \param pBuffer1 [in] address of buffer 1 to be compared

+ * \param pBuffer2 [in] address of buffer 2 to be compared

+ * \param uSize [in] the size to be compared

+ * \return value: same as standard C run-time memcmp() function.

+ */

+VO_S32	cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize);

+

+/**

+ * memory move function

+ * \param uID [in] module ID

+ * \param pDest [in/out] address of destination memory

+ * \param pSource [in] address of source memory

+ * \param uSize [in] the size to be moved

+ * \return value 0, if succeeded.

+ */

+VO_U32	cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize);

+

+

+#ifdef __cplusplus

+}

+#endif /* __cplusplus */

+

+#endif // __cmnMemory_H__

+

+

diff --git a/media/libstagefright/codecs/common/include/voAAC.h b/media/libstagefright/codecs/common/include/voAAC.h
new file mode 100644
index 0000000..d11ed83
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voAAC.h
@@ -0,0 +1,74 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		voAAC.h

+

+	Content:	AAC codec APIs & data types

+

+*******************************************************************************/

+

+#ifndef __voAAC_H__

+#define __voAAC_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif /* __cplusplus */

+

+#include "voAudio.h"

+

+/*!

+ * the frame type that the decoder supports

+ */

+typedef enum {

+	VOAAC_RAWDATA			= 0,	/*!<contains only raw aac data in a frame*/

+	VOAAC_ADTS				= 1,	/*!<contains ADTS header + raw AAC data in a frame*/

+	VOAAC_FT_MAX			= VO_MAX_ENUM_VALUE

+} VOAACFRAMETYPE;

+

+/*!

+ * the structure for AAC encoder input parameter

+ */

+typedef  struct {

+  int	  sampleRate;          /*! audio file sample rate */

+  int	  bitRate;             /*! encoder bit rate in bits/sec */

+  short   nChannels;		   /*! number of channels on input (1,2) */

+  short   adtsUsed;			   /*! whether write adts header */

+} AACENC_PARAM;

+

+/* AAC Param ID */

+#define VO_PID_AAC_Mdoule				0x42211000

+#define VO_PID_AAC_ENCPARAM				VO_PID_AAC_Mdoule | 0x0040  /*!< get/set AAC encoder parameter, the parameter is a pointer to AACENC_PARAM */

+

+/* AAC decoder error ID */

+#define VO_ERR_AAC_Mdoule				0x82210000

+#define VO_ERR_AAC_UNSFILEFORMAT		(VO_ERR_AAC_Mdoule | 0xF001)

+#define VO_ERR_AAC_UNSPROFILE			(VO_ERR_AAC_Mdoule | 0xF002)

+

+/**

+ * Get audio encoder API interface

+ * \param pEncHandle [out] Return the AAC Encoder handle.

+ * \retval VO_ERR_OK Succeeded.

+ */

+VO_S32 VO_API voGetAACEncAPI (VO_AUDIO_CODECAPI * pEncHandle);

+

+#ifdef __cplusplus

+}

+#endif /* __cplusplus */

+

+#endif // __voAAC_H__

+

+

+

diff --git a/media/libstagefright/codecs/common/include/voAMRWB.h b/media/libstagefright/codecs/common/include/voAMRWB.h
new file mode 100644
index 0000000..8a93eb8
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voAMRWB.h
@@ -0,0 +1,87 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		voAMRWB.h

+

+	Content:	AMR-WB codec APIs & data types

+

+*******************************************************************************/

+#ifndef  __VOAMRWB_H__

+#define  __VOAMRWB_H__

+

+#include  "voAudio.h"

+#ifdef __cplusplus

+extern "C" {

+#endif /* __cplusplus */

+#pragma pack(push, 4)

+

+/*!* the bit rate the codec supports*/

+typedef enum { 

+	VOAMRWB_MDNONE		= -1,	/*!< Invalid mode */

+	VOAMRWB_MD66		= 0,	/*!< 6.60kbps   */

+	VOAMRWB_MD885		= 1,    /*!< 8.85kbps   */       

+	VOAMRWB_MD1265		= 2,	/*!< 12.65kbps  */

+	VOAMRWB_MD1425		= 3,	/*!< 14.25kbps  */

+	VOAMRWB_MD1585		= 4,	/*!< 15.85bps   */

+	VOAMRWB_MD1825		= 5,	/*!< 18.25bps   */

+	VOAMRWB_MD1985		= 6,	/*!< 19.85kbps  */

+	VOAMRWB_MD2305		= 7,    /*!< 23.05kbps  */

+	VOAMRWB_MD2385          = 8,    /*!< 23.85kbps> */	

+	VOAMRWB_N_MODES 	= 9,	/*!< Invalid mode */

+	VOAMRWB_MODE_MAX    = VO_MAX_ENUM_VALUE

+	

+}VOAMRWBMODE;

+

+/*!* the frame format the codec supports*/

+typedef enum {

+	VOAMRWB_DEFAULT  	= 0,	/*!< the frame type is the header (defined in RFC3267) + rawdata*/

+	/*One word (2-byte) for sync word (0x6b21)*/

+	/*One word (2-byte) for frame length N.*/

+	/*N words (2-byte) containing N bits (bit 0 = 0x007f, bit 1 = 0x0081).*/

+	VOAMRWB_ITU         = 1, 

+	/*One word (2-byte) for sync word (0x6b21).*/

+	/*One word (2-byte) to indicate the frame type.*/	

+	/*One word (2-byte) to indicate the mode.*/

+	/*N words  (2-byte) containing N bits (bit 0 = 0xff81, bit 1 = 0x007f).*/

+	VOAMRWB_RFC3267		= 2,	/* see RFC 3267 */  

+    VOAMRWB_TMAX        = VO_MAX_ENUM_VALUE	

+}VOAMRWBFRAMETYPE;

+

+

+#define    VO_PID_AMRWB_Module							0x42261000 

+#define    VO_PID_AMRWB_FORMAT                          (VO_PID_AMRWB_Module | 0x0002)

+#define    VO_PID_AMRWB_CHANNELS                        (VO_PID_AMRWB_Module | 0x0003)

+#define    VO_PID_AMRWB_SAMPLERATE                      (VO_PID_AMRWB_Module | 0x0004)

+#define    VO_PID_AMRWB_FRAMETYPE                       (VO_PID_AMRWB_Module | 0x0005)

+#define    VO_PID_AMRWB_MODE                            (VO_PID_AMRWB_Module | 0x0006)

+#define    VO_PID_AMRWB_DTX                             (VO_PID_AMRWB_Module | 0x0007)

+

+/**

+ * Get audio codec API interface

+ * \param pEncHandle [out] Return the AMRWB Encoder handle.

+ * \retval VO_ERR_OK Succeeded.

+ */

+VO_S32 VO_API voGetAMRWBEncAPI(VO_AUDIO_CODECAPI *pEncHandle);

+

+

+#pragma pack(pop)

+#ifdef __cplusplus

+} /* extern "C" */

+#endif /* __cplusplus */

+

+

+#endif   //__VOAMRWB_H__

+

diff --git a/media/libstagefright/codecs/common/include/voAudio.h b/media/libstagefright/codecs/common/include/voAudio.h
new file mode 100644
index 0000000..64c9dfb
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voAudio.h
@@ -0,0 +1,173 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		voAudio.h

+

+	Content:	Audio types and functions

+

+*******************************************************************************/

+

+#ifndef __voAudio_H__

+#define __voAudio_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif /* __cplusplus */

+

+#include "voIndex.h"

+#include "voMem.h"

+

+#define	VO_PID_AUDIO_BASE			 0x42000000							/*!< The base param ID for AUDIO codec */

+#define	VO_PID_AUDIO_FORMAT			(VO_PID_AUDIO_BASE | 0X0001)		/*!< The format data of audio in track */

+#define	VO_PID_AUDIO_SAMPLEREATE	(VO_PID_AUDIO_BASE | 0X0002)		/*!< The sample rate of audio  */

+#define	VO_PID_AUDIO_CHANNELS		(VO_PID_AUDIO_BASE | 0X0003)		/*!< The channel of audio */

+#define	VO_PID_AUDIO_BITRATE		(VO_PID_AUDIO_BASE | 0X0004)		/*!< The bit rate of audio */

+#define VO_PID_AUDIO_CHANNELMODE	(VO_PID_AUDIO_BASE | 0X0005)		/*!< The channel mode of audio */

+

+#define	VO_ERR_AUDIO_BASE			0x82000000

+#define VO_ERR_AUDIO_UNSCHANNEL		VO_ERR_AUDIO_BASE | 0x0001

+#define VO_ERR_AUDIO_UNSSAMPLERATE	VO_ERR_AUDIO_BASE | 0x0002

+#define VO_ERR_AUDIO_UNSFEATURE		VO_ERR_AUDIO_BASE | 0x0003

+

+

+/**

+ *Enumeration used to define the possible audio coding formats.

+ */

+typedef enum VO_AUDIO_CODINGTYPE {

+	VO_AUDIO_CodingUnused = 0,  /**< Placeholder value when coding is N/A  */

+	VO_AUDIO_CodingPCM,         /**< Any variant of PCM coding */

+	VO_AUDIO_CodingADPCM,       /**< Any variant of ADPCM encoded data */

+	VO_AUDIO_CodingAMRNB,       /**< Any variant of AMR encoded data */

+	VO_AUDIO_CodingAMRWB,       /**< Any variant of AMR encoded data */

+	VO_AUDIO_CodingAMRWBP,      /**< Any variant of AMR encoded data */

+	VO_AUDIO_CodingQCELP13,     /**< Any variant of QCELP 13kbps encoded data */

+	VO_AUDIO_CodingEVRC,        /**< Any variant of EVRC encoded data */

+	VO_AUDIO_CodingAAC,         /**< Any variant of AAC encoded data, 0xA106 - ISO/MPEG-4 AAC, 0xFF - AAC */

+	VO_AUDIO_CodingAC3,         /**< Any variant of AC3 encoded data */

+	VO_AUDIO_CodingFLAC,        /**< Any variant of FLAC encoded data */

+	VO_AUDIO_CodingMP1,			/**< Any variant of MP1 encoded data */

+	VO_AUDIO_CodingMP3,         /**< Any variant of MP3 encoded data */

+	VO_AUDIO_CodingOGG,         /**< Any variant of OGG encoded data */

+	VO_AUDIO_CodingWMA,         /**< Any variant of WMA encoded data */

+	VO_AUDIO_CodingRA,          /**< Any variant of RA encoded data */

+	VO_AUDIO_CodingMIDI,        /**< Any variant of MIDI encoded data */

+	VO_AUDIO_CodingDRA,         /**< Any variant of dra encoded data */

+	VO_AUDIO_CodingG729,        /**< Any variant of dra encoded data */

+	VO_AUDIO_Coding_MAX		= VO_MAX_ENUM_VALUE

+} VO_AUDIO_CODINGTYPE;

+

+/*!

+* the channel type value

+*/

+typedef enum {

+	VO_CHANNEL_CENTER				= 1,	/*!<center channel*/

+	VO_CHANNEL_FRONT_LEFT			= 1<<1,	/*!<front left channel*/

+	VO_CHANNEL_FRONT_RIGHT			= 1<<2,	/*!<front right channel*/

+	VO_CHANNEL_SIDE_LEFT  			= 1<<3, /*!<side left channel*/

+	VO_CHANNEL_SIDE_RIGHT			= 1<<4, /*!<side right channel*/

+	VO_CHANNEL_BACK_LEFT			= 1<<5,	/*!<back left channel*/

+	VO_CHANNEL_BACK_RIGHT			= 1<<6,	/*!<back right channel*/

+	VO_CHANNEL_BACK_CENTER			= 1<<7,	/*!<back center channel*/

+	VO_CHANNEL_LFE_BASS				= 1<<8,	/*!<low-frequency effects bass channel*/

+	VO_CHANNEL_ALL					= 0xffff,/*!<[default] include all channels */

+	VO_CHANNEL_MAX					= VO_MAX_ENUM_VALUE

+} VO_AUDIO_CHANNELTYPE;

+

+/**

+ * General audio format info

+ */

+typedef struct

+{

+	VO_S32	SampleRate;  /*!< Sample rate */

+	VO_S32	Channels;    /*!< Channel count */

+	VO_S32	SampleBits;  /*!< Bits per sample */

+} VO_AUDIO_FORMAT;

+

+/**

+ * General audio output info

+ */

+typedef struct

+{

+	VO_AUDIO_FORMAT	Format;			/*!< Sample rate */

+	VO_U32			InputUsed;		/*!< Channel count */

+	VO_U32			Resever;		/*!< Resevered */

+} VO_AUDIO_OUTPUTINFO;

+

+/**

+ * General audio codec function set

+ */

+typedef struct VO_AUDIO_CODECAPI

+{

+	/**

+	 * Init the audio codec module and return codec handle

+	 * \param phCodec [OUT] Return the video codec handle

+	 * \param vType	[IN] The codec type if the module support multi codec.

+	 * \param pUserData	[IN] The init param. It is either a memory operator or an allocated memory

+	 * \retval VO_ERR_NONE Succeeded.

+	 */

+	VO_U32 (VO_API * Init) (VO_HANDLE * phCodec, VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA * pUserData );

+

+	/**

+	 * Set input audio data.

+	 * \param hCodec [IN]] The codec handle which was created by Init function.

+	 * \param pInput [IN] The input buffer param.

+	 * \retval VO_ERR_NONE Succeeded.

+	 */

+	VO_U32 (VO_API * SetInputData) (VO_HANDLE hCodec, VO_CODECBUFFER * pInput);

+

+	/**

+	 * Get the outut audio data

+	 * \param hCodec [IN]] The codec handle which was created by Init function.

+	 * \param pOutBuffer [OUT] The output audio data

+	 * \param pOutInfo [OUT] The codec fills audio format and the input data size used in current call.

+	 *						 pOutInfo->InputUsed is total used input data size in byte.

+	 * \retval  VO_ERR_NONE Succeeded.

+	 *			VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought. Continue to input 

+	 *										data before next call.

+	 */

+	VO_U32 (VO_API * GetOutputData) (VO_HANDLE hCodec, VO_CODECBUFFER * pOutBuffer, VO_AUDIO_OUTPUTINFO * pOutInfo);

+

+	/**

+	 * Set the parameter for the specified param ID.

+	 * \param hCodec [IN]] The codec handle which was created by Init function.

+	 * \param uParamID [IN] The param ID.

+	 * \param pData [IN] The param value.

+	 * \retval VO_ERR_NONE Succeeded.

+	 */

+	VO_U32 (VO_API * SetParam) (VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData);

+

+	/**

+	 * Get the parameter for the specified param ID.

+	 * \param hCodec [IN]] The codec handle which was created by Init function.

+	 * \param uParamID [IN] The param ID.

+	 * \param pData [IN] The param value.

+	 * \retval VO_ERR_NONE Succeeded.

+	 */

+	VO_U32 (VO_API * GetParam) (VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData);

+

+	/**

+	 * Uninit the Codec.

+	 * \param hCodec [IN]] The codec handle which was created by Init function.

+	 * \retval VO_ERR_NONE Succeeded.

+	 */

+	VO_U32 (VO_API * Uninit) (VO_HANDLE hCodec);

+} VO_AUDIO_CODECAPI;

+

+#ifdef __cplusplus

+}

+#endif /* __cplusplus */

+

+#endif // __voAudio_H__

diff --git a/media/libstagefright/codecs/common/include/voIndex.h b/media/libstagefright/codecs/common/include/voIndex.h
new file mode 100644
index 0000000..541a0db
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voIndex.h
@@ -0,0 +1,193 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		voIndex.h

+

+	Content:	module and ID definition

+

+*******************************************************************************/

+

+#ifndef __voIndex_H__

+#define __voIndex_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif /* __cplusplus */

+

+#include "voType.h"

+

+/* Define the module ID */

+#define _MAKE_SOURCE_ID(id, name) \

+VO_INDEX_SRC_##name = _VO_INDEX_SOURCE | id,

+

+#define _MAKE_CODEC_ID(id, name) \

+VO_INDEX_DEC_##name = _VO_INDEX_DEC | id, \

+VO_INDEX_ENC_##name = _VO_INDEX_ENC | id,

+

+#define _MAKE_EFFECT_ID(id, name) \

+VO_INDEX_EFT_##name = _VO_INDEX_EFFECT | id,

+

+#define _MAKE_SINK_ID(id, name) \

+VO_INDEX_SNK_##name = _VO_INDEX_SINK | id,

+

+#define _MAKE_FILTER_ID(id, name) \

+VO_INDEX_FLT_##name = _VO_INDEX_FILTER | id,

+

+#define _MAKE_OMX_ID(id, name) \

+VO_INDEX_OMX_##name = _VO_INDEX_OMX | id,

+

+#define _MAKE_MFW_ID(id, name) \

+VO_INDEX_MFW_##name = _VO_INDEX_MFW | id,

+

+enum

+{

+	_VO_INDEX_SOURCE		= 0x01000000,

+	_VO_INDEX_DEC			= 0x02000000,

+	_VO_INDEX_ENC			= 0x03000000,

+	_VO_INDEX_EFFECT		= 0x04000000,

+	_VO_INDEX_SINK			= 0x05000000,

+	_VO_INDEX_FILTER		= 0x06000000,

+	_VO_INDEX_OMX			= 0x07000000,

+	_VO_INDEX_MFW			= 0x08000000,

+

+	// define file parser modules

+	_MAKE_SOURCE_ID (0x010000, MP4)

+	_MAKE_SOURCE_ID (0x020000, AVI)

+	_MAKE_SOURCE_ID (0x030000, ASF)

+	_MAKE_SOURCE_ID (0x040000, REAL)

+	_MAKE_SOURCE_ID (0x050000, AUDIO)

+	_MAKE_SOURCE_ID (0x060000, FLASH)

+	_MAKE_SOURCE_ID (0x070000, OGG)

+	_MAKE_SOURCE_ID (0x080000, MKV)

+

+	// define network source modules

+	_MAKE_SOURCE_ID (0x110000, RTSP)

+	_MAKE_SOURCE_ID (0x120000, HTTP)

+

+	// define CMMB source modules

+	_MAKE_SOURCE_ID (0x200000, CMMB)

+	_MAKE_SOURCE_ID (0x210000, CMMB_INNO)

+	_MAKE_SOURCE_ID (0x220000, CMMB_TELE)

+	_MAKE_SOURCE_ID (0x230000, CMMB_SIANO)

+

+	// define DVBT source modules

+	_MAKE_SOURCE_ID (0x300000, DVBT)

+	_MAKE_SOURCE_ID (0x310000, DVBT_DIBCOM)

+

+	// define other source modules

+	_MAKE_SOURCE_ID (0x400000, ID3)

+

+	// define video codec modules

+	_MAKE_CODEC_ID (0x010000, H264)

+	_MAKE_CODEC_ID (0x020000, MPEG4)

+	_MAKE_CODEC_ID (0x030000, H263)

+	_MAKE_CODEC_ID (0x040000, S263)

+	_MAKE_CODEC_ID (0x050000, RV)

+	_MAKE_CODEC_ID (0x060000, WMV)

+	_MAKE_CODEC_ID (0x070000, DIVX3)

+	_MAKE_CODEC_ID (0x080000, MJPEG)

+	_MAKE_CODEC_ID (0x090000, MPEG2)

+	_MAKE_CODEC_ID (0x0A0000, VP6)

+

+	// define audio codec modules

+	_MAKE_CODEC_ID (0x210000, AAC)

+	_MAKE_CODEC_ID (0x220000, MP3)

+	_MAKE_CODEC_ID (0x230000, WMA)

+	_MAKE_CODEC_ID (0x240000, RA)

+	_MAKE_CODEC_ID (0x250000, AMRNB)

+	_MAKE_CODEC_ID (0x260000, AMRWB)

+	_MAKE_CODEC_ID (0x270000, AMRWBP)

+	_MAKE_CODEC_ID (0x280000, QCELP)

+	_MAKE_CODEC_ID (0x290000, EVRC)

+	_MAKE_CODEC_ID (0x2A0000, ADPCM)

+	_MAKE_CODEC_ID (0x2B0000, MIDI)

+	_MAKE_CODEC_ID (0x2C0000, AC3)

+	_MAKE_CODEC_ID (0x2D0000, FLAC)

+	_MAKE_CODEC_ID (0x2E0000, DRA)

+	_MAKE_CODEC_ID (0x2F0000, OGG)

+	_MAKE_CODEC_ID (0x300000, G729)

+

+	// define image codec modules

+	_MAKE_CODEC_ID (0x410000, JPEG)

+	_MAKE_CODEC_ID (0x420000, GIF)

+	_MAKE_CODEC_ID (0x430000, PNG)

+	_MAKE_CODEC_ID (0x440000, TIF)

+

+	// define effect modules

+	_MAKE_EFFECT_ID (0x010000, EQ)

+

+	// define sink modules

+	_MAKE_SINK_ID (0x010000, VIDEO)

+	_MAKE_SINK_ID (0x020000, AUDIO)

+	_MAKE_SINK_ID (0x030000, CCRRR)

+	_MAKE_SINK_ID (0x040000, CCRRV)

+

+	_MAKE_SINK_ID (0x110000, MP4)

+	_MAKE_SINK_ID (0x120000, AVI)

+	_MAKE_SINK_ID (0x130000, AFW)

+

+	// define media frame module ID

+	_MAKE_MFW_ID (0x010000, VOMMPLAY)

+	_MAKE_MFW_ID (0x020000, VOMMREC)

+	_MAKE_MFW_ID (0x030000, VOME)

+};

+

+

+/* define the error ID */

+#define VO_ERR_NONE						0x00000000

+#define VO_ERR_FINISH					0x00000001

+#define VO_ERR_BASE						0X80000000

+#define VO_ERR_FAILED					0x80000001

+#define VO_ERR_OUTOF_MEMORY				0x80000002

+#define VO_ERR_NOT_IMPLEMENT			0x80000003

+#define VO_ERR_INVALID_ARG				0x80000004

+#define VO_ERR_INPUT_BUFFER_SMALL		0x80000005

+#define VO_ERR_OUTPUT_BUFFER_SMALL		0x80000006

+#define VO_ERR_WRONG_STATUS				0x80000007

+#define VO_ERR_WRONG_PARAM_ID			0x80000008

+#define VO_ERR_LICENSE_ERROR			0x80000009

+

+/* xxx is the module ID

+#define VO_ERR_FAILED					0x8xxx0001

+#define VO_ERR_OUTOF_MEMORY				0x8xxx0002

+#define VO_ERR_NOT_IMPLEMENT			0x8xxx0003

+#define VO_ERR_INVALID_ARG				0x8xxx0004

+#define VO_ERR_INPUT_BUFFER_SMALL		0x8xxx0005

+#define VO_ERR_OUTPUT_BUFFER_SMALL		0x8xxx0006

+#define VO_ERR_WRONG_STATUS				0x8xxx0007

+#define VO_ERR_WRONG_PARAM_ID			0x8xxx0008

+#define VO_ERR_LICENSE_ERROR			0x8xxx0009

+// Module own error ID

+#define VO_ERR_Module					0x8xxx0X00

+*/

+ 

+#define	VO_PID_COMMON_BASE				 0x40000000						/*!< The base of common param ID */

+#define	VO_PID_COMMON_QUERYMEM			(VO_PID_COMMON_BASE | 0X0001)	/*!< Query the memory needed; Reserved. */

+#define	VO_PID_COMMON_INPUTTYPE			(VO_PID_COMMON_BASE | 0X0002)	/*!< Set or get the input buffer type. VO_INPUT_TYPE */

+#define	VO_PID_COMMON_HASRESOURCE		(VO_PID_COMMON_BASE | 0X0003)	/*!< Query it has resource to be used. VO_U32 *, 1 have, 0 No */

+#define	VO_PID_COMMON_HEADDATA			(VO_PID_COMMON_BASE | 0X0004)	/*!< Decoder track header data. VO_CODECBUFFER * */

+#define	VO_PID_COMMON_FLUSH				(VO_PID_COMMON_BASE | 0X0005)	/*!< Flush the codec buffer. VO_U32 *, 1 Flush, 0 No * */

+

+/*

+// Module Param ID

+#define VO_ID_Mdoule					0x0xxx1000

+*/

+

+#ifdef __cplusplus

+}

+#endif /* __cplusplus */

+

+#endif // __voIndex_H__

diff --git a/media/libstagefright/codecs/common/include/voMem.h b/media/libstagefright/codecs/common/include/voMem.h
new file mode 100644
index 0000000..8dfb634
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voMem.h
@@ -0,0 +1,65 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** 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.
+ */
+/*******************************************************************************
+	File:		voMem.h
+
+	Content:	memory functions & data structures
+
+*******************************************************************************/
+
+#ifndef __voMem_H__
+#define __voMem_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "voIndex.h"
+
+typedef struct
+{
+	VO_S32				Size;				/*!< Buffer stride */
+	VO_S32				Flag;
+	VO_PTR				VBuffer;			/*!< user data pointer */
+	VO_PTR				PBuffer;			/*!< user data pointer */
+}
+VO_MEM_INFO;
+
+typedef struct VO_MEM_OPERATOR
+{
+	VO_U32 (VO_API * Alloc) (VO_S32 uID, VO_MEM_INFO * pMemInfo);
+	VO_U32 (VO_API * Free) (VO_S32 uID, VO_PTR pBuff);
+	VO_U32 (VO_API * Set) (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize);
+	VO_U32 (VO_API * Copy) (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize);
+	VO_U32 (VO_API * Check) (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize);
+	VO_S32 (VO_API * Compare) (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize);
+	VO_U32 (VO_API * Move) (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize);
+} VO_MEM_OPERATOR;
+
+#define voMemAlloc(pBuff, pMemOP, ID, nSize) \
+{ \
+	VO_MEM_INFO voMemInfo; \
+	voMemInfo.Size=nSize; \
+	pMemOP->Alloc(ID, &voMemInfo); \
+	pBuff=(VO_PBYTE)voMemInfo.VBuffer; \
+}
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // __voMem_H__
diff --git a/media/libstagefright/codecs/common/include/voType.h b/media/libstagefright/codecs/common/include/voType.h
new file mode 100644
index 0000000..2669134
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voType.h
@@ -0,0 +1,221 @@
+/*

+ ** Copyright 2003-2010, VisualOn, Inc.

+ **

+ ** 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.

+ */

+/*******************************************************************************

+	File:		voType.h

+

+	Content:	data type definition

+

+*******************************************************************************/

+#ifndef __voType_H__

+#define __voType_H__

+

+#ifdef __cplusplus

+extern "C" {

+#endif /* __cplusplus */

+

+#ifdef _WIN32

+#	define VO_API __cdecl

+#	define VO_CBI __stdcall

+#else

+#	define VO_API

+#	define VO_CBI

+#endif //_WIN32

+

+/** VO_IN is used to identify inputs to an VO function.  This designation

+    will also be used in the case of a pointer that points to a parameter

+    that is used as an output. */

+#ifndef VO_IN

+#define VO_IN

+#endif

+

+/** VO_OUT is used to identify outputs from an VO function.  This

+    designation will also be used in the case of a pointer that points

+    to a parameter that is used as an input. */

+#ifndef VO_OUT

+#define VO_OUT

+#endif

+

+/** VO_INOUT is used to identify parameters that may be either inputs or

+    outputs from an VO function at the same time.  This designation will

+    also be used in the case of a pointer that  points to a parameter that

+    is used both as an input and an output. */

+#ifndef VO_INOUT

+#define VO_INOUT

+#endif

+

+#define VO_MAX_ENUM_VALUE	0X7FFFFFFF

+

+/** VO_VOID */

+typedef void VO_VOID;

+

+/** VO_U8 is an 8 bit unsigned quantity that is byte aligned */

+typedef unsigned char VO_U8;

+

+/** VO_BYTE is an 8 bit unsigned quantity that is byte aligned */

+typedef unsigned char VO_BYTE;

+

+/** VO_S8 is an 8 bit signed quantity that is byte aligned */

+typedef signed char VO_S8;

+

+/** VO_CHAR is an 8 bit signed quantity that is byte aligned */

+typedef char VO_CHAR;

+

+/** VO_U16 is a 16 bit unsigned quantity that is 16 bit word aligned */

+typedef unsigned short VO_U16;

+

+/** VO_WCHAR is a 16 bit unsigned quantity that is 16 bit word aligned */

+#if defined _WIN32

+typedef unsigned short VO_WCHAR;

+typedef unsigned short* VO_PWCHAR;

+#elif defined LINUX

+typedef unsigned char VO_WCHAR;

+typedef unsigned char* VO_PWCHAR;

+#endif

+

+/** VO_S16 is a 16 bit signed quantity that is 16 bit word aligned */

+typedef signed short VO_S16;

+

+/** VO_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */

+typedef unsigned long VO_U32;

+

+/** VO_S32 is a 32 bit signed quantity that is 32 bit word aligned */

+typedef signed long VO_S32;

+

+/* Users with compilers that cannot accept the "long long" designation should

+   define the VO_SKIP64BIT macro.  It should be noted that this may cause

+   some components to fail to compile if the component was written to require

+   64 bit integral types.  However, these components would NOT compile anyway

+   since the compiler does not support the way the component was written.

+*/

+#ifndef VO_SKIP64BIT

+#ifdef _WIN32

+/** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */

+typedef unsigned __int64  VO_U64;

+/** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */

+typedef signed   __int64  VO_S64;

+#else // WIN32

+/** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */

+typedef unsigned long long VO_U64;

+/** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */

+typedef signed long long VO_S64;

+#endif // WIN32

+#endif // VO_SKIP64BIT

+

+/** The VO_BOOL type is intended to be used to represent a true or a false

+    value when passing parameters to and from the VO core and components.  The

+    VO_BOOL is a 32 bit quantity and is aligned on a 32 bit word boundary.

+ */

+typedef enum VO_BOOL {

+    VO_FALSE = 0,

+    VO_TRUE = !VO_FALSE,

+	VO_BOOL_MAX = VO_MAX_ENUM_VALUE

+} VO_BOOL;

+

+/** The VO_PTR type is intended to be used to pass pointers between the VO

+    applications and the VO Core and components.  This is a 32 bit pointer and

+    is aligned on a 32 bit boundary.

+ */

+typedef void* VO_PTR;

+

+/** The VO_HANDLE type is intended to be used to pass pointers between the VO

+    applications and the VO Core and components.  This is a 32 bit pointer and

+    is aligned on a 32 bit boundary.

+ */

+typedef void* VO_HANDLE;

+

+/** The VO_STRING type is intended to be used to pass "C" type strings between

+    the application and the core and component.  The VO_STRING type is a 32

+    bit pointer to a zero terminated string.  The  pointer is word aligned and

+    the string is byte aligned.

+ */

+typedef char* VO_PCHAR;

+

+/** The VO_PBYTE type is intended to be used to pass arrays of bytes such as

+    buffers between the application and the component and core.  The VO_PBYTE

+    type is a 32 bit pointer to a zero terminated string.  The  pointer is word

+    aligned and the string is byte aligned.

+ */

+typedef unsigned char* VO_PBYTE;

+

+/** The VO_PTCHAR type is intended to be used to pass arrays of wchar such as

+    unicode char between the application and the component and core.  The VO_PTCHAR

+    type is a 32 bit pointer to a zero terminated string.  The  pointer is word

+    aligned and the string is byte aligned.

+ */

+/*

+#if !defined LINUX

+typedef unsigned short* VO_PTCHAR;

+typedef unsigned short* VO_TCHAR;

+#else

+typedef char* VO_PTCHAR;

+typedef char VO_TCHAR;

+#endif

+*/

+

+#ifndef NULL

+#ifdef __cplusplus

+#define NULL    0

+#else

+#define NULL    ((void *)0)

+#endif

+#endif

+

+/**

+ * Input stream format, Frame or Stream..

+ */

+typedef enum {

+    VO_INPUT_FRAME	= 1,	/*!< Input contains completely frame(s) data. */

+    VO_INPUT_STREAM,		/*!< Input is stream data. */

+	VO_INPUT_STREAM_MAX = VO_MAX_ENUM_VALUE

+} VO_INPUT_TYPE;

+

+

+/**

+ * General data buffer, used as input or output.

+ */

+typedef struct {

+	VO_PBYTE	Buffer;		/*!< Buffer pointer */

+	VO_U32		Length;		/*!< Buffer size in byte */

+	VO_S64		Time;		/*!< The time of the buffer */

+} VO_CODECBUFFER;

+

+

+/**

+ * The init memdata flag.

+ */

+typedef enum{

+	VO_IMF_USERMEMOPERATOR		=0,	/*!< memData is  the pointer of memoperator function*/

+	VO_IMF_PREALLOCATEDBUFFER	=1,	/*!< memData is  preallocated memory*/

+	VO_IMF_MAX = VO_MAX_ENUM_VALUE

+}VO_INIT_MEM_FlAG;

+

+

+/**

+ * The init memory structure..

+ */

+typedef struct{

+	VO_INIT_MEM_FlAG			memflag;	/*!<memory flag  */

+	VO_PTR						memData;	/*!<a pointer to VO_MEM_OPERATOR or a preallocated buffer  */

+	VO_U32						reserved1;	/*!<reserved  */

+	VO_U32						reserved2;	/*!<reserved */

+}VO_CODEC_INIT_USERDATA;

+

+

+#ifdef __cplusplus

+}

+#endif /* __cplusplus */

+

+#endif // __voType_H__

diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
index 8350f7a..0f08f6e 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
@@ -37,7 +37,8 @@
       mStarted(false),
       mHandle(new tagvideoDecControls),
       mInputBuffer(NULL),
-      mNumSamplesOutput(0) {
+      mNumSamplesOutput(0),
+      mTargetTimeUs(-1) {
 
     LOGV("M4vH263Decoder");
     memset(mHandle, 0, sizeof(tagvideoDecControls));
@@ -146,6 +147,7 @@
     mSource->start();
 
     mNumSamplesOutput = 0;
+    mTargetTimeUs = -1;
     mStarted = true;
 
     return OK;
@@ -175,8 +177,11 @@
         MediaBuffer **out, const ReadOptions *options) {
     *out = NULL;
 
+    bool seeking = false;
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+        seeking = true;
         CHECK_EQ(PVResetVideoDecoder(mHandle), PV_TRUE);
     }
 
@@ -186,6 +191,16 @@
         return err;
     }
 
+    if (seeking) {
+        int64_t targetTimeUs;
+        if (inputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
+                && targetTimeUs >= 0) {
+            mTargetTimeUs = targetTimeUs;
+        } else {
+            mTargetTimeUs = -1;
+        }
+    }
+
     uint8_t *bitstream =
         (uint8_t *) inputBuffer->data() + inputBuffer->range_offset();
 
@@ -221,17 +236,40 @@
         return INFO_FORMAT_CHANGED;
     }
 
-    *out = mFrames[mNumSamplesOutput & 0x01];
-    (*out)->add_ref();
-
     int64_t timeUs;
     CHECK(inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
-    (*out)->meta_data()->setInt64(kKeyTime, timeUs);
 
-    ++mNumSamplesOutput;
     inputBuffer->release();
     inputBuffer = NULL;
 
+    bool skipFrame = false;
+
+    if (mTargetTimeUs >= 0) {
+        CHECK(timeUs <= mTargetTimeUs);
+
+        if (timeUs < mTargetTimeUs) {
+            // We're still waiting for the frame with the matching
+            // timestamp and we won't return the current one.
+            skipFrame = true;
+
+            LOGV("skipping frame at %lld us", timeUs);
+        } else {
+            LOGV("found target frame at %lld us", timeUs);
+
+            mTargetTimeUs = -1;
+        }
+    }
+
+    if (skipFrame) {
+        *out = new MediaBuffer(0);
+    } else {
+        *out = mFrames[mNumSamplesOutput & 0x01];
+        (*out)->add_ref();
+        (*out)->meta_data()->setInt64(kKeyTime, timeUs);
+    }
+
+    ++mNumSamplesOutput;
+
     return OK;
 }
 
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
new file mode 100644
index 0000000..f2c9320
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
@@ -0,0 +1,37 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+    M4vH263Encoder.cpp \
+    src/bitstream_io.cpp \
+    src/combined_encode.cpp \
+    src/datapart_encode.cpp \
+    src/dct.cpp \
+    src/findhalfpel.cpp \
+    src/fastcodemb.cpp \
+    src/fastidct.cpp \
+    src/fastquant.cpp \
+    src/me_utils.cpp \
+    src/mp4enc_api.cpp \
+    src/rate_control.cpp \
+    src/motion_est.cpp \
+    src/motion_comp.cpp \
+    src/sad.cpp \
+    src/sad_halfpel.cpp \
+    src/vlc_encode.cpp \
+    src/vop.cpp
+
+
+LOCAL_MODULE := libstagefright_m4vh263enc
+
+LOCAL_CFLAGS := \
+    -DBX_RC \
+    -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+
+LOCAL_C_INCLUDES := \
+    $(LOCAL_PATH)/src \
+    $(LOCAL_PATH)/include \
+    $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+    $(TOP)/frameworks/base/media/libstagefright/include
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
new file mode 100644
index 0000000..5002442
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2010 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 "M4vH263Encoder"
+#include <utils/Log.h>
+
+#include "M4vH263Encoder.h"
+
+#include "mp4enc_api.h"
+#include "OMX_Video.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+inline static void ConvertYUV420SemiPlanarToYUV420Planar(
+        uint8_t *inyuv, uint8_t* outyuv,
+        int32_t width, int32_t height) {
+
+    int32_t outYsize = width * height;
+    uint32_t *outy = (uint32_t *)  outyuv;
+    uint16_t *outcb = (uint16_t *) (outyuv + outYsize);
+    uint16_t *outcr = (uint16_t *) (outyuv + outYsize + (outYsize >> 2));
+
+    /* Y copying */
+    memcpy(outy, inyuv, outYsize);
+
+    /* U & V copying */
+    uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
+    for (int32_t i = height >> 1; i > 0; --i) {
+        for (int32_t j = width >> 2; j > 0; --j) {
+            uint32_t temp = *inyuv_4++;
+            uint32_t tempU = temp & 0xFF;
+            tempU = tempU | ((temp >> 8) & 0xFF00);
+
+            uint32_t tempV = (temp >> 8) & 0xFF;
+            tempV = tempV | ((temp >> 16) & 0xFF00);
+
+            // Flip U and V
+            *outcb++ = tempV;
+            *outcr++ = tempU;
+        }
+    }
+}
+
+M4vH263Encoder::M4vH263Encoder(
+        const sp<MediaSource>& source,
+        const sp<MetaData>& meta)
+    : mSource(source),
+      mMeta(meta),
+      mNumInputFrames(-1),
+      mNextModTimeUs(0),
+      mStarted(false),
+      mInputBuffer(NULL),
+      mInputFrameData(NULL),
+      mGroup(NULL) {
+
+    LOGV("Construct software M4vH263Encoder");
+
+    mHandle = new tagvideoEncControls;
+    memset(mHandle, 0, sizeof(tagvideoEncControls));
+
+    mInitCheck = initCheck(meta);
+}
+
+M4vH263Encoder::~M4vH263Encoder() {
+    LOGV("Destruct software M4vH263Encoder");
+    if (mStarted) {
+        stop();
+    }
+
+    delete mEncParams;
+    delete mHandle;
+}
+
+status_t M4vH263Encoder::initCheck(const sp<MetaData>& meta) {
+    LOGV("initCheck");
+    CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
+    CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
+    CHECK(meta->findInt32(kKeySampleRate, &mVideoFrameRate));
+    CHECK(meta->findInt32(kKeyBitRate, &mVideoBitRate));
+
+    // XXX: Add more color format support
+    CHECK(meta->findInt32(kKeyColorFormat, &mVideoColorFormat));
+    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+        if (mVideoColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
+            LOGE("Color format %d is not supported", mVideoColorFormat);
+            return BAD_VALUE;
+        }
+        // Allocate spare buffer only when color conversion is needed.
+        // Assume the color format is OMX_COLOR_FormatYUV420SemiPlanar.
+        mInputFrameData =
+            (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+        CHECK(mInputFrameData);
+    }
+
+    // XXX: Remove this restriction
+    if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+        LOGE("Video frame size %dx%d must be a multiple of 16",
+            mVideoWidth, mVideoHeight);
+        return BAD_VALUE;
+    }
+
+    mEncParams = new tagvideoEncOptions;
+    memset(mEncParams, 0, sizeof(tagvideoEncOptions));
+    if (!PVGetDefaultEncOption(mEncParams, 0)) {
+        LOGE("Failed to get default encoding parameters");
+        return BAD_VALUE;
+    }
+
+    // Need to know which role the encoder is in.
+    // XXX: Set the mode proper for other types of applications
+    //      like streaming or video conference
+    const char *mime;
+    CHECK(meta->findCString(kKeyMIMEType, &mime));
+    CHECK(!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
+          !strcmp(mime, MEDIA_MIMETYPE_VIDEO_H263));
+    if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
+        mEncParams->encMode = COMBINE_MODE_WITH_ERR_RES;
+    } else {
+        mEncParams->encMode = H263_MODE;
+    }
+    mEncParams->encWidth[0] = mVideoWidth;
+    mEncParams->encHeight[0] = mVideoHeight;
+    mEncParams->encFrameRate[0] = mVideoFrameRate;
+    mEncParams->rcType = VBR_1;
+    mEncParams->vbvDelay = (float)5.0;
+
+    // Set profile and level
+    // If profile and level setting is not correct, failure
+    // is reported when the encoder is initialized.
+    mEncParams->profile_level = CORE_PROFILE_LEVEL2;
+    int32_t profileLevel;
+    if (meta->findInt32(kKeyVideoLevel, &profileLevel)) {
+        mEncParams->profile_level = (ProfileLevelType)profileLevel;
+    }
+
+    mEncParams->packetSize = 32;
+    mEncParams->rvlcEnable = PV_OFF;
+    mEncParams->numLayers = 1;
+    mEncParams->timeIncRes = 1000;
+    mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate;
+
+    mEncParams->bitRate[0] = mVideoBitRate;
+    mEncParams->iQuant[0] = 15;
+    mEncParams->pQuant[0] = 12;
+    mEncParams->quantType[0] = 0;
+    mEncParams->noFrameSkipped = PV_OFF;
+
+    // Set IDR frame refresh interval
+    int32_t iFramesIntervalSec;
+    CHECK(meta->findInt32(kKeyIFramesInterval, &iFramesIntervalSec));
+    if (iFramesIntervalSec < 0) {
+        mEncParams->intraPeriod = -1;
+    } else if (iFramesIntervalSec == 0) {
+        mEncParams->intraPeriod = 1;  // All I frames
+    } else {
+        mEncParams->intraPeriod =
+            (iFramesIntervalSec * mVideoFrameRate);
+    }
+
+    mEncParams->numIntraMB = 0;
+    mEncParams->sceneDetect = PV_ON;
+    mEncParams->searchRange = 16;
+    mEncParams->mv8x8Enable = PV_OFF;
+    mEncParams->gobHeaderInterval = 0;
+    mEncParams->useACPred = PV_ON;
+    mEncParams->intraDCVlcTh = 0;
+
+    mFormat = new MetaData;
+    mFormat->setInt32(kKeyWidth, mVideoWidth);
+    mFormat->setInt32(kKeyHeight, mVideoHeight);
+    mFormat->setInt32(kKeyBitRate, mVideoBitRate);
+    mFormat->setInt32(kKeySampleRate, mVideoFrameRate);
+    mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
+
+    mFormat->setCString(kKeyMIMEType, mime);
+    mFormat->setCString(kKeyDecoderComponent, "M4vH263Encoder");
+    return OK;
+}
+
+status_t M4vH263Encoder::start(MetaData *params) {
+    LOGV("start");
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mStarted) {
+        LOGW("Call start() when encoder already started");
+        return OK;
+    }
+
+    if (!PVInitVideoEncoder(mHandle, mEncParams)) {
+        LOGE("Failed to initialize the encoder");
+        return UNKNOWN_ERROR;
+    }
+
+    mGroup = new MediaBufferGroup();
+    int32_t maxSize;
+    if (!PVGetMaxVideoFrameSize(mHandle, &maxSize)) {
+        maxSize = 256 * 1024;  // Magic #
+    }
+    LOGV("Max output buffer size: %d", maxSize);
+    mGroup->add_buffer(new MediaBuffer(maxSize));
+
+    mSource->start(params);
+    mNumInputFrames = -1;  // 1st frame contains codec specific data
+    mStarted = true;
+
+    return OK;
+}
+
+status_t M4vH263Encoder::stop() {
+    LOGV("stop");
+    if (!mStarted) {
+        LOGW("Call stop() when encoder has not started");
+        return OK;
+    }
+
+    if (mInputBuffer) {
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+    }
+
+    if (mGroup) {
+        delete mGroup;
+        mGroup = NULL;
+    }
+
+    if (mInputFrameData) {
+        delete mInputFrameData;
+        mInputFrameData = NULL;
+    }
+
+    CHECK(PVCleanUpVideoEncoder(mHandle));
+
+    mSource->stop();
+    mStarted = false;
+
+    return OK;
+}
+
+sp<MetaData> M4vH263Encoder::getFormat() {
+    LOGV("getFormat");
+    return mFormat;
+}
+
+status_t M4vH263Encoder::read(
+        MediaBuffer **out, const ReadOptions *options) {
+
+    *out = NULL;
+
+    MediaBuffer *outputBuffer;
+    CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer));
+    uint8_t *outPtr = (uint8_t *) outputBuffer->data();
+    int32_t dataLength = outputBuffer->size();
+
+    // Output codec specific data
+    if (mNumInputFrames < 0) {
+        if (!PVGetVolHeader(mHandle, outPtr, &dataLength, 0)) {
+            LOGE("Failed to get VOL header");
+            return UNKNOWN_ERROR;
+        }
+        LOGV("Output VOL header: %d bytes", dataLength);
+        outputBuffer->meta_data()->setInt32(kKeyIsCodecConfig, 1);
+        outputBuffer->set_range(0, dataLength);
+        *out = outputBuffer;
+        ++mNumInputFrames;
+        return OK;
+    }
+
+    // Ready for accepting an input video frame
+    if (OK != mSource->read(&mInputBuffer, options)) {
+        LOGE("Failed to read from data source");
+        outputBuffer->release();
+        return UNKNOWN_ERROR;
+    }
+    int64_t timeUs;
+    CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+    if (mNextModTimeUs > timeUs) {
+        LOGV("mNextModTimeUs %lld > timeUs %lld", mNextModTimeUs, timeUs);
+        outputBuffer->set_range(0, 0);
+        *out = outputBuffer;
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+        return OK;
+    }
+
+    // Color convert to OMX_COLOR_FormatYUV420Planar if necessary
+    outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+    uint8_t *inPtr = (uint8_t *) mInputBuffer->data();
+    if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+        CHECK(mInputFrameData);
+        CHECK(mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar);
+        ConvertYUV420SemiPlanarToYUV420Planar(
+            inPtr, mInputFrameData, mVideoWidth, mVideoHeight);
+        inPtr = mInputFrameData;
+    }
+    CHECK(inPtr != NULL);
+
+    // Ready for encoding a video frame
+    VideoEncFrameIO vin, vout;
+    vin.height = ((mVideoHeight + 15) >> 4) << 4;
+    vin.pitch  = ((mVideoWidth  + 15) >> 4) << 4;
+    vin.timestamp = (timeUs + 500) / 1000; // in ms
+    vin.yChan = inPtr;
+    vin.uChan = vin.yChan + vin.height * vin.pitch;
+    vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2);
+    unsigned long modTimeMs = 0;
+    int32_t nLayer = 0;
+    MP4HintTrack hintTrack;
+    if (!PVEncodeVideoFrame(mHandle, &vin, &vout,
+            &modTimeMs, outPtr, &dataLength, &nLayer) ||
+        !PVGetHintTrack(mHandle, &hintTrack)) {
+        LOGE("Failed to encode frame or get hink track at frame %lld",
+            mNumInputFrames);
+        outputBuffer->release();
+        mInputBuffer->release();
+        mInputBuffer = NULL;
+        return UNKNOWN_ERROR;
+    }
+    CHECK_EQ(NULL, PVGetOverrunBuffer(mHandle));
+    if (hintTrack.CodeType == 0) {  // I-frame serves as sync frame
+        outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+    }
+
+    ++mNumInputFrames;
+    mNextModTimeUs = modTimeMs * 1000LL;
+    outputBuffer->set_range(0, dataLength);
+    *out = outputBuffer;
+    mInputBuffer->release();
+    mInputBuffer = NULL;
+    return OK;
+}
+
+void M4vH263Encoder::signalBufferReturned(MediaBuffer *buffer) {
+}
+
+}  // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/enc/include/cvei.h b/media/libstagefright/codecs/m4v_h263/enc/include/cvei.h
new file mode 100644
index 0000000..18e54dc
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/include/cvei.h
@@ -0,0 +1,437 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/*  File: cvei.h                                                                */
+/*  Purpose:                                                                    */
+/*  Date:                                                                       */
+/*  Revision History:                                                           */
+/** @introduction   Common Video Encoder Interface (CVEI) is intended to be used by
+    application developers who want to create a multimedia application with video
+    encoding feature. CVEI is designed such that new video encoder algorithms or
+    modules can be plugged in seamlessly without user interaction. In other words,
+    any changes to the CVEI library are transparent to the users. Users can still
+    use the same set of APIs for new encoding tools.
+
+    @requirement    CVEI will take an input frame in one of several format supported
+    by PV and encode it to an MPEG4 bitstream. It will also return a reconstructed
+    image in YUV 4:2:0 format. Currently the input format supported are YUV 4:2:0,
+    RGB24 and UYVY 4:2:2.
+
+    CVEI is designed such that it is simple to use. It should hides implementation
+    dependency  from the users. In this version, we decided that the operation will
+    be synchronous, i.e., the encoding will be a blocked call. Asynchronous operation
+    will be in the level above CVEI, i.e., in Author Engine Video Module which will
+    take care of capturing device as well.
+
+    @brief  The following classes are used to interface with codecs. Their names
+    are CPVxxxVideoEncoder where xxx is codec specific such as MPEG4, H263, H26L,
+    etc. All of them are subclasses of CPVCommonVideoEncoder.
+*/
+/*********************************************************************************/
+
+#ifndef __CVEI_H
+#define __CVEI_H
+
+#include "oscl_scheduler_ao.h"
+#include "oscl_base.h"
+#include "mp4enc_api.h" /* for MP4HintTrack */
+
+#define MAX_LAYER 2
+
+/** General returned values. */
+enum TCVEI_RETVAL
+{
+    ECVEI_SUCCESS,
+    ECVEI_FAIL,
+    ECVEI_FLUSH,
+    ECVEI_MORE_OUTPUT
+} ;
+
+/** Returned events with the callback function. */
+enum TCVEI_EVENT
+{
+    /** Called when a packet or a frame of output bitstream is ready. */
+    ECVEI_BUFFER_READY,
+
+    /** Called when the last packet of a frame of output bitstream is ready. */
+    ECVEI_FRAME_DONE,
+
+    /** Called when no buffers is available for output bitstream. A buffer can be added thru AddBuffer API. */
+    ECVEI_NO_BUFFERS,
+
+    /** Called when there is an error with the encoding operation. */
+    ECVEI_ERROR
+};
+
+/** Contains supported input format */
+enum TPVVideoFormat
+{
+    ECVEI_RGB24,
+    ECVEI_RGB12,
+    ECVEI_YUV420,
+    ECVEI_UYVY,
+    ECVEI_YUV420SEMIPLANAR
+};
+
+/** Type of contents for optimal encoding mode. */
+enum TPVContentType
+{
+    /** Content is to be streamed in real-time. */
+    ECVEI_STREAMING,
+
+    /** Content is to be downloaded and playbacked later.*/
+    ECVEI_DOWNLOAD,
+
+    /** Content is to be 3gpp baseline compliant. */
+    ECVEI_H263
+};
+
+/** Rate control type. */
+enum TMP4RateControlType
+{
+    /** Constant quality, variable bit rate, fixed quantization level. */
+    ECONSTANT_Q,
+
+    /** Short-term constant bit rate control. */
+    ECBR_1,
+
+    /** Long-term constant bit rate control. */
+    EVBR_1
+};
+
+/** Targeted profile and level to encode. */
+enum TPVM4VProfileLevel
+{
+    /* Non-scalable profile */
+    ECVEI_SIMPLE_LEVEL0 = 0,
+    ECVEI_SIMPLE_LEVEL1,
+    ECVEI_SIMPLE_LEVEL2,
+    ECVEI_SIMPLE_LEVEL3,
+    ECVEI_CORE_LEVEL1,
+    ECVEI_CORE_LEVEL2,
+
+    /* Scalable profile */
+    ECVEI_SIMPLE_SCALABLE_LEVEL0 = 6,
+    ECVEI_SIMPLE_SCALABLE_LEVEL1,
+    ECVEI_SIMPLE_SCALABLE_LEVEL2,
+
+    ECVEI_CORE_SCALABLE_LEVEL1 = 10,
+    ECVEI_CORE_SCALABLE_LEVEL2,
+    ECVEI_CORE_SCALABLE_LEVEL3
+};
+
+/** This structure contains encoder settings. */
+struct TPVVideoEncodeParam
+{
+    /** Specifies an  ID that will be used to specify this encoder while returning
+    the bitstream in asynchronous mode. */
+    uint32              iEncodeID;
+
+    /** Specifies whether base only (iNumLayer = 1) or base + enhancement layer
+    (iNumLayer =2 ) is to be used. */
+    int32               iNumLayer;
+
+    /** Specifies the width in pixels of the encoded frames. IFrameWidth[0] is for
+    base layer and iFrameWidth[1] is for enhanced layer. */
+    int                 iFrameWidth[MAX_LAYER];
+
+    /** Specifies the height in pixels of the encoded frames. IFrameHeight[0] is for
+    base layer and iFrameHeight[1] is for enhanced layer. */
+    int                 iFrameHeight[MAX_LAYER];
+
+    /** Specifies the cumulative bit rate in bit per second. IBitRate[0] is for base
+    layer and iBitRate[1] is for base+enhanced layer.*/
+    int                 iBitRate[MAX_LAYER];
+
+    /** Specifies the cumulative frame rate in frame per second. IFrameRate[0] is for
+    base layer and iFrameRate[1] is for base+enhanced layer. */
+    float               iFrameRate[MAX_LAYER];
+
+    /** Specifies the picture quality factor on the scale of 1 to 10. It trades off
+    the picture quality with the frame rate. Higher frame quality means lower frame rate.
+    Lower frame quality for higher frame rate.*/
+    int32               iFrameQuality;
+
+    /** Enable the use of iFrameQuality to determine the frame rate. If it is false,
+    the encoder will try to meet the specified frame rate regardless of the frame quality.*/
+    bool                iEnableFrameQuality;
+
+    /** Specifies the maximum number of P-frames between 2 INTRA frames. An INTRA mode is
+    forced to a frame once this interval is reached. When there is only one I-frame is present
+    at the beginning of the clip, iIFrameInterval should be set to -1. */
+    int32               iIFrameInterval;
+
+    /** According to iIFrameInterval setting, the minimum number of intra MB per frame is
+    optimally calculated for error resiliency. However, when iIFrameInterval is set to -1,
+    iNumIntraMBRefresh must be specified to guarantee the minimum number of intra
+    macroblocks per frame.*/
+    uint32              iNumIntraMBRefresh;
+
+    /** Specifies the VBV buffer size which determines the end-to-end delay between the
+    encoder and the decoder.  The size is in unit of seconds. For download application,
+    the buffer size can be larger than the streaming application. For 2-way application,
+    this buffer shall be kept minimal. For a special case, in VBR mode, iBufferDelay will
+    be set to -1 to allow buffer underflow. */
+    float               iBufferDelay;
+
+    /** Specifies the type of the access whether it is streaming, CVEI_STREAMING
+    (data partitioning mode) or download, CVEI_DOWNLOAD (combined mode).*/
+    TPVContentType      iContentType;
+
+    /** Specifies the rate control algorithm among one of the following constant Q,
+    CBR and VBR.  The structure TMP4RateControlType is defined below.*/
+    TMP4RateControlType iRateControlType;
+
+    /** Specifies high quality but also high complexity mode for rate control. */
+    bool                iRDOptimal;
+
+    /** Specifies the initial quantization parameter for the first I-frame. If constant Q
+    rate control is used, this QP will be used for all the I-frames. This number must be
+    set between 1 and 31, otherwise, Initialize() will fail. */
+    int                 iIquant[2];
+
+    /** Specifies the initial quantization parameter for the first P-frame. If constant Q
+    rate control is used, this QP will be used for all the P-frames. This number must be
+    set between 1 and 31, otherwise, Initialize() will fail. */
+    int                 iPquant[2];
+
+    /** Specifies the initial quantization parameter for the first B-frame. If constant Q
+    rate control is used, this QP will be used for all the B-frames. This number must be
+    set between 1 and 31, otherwise, Initialize() will fail. */
+    int                 iBquant[2];
+
+    /** Specifies the search range in pixel unit for motion vector. The range of the
+    motion vector will be of dimension [-iSearchRange.5, +iSearchRange.0]. */
+    int32               iSearchRange;
+
+    /** Specifies the use of 8x8 motion vectors. */
+    bool                iMV8x8;
+
+    /** Specifies the use of half-pel motion vectors. */
+    bool                iMVHalfPel;
+
+    /** Specifies automatic scene detection where I-frame will be used the the first frame
+    in a new scene. */
+    bool                iSceneDetection;
+
+    /** Specifies the packet size in bytes which represents the number of bytes between two resync markers.
+    For ECVEI_DOWNLOAD and ECVEI_H263, if iPacketSize is set to 0, there will be no resync markers in the bitstream.
+    For ECVEI_STREAMING is parameter must be set to a value greater than 0.*/
+    uint32              iPacketSize;
+
+    /** Specifies whether the current frame skipping decision is allowed after encoding
+    the current frame. If there is no memory of what has been coded for the current frame,
+    iNoCurrentSkip has to be on. */
+    bool                iNoCurrentSkip;
+
+    /** Specifies that no frame skipping is allowed. Frame skipping is a tool used to
+    control the average number of bits spent to meet the target bit rate. */
+    bool                iNoFrameSkip;
+
+    /** Specifies the duration of the clip in millisecond.*/
+    int32               iClipDuration;
+
+    /** Specifies the profile and level used to encode the bitstream. When present,
+    other settings will be checked against the range allowable by this target profile
+    and level. Fail may be returned from the Initialize call. */
+    TPVM4VProfileLevel  iProfileLevel;
+
+    /** Specifies FSI Buffer input */
+    uint8*              iFSIBuff;
+
+    /** Specifies FSI Buffer Length */
+    int             iFSIBuffLength;
+
+
+};
+
+
+/** Structure for input format information */
+struct TPVVideoInputFormat
+{
+    /** Contains the width in pixels of the input frame. */
+    int32           iFrameWidth;
+
+    /** Contains the height in pixels of the input frame. */
+    int32           iFrameHeight;
+
+    /** Contains the input frame rate in the unit of frame per second. */
+    float           iFrameRate;
+
+    /** Contains Frame Orientation. Used for RGB input. 1 means Bottom_UP RGB, 0 means Top_Down RGB, -1 for video formats other than RGB*/
+    int             iFrameOrientation;
+
+    /** Contains the format of the input video, e.g., YUV 4:2:0, UYVY, RGB24, etc. */
+    TPVVideoFormat  iVideoFormat;
+};
+
+
+/** Contains the input data information */
+struct TPVVideoInputData
+{
+    /** Pointer to an input frame buffer in input source format.*/
+    uint8       *iSource;
+
+    /** The corresponding time stamp of the input frame. */
+    uint32      iTimeStamp;
+};
+
+/** Contains the output data information */
+struct TPVVideoOutputData
+{
+    /** Pointer to the reconstructed frame buffer in YUV 4:2:0 domain. */
+    uint8           *iFrame;
+
+    /** The number of layer encoded, 0 for base, 1 for enhanced. */
+    int32           iLayerNumber;
+
+    /** Pointer to the encoded bitstream buffer. */
+    uint8           *iBitStream;
+
+    /** The size in bytes of iBStream. */
+    int32           iBitStreamSize;
+
+    /** The time stamp of the encoded frame according to the bitstream. */
+    uint32          iVideoTimeStamp;
+
+    /** The time stamp of the encoded frame as given before the encoding. */
+    uint32          iExternalTimeStamp;
+
+    /** The hint track information. */
+    MP4HintTrack    iHintTrack;
+};
+
+/** An observer class for callbacks to report the status of the CVEI */
+class MPVCVEIObserver
+{
+    public:
+        /** The callback funtion with aEvent being one of TCVEIEvent enumeration. */
+        virtual void HandlePVCVEIEvent
+        (uint32 aId, uint32 aEvent, uint32 aParam1 = 0) = 0;
+        virtual ~MPVCVEIObserver() {}
+};
+
+/** This class is the base class for codec specific interface class.
+The users must maintain an instance of the codec specific class throughout
+the encoding session.
+*/
+class CommonVideoEncoder : public OsclTimerObject
+{
+    public:
+        /** Constructor for CVEI class. */
+        CommonVideoEncoder() : OsclTimerObject(OsclActiveObject::EPriorityNominal, "PVEncoder") {};
+
+        /** Initialization function to set the input video format and the
+        encoding parameters. This function returns CVEI_ERROR if there is
+        any errors. Otherwise, the function returns CVEI_SUCCESS.*/
+        virtual  TCVEI_RETVAL Initialize(TPVVideoInputFormat *aVidInFormat, TPVVideoEncodeParam *aEncParam) = 0;
+
+        /** Set the observer for asynchronous encoding mode. */
+        virtual  TCVEI_RETVAL SetObserver(MPVCVEIObserver *aObserver) = 0;
+
+        /** Add a buffer to the queue of output buffers for output bitstream in
+        asynchronous encoding mode. */
+        virtual  TCVEI_RETVAL AddBuffer(TPVVideoOutputData *aVidOut) = 0;
+
+        /** This function sends in an input video data structure containing a source
+        frame and the associated timestamp. The encoded bitstream will be returned by
+        observer callback.
+        The above 3 APIs only replace EncodeFrame() API. Other APIs such as initialization
+        and update parameters remain the same. */
+        virtual  TCVEI_RETVAL Encode(TPVVideoInputData *aVidIn) = 0;
+
+        /** This function returns the maximum VBV buffer size such that the
+            application can allocate a buffer that guarantees to fit one frame.*/
+        virtual  int32 GetBufferSize() = 0;
+
+        /** This function returns the VOL header part (starting from the VOS header)
+        of the encoded bitstream. This function must be called after Initialize.
+        The output is written to the memory (volHeader) allocated by the users.*/
+        virtual  TCVEI_RETVAL GetVolHeader(uint8 *volHeader, int32 *size, int32 layer) = 0;
+
+        /** This function sends in an input video data structure containing a source
+        frame and the associated timestamp. It returns an output video data structure
+        containing coded bit stream, reconstructed frame in YUV 4:2:0 (can be changed
+        to source format) and the timestamp associated with the coded frame.
+        The input timestamp may not correspond to the output timestamp. User can send
+        an input structure in without getting any encoded data back or getting an encoded
+        frame in the past. This function returns ECVEI_ERROR if there is any errors.
+        Otherwise, the function returns ECVEI_SUCCESS.
+        In case of Overrun Buffer usage, it is possible that return value is ECVEI_MORE_OUTPUT
+        which indicates that frame cannot fit in the current buffer*/
+        virtual  TCVEI_RETVAL EncodeFrame(TPVVideoInputData  *aVidIn, TPVVideoOutputData *aVidOut, int *aRemainingBytes
+#ifdef PVAUTHOR_PROFILING
+                                          , void *aParam1 = 0
+#endif
+                                         ) = 0;
+
+        /** Before the termination of the encoding process, the users have to query
+        whether there are any encoded frame pending inside the CVEI. The returned value
+        will indicate whether there are more frames to be flushed (ECVEI_FLUSH).
+        FlushOutput has to be called until there are no more frames, i.e., it returns
+        ECVEI_SUCCESS. This function may be called during the encoding operation if
+        there is no input frame and the application does not want to waste the time
+        waiting for input frame. It can call this function to flush encoded frame
+        out of the memory. */
+        virtual  TCVEI_RETVAL FlushOutput(TPVVideoOutputData *aVidOut) = 0;
+
+        /** This function cleanup the CVEI allocated resources. */
+        virtual  TCVEI_RETVAL Terminate() = 0;
+
+        /**This function dynamically changes the target bit rate of the encoder
+        while encoding. aBitRate[n] is the new accumulate target bit rate of layer n.
+        Successful update is returned with ECVEI_SUCCESS.*/
+        virtual  TCVEI_RETVAL UpdateBitRate(int32 aNumLayer, int32 *aBitRate) = 0;
+
+        /** This function dynamically changes the target frame rate of the encoder
+        while encoding. aFrameRate[n] is the new accumulate target frame rate of
+        layer n. Successful update is returned with ECVEI_SUCCESS. */
+        virtual  TCVEI_RETVAL UpdateFrameRate(int32 aNumLayer, float *aFrameRate) = 0;
+
+        /** This function dynamically changes the I-Vop update interval while
+        encoding to a new value, aIFrameInterval. */
+        virtual  TCVEI_RETVAL UpdateIFrameInterval(int32 aIFrameInterval) = 0;
+
+        /** This function forces an I-Vop mode to the next frame to be encoded. */
+        virtual  TCVEI_RETVAL IFrameRequest() = 0;
+
+        /** This function returns the input width of a specific layer
+        (not necessarily multiple of 16). */
+        virtual  int32 GetEncodeWidth(int32 aLayer) = 0;
+
+        /** This function returns the input height of a specific layer
+        (not necessarily multiple of 16). */
+        virtual  int32 GetEncodeHeight(int32 aLayer) = 0;
+
+        /** This function returns the target encoded frame rate of a specific layer. */
+        virtual  float GetEncodeFrameRate(int32 aLayer) = 0;
+    protected:
+        virtual void Run(void) = 0;
+        virtual void DoCancel(void) = 0;
+        /* internal enum */
+        enum TCVEIState
+        {
+            EIdle,
+            EEncode
+        };
+
+        TCVEIState  iState;
+        uint32      iId;
+};
+
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h b/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h
new file mode 100644
index 0000000..a54fd8b
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h
@@ -0,0 +1,454 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _MP4ENC_API_H_
+#define _MP4ENC_API_H_
+
+#include <string.h>
+
+#ifndef _PV_TYPES_
+#define _PV_TYPES_
+typedef unsigned char UChar;
+typedef char Char;
+typedef unsigned int UInt;
+typedef int Int;
+typedef unsigned short UShort;
+typedef short Short;
+typedef unsigned int Bool;
+typedef unsigned long ULong;
+
+#define PV_CODEC_INIT  0
+#define PV_CODEC_STOP  1
+#endif
+
+#define PV_TRUE  1
+#define PV_FALSE 0
+
+typedef enum
+{
+    SHORT_HEADER,
+    SHORT_HEADER_WITH_ERR_RES,
+    H263_MODE,
+    H263_MODE_WITH_ERR_RES,
+    DATA_PARTITIONING_MODE,
+    COMBINE_MODE_NO_ERR_RES,
+    COMBINE_MODE_WITH_ERR_RES
+
+} MP4EncodingMode;
+
+typedef enum
+{
+    CONSTANT_Q,
+    CBR_1,
+    VBR_1,
+    CBR_2,
+    VBR_2,
+    CBR_LOWDELAY
+} MP4RateControlType;
+
+typedef enum
+{
+    PASS1,
+    PASS2
+} PassNum;
+
+typedef enum
+{
+    PV_OFF,
+    PV_ON
+} ParamEncMode;
+
+
+/* {SPL0, SPL1, SPL2, SPL3, CPL1, CPL2, CPL2, CPL2} , SPL0: Simple Profile@Level0 , CPL1: Core Profile@Level1 */
+/* {SSPL0, SSPL1, SSPL2, SSPL2, CSPL1, CSPL2, CSPL3, CSPL3} , SSPL0: Simple Scalable Profile@Level0, CPL1: Core Scalable Profile@Level1 */
+
+typedef enum
+{
+    /* Non-scalable profile */
+    SIMPLE_PROFILE_LEVEL0 = 0,
+    SIMPLE_PROFILE_LEVEL1,
+    SIMPLE_PROFILE_LEVEL2,
+    SIMPLE_PROFILE_LEVEL3,
+    CORE_PROFILE_LEVEL1,
+    CORE_PROFILE_LEVEL2,
+
+    /* Scalable profile */
+    SIMPLE_SCALABLE_PROFILE_LEVEL0 = 6,
+    SIMPLE_SCALABLE_PROFILE_LEVEL1,
+    SIMPLE_SCALABLE_PROFILE_LEVEL2,
+
+    CORE_SCALABLE_PROFILE_LEVEL1 = 10,
+    CORE_SCALABLE_PROFILE_LEVEL2,
+    CORE_SCALABLE_PROFILE_LEVEL3
+
+} ProfileLevelType;
+
+
+typedef struct tagMP4HintTrack
+{
+    UChar   MTB;
+    UChar   LayerID;
+    UChar   CodeType;
+    UChar   RefSelCode;
+} MP4HintTrack;
+
+typedef struct tagvideoEncControls
+{
+    void            *videoEncoderData;
+    Int             videoEncoderInit;
+} VideoEncControls;
+
+
+typedef struct tagvideoEncFrameIO
+{
+    UChar   *yChan; /* pointer to Y */
+    UChar   *uChan; /* pointer to U */
+    UChar   *vChan; /* pointer to V */
+    Int     height; /* height for Y */
+    Int     pitch;  /* stride  for Y */
+    ULong   timestamp; /* modulo timestamp in millisecond*/
+
+}   VideoEncFrameIO  ;
+
+/**
+@brief  Encoding options structure */
+typedef struct tagvideoEncOptions
+{
+    /** @brief Sets the encoding mode, defined by the above enumaration. If there are conflicts between the encoding mode
+    *   and subsequent encoding options, encoding mode take precedent over encoding options. */
+    MP4EncodingMode     encMode;
+
+    /** @brief Sets the number of bytes per packet, only used in DATA_PARTITIONING_MODE or COMBINE_MODE_WITH_ERR_RES mode.
+    *           The resync marker will be inserted as often as the size of the packet.*/
+    Int                 packetSize;
+
+    /** @brief Selects MPEG-4/H.263 profile and level, if specified other encoding options must conform with it. */
+    ProfileLevelType    profile_level;
+
+    /** @brief Enables reversible variable length code (RVLC) mode. Normally it is set to PV_OFF.*/
+    ParamEncMode        rvlcEnable;
+
+    /** @brief Set the frequency of GOB header interval */
+    Int                 gobHeaderInterval;
+
+    /** @brief Sets the number of bitstream layers: 1 is base only: 2 is base + enhancement */
+    Int                 numLayers;
+
+    /** @brief Sets the number of ticks per second used for timing information encoded in MPEG4 bitstream.*/
+    Int                 timeIncRes;
+
+    /** @brief Sets the number of ticks in time increment resolution between 2 source frames (equivalent to source frame rate). */
+    Int                 tickPerSrc;
+
+    /** @brief Specifies encoded heights in pixels, height[n] represents the n-th layer's height. */
+    Int                 encHeight[2];
+
+    /** @brief Specifies encoded widths in pixels, width[n] represents the n-th layer's width.*/
+    Int                 encWidth[2];
+
+    /** @brief Specifies target frame rates in frames per second, frameRate[n] represents the n-th layer's target frame rate.*/
+    float               encFrameRate[2];
+
+    /** @brief Specifies target bit rates in bits per second unit, bitRate[n] represents the n-th layer's target bit rate. */
+    Int                 bitRate[2];
+
+    /** @brief Specifies default quantization parameters for I-Vop. Iquant[n] represents the n-th layer default quantization parameter. The default is Iquant[0]=12.*/
+    Int                 iQuant[2];
+
+    /** @brief Specifies default quantization parameters for P-Vop. Pquant[n] represents the n-th layer default quantization parameter. The default is Pquant[0]=10.*/
+    Int                 pQuant[2];
+
+    /** @brief  specifies quantization mode (H263 mode or MPEG mode) of the encoded base and enhance layer (if any).
+    *           In Simple and Simple Scalable profile, we use only H263 mode.*/
+    Int                 quantType[2];
+
+    /** @brief Sets rate control algorithm, one of (CONSTANT_Q, CBR_1, or VBR_1).
+    *           CONSTANT_Q uses the default quantization values to encode the sequence.
+    *           CBR_1 (constant bit rate) controls the output at a desired bit rate
+    *           VBR_1 (variable bit rate) gives better picture quality at the expense of bit rate fluctuation
+    *           Note:   type=CONSTANT_Q produces sequences with arbitrary bit rate.
+    *                   type=CBR_1 produces sequences suitable for streaming.
+    *                   type=VBR_1 produces sequences suitable for download. */
+    MP4RateControlType  rcType;
+
+    /** @brief  Sets the VBV buffer size (in the unit of second delay) used to prevent buffer overflow and underflow
+    *           on the decoder side. This function is redundant to PVSetVBVSize. Either one of them is used at a time. */
+    float               vbvDelay;
+
+    /** @brief  Specifies whether frame skipping is permitted or not. When rate control type is set to CONSTANT_Q
+    *           frame skipping is automatically banned.  In CBR_1 and VBR_1 rate control, frame skipping is allowed by default.
+    *           However, users can force no frame skipping with this flag, but buffer constraint may be violated.*/
+    ParamEncMode        noFrameSkipped;
+
+    /** @brief Sets the maximum number of P-frames between two I-frames. I-frame mode is periodically forced
+    *           if no I-frame is encoded after the specified period to add error resiliency and help resynchronize in case of errors.
+    *           If scene change detection can add additional I-frame if new scenes are detected.
+    *           intraPeriod is the I frame interval in terms of second.
+    *           intraPeriod =0 indicates I-frame encoding only;
+    *           intraPeriod = -1  indicates I-frame followed by all P-frames; (default)
+    *           intraPeriod = N, indicates the number of P-frames between 2 I-frames.*/
+    Int                 intraPeriod;
+
+
+    /** @brief  Specifies the number Intra MBs to be refreshed in a P-frame. */
+    Int                 numIntraMB;
+
+    /**
+    *   @brief  Specifies whether the scene change detection (SCD) is enabled or disabled.
+    *           With SCD enable, when a new scene is detected, I-Vop mode will be used for the first frame of
+    *           the new scene resulting in better picture quality. An insertion of an I-VOP resets the intraPeriod
+    *           specified by the IntraPeriodAPI().*/
+    ParamEncMode        sceneDetect;
+
+    /** @brief  Specifies the search range of motion estimation search.  Larger value implies
+    *           larger search range, better motion vector match, but more complexity.
+    *           If searchRange=n, the motion vector search is in the range of [-n,n-1] pixels.
+    *           If half-pel  mode is on, the range is [-n, (n-1)+1/2] pixels. The default value is 16.*/
+    Int                 searchRange;
+
+    /** @brief  Turns on/off 8x8 block motion estimation and compensation.
+    *           If on, four motion vectors may be used for motion estimation and compensation of a macroblock,
+    *           otherwise one motion vector per macroblock is used. When the 8x8 MV is off, the total encoding complexity
+    *           is less but the image quality is also worse. Therefore, it can be used in complexity limited environment.*/
+    ParamEncMode        mv8x8Enable;
+
+
+    /** @brief Set the threshold for using intra DC VLC.
+    *           Value must range from 0-7.*/
+    Int                 intraDCVlcTh;
+
+    /** @brief This flag turns on the use of AC prediction */
+    Bool                useACPred;
+
+} VideoEncOptions;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+    /* API's */
+    /* Always start with this one !!*/
+    /**
+    *   @brief  Gets default encoding options. This way users only have to set relevant encoding options and leave the one
+    *           they are unsure of.
+    *   @encOption  Pointer to VideoEncOption structure.
+    *   @encUseCase This value determines the set of default encoding options, for example, different encoding options
+    *            are assigned to streaming use-case as compared to download use-case. It can be project dependent too.
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool PVGetDefaultEncOption(VideoEncOptions *encOption, Int encUseCase);
+
+    /**
+    *   @brief  Verifies the consistency of encoding parameters, allocates memory needed and set necessary internal variables.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVInitVideoEncoder(VideoEncControls *encCtrl, VideoEncOptions *encOption);
+
+    /* acquiring encoder info APIs */
+    /**
+    *   @brief  This function returns VOL header. It has to be called before the frame is encoded.  If so,
+    *           then the VOL Header is passed back to the application. Then all frames that are encoded do not contain the VOL Header.
+    *           If you do not call the API then the VOL Header is passed within the first frame that is encoded.
+    *           The behavior is unknown if it is called after the first frame is encoded. It is mainly used for MP4 file format authoring.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs.
+    *   @param  volHeader is the Buffer for VOL header.
+    *   @param  size is the size of VOL header in bytes.
+    *   @param  layer is the layer of the requested VOL header.
+    *   @return true for correct operation; false if error happens.
+    */
+    OSCL_IMPORT_REF Bool    PVGetVolHeader(VideoEncControls *encCtrl, UChar *volHeader, Int *size, Int layer);
+
+    /**
+    *   @brief  This function returns the profile and level in H.263 coding when the encoding parameters are set
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs.
+    *   @param  profileID is the pointer of the profile ID. Right now we only support profile 0
+    *   @param  levelID is the pointer of the level ID that could be 10-70.
+    *   @return true for correct operation; false if error happens.
+    */
+    OSCL_IMPORT_REF Bool    PVGetH263ProfileLevelID(VideoEncControls *encCtrl, Int *profileID, Int *levelID);
+
+    /**
+    *   @brief  This function returns the profile and level of MPEG4 when the encoding parameters are set
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs.
+    *   @param  profile_level is the pointer of the profile enumeration
+    *   @param  nLayer is the index of the layer of interest
+    *   @return true for correct operation; false if error happens.
+    */
+    OSCL_IMPORT_REF Bool    PVGetMPEG4ProfileLevelID(VideoEncControls *encCtrl, Int *profile_level, Int nLayer);
+
+    /**
+    *   @brief  This function returns maximum frame size in bytes
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  maxVideoFrameSize is the pointer of the maximum frame size
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVGetMaxVideoFrameSize(VideoEncControls *encCtrl, Int *maxVideoFrameSize);
+
+#ifndef LIMITED_API
+    /**
+    *   @brief  This function returns the total amount of memory (in bytes) allocated by the encoder library.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Int     PVGetEncMemoryUsage(VideoEncControls *encCtrl);
+
+    /**
+    *   @brief  This function is used by PVAuthor to get the size of the VBV buffer.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  VBVSize is the pointer of The size of the VBV buffer in bytes.
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVGetVBVSize(VideoEncControls *encCtrl, Int *VBVSize);
+#endif
+
+    /**
+    *   @brief  This function encodes a frame in YUV 4:2:0 format from the *video_in input frame and put the result in YUV
+    *           for reconstructed frame and bstream for MPEG4 bitstream. The application is required to allocate memory for
+    *           bitstream buffer.The size of the input bitstream memory and the returned output buffer are specified in the
+    *           size field. The encoded layer is specified by the nLayer field. If the current frame is not encoded, size=0 and nLayer=-1.
+    *           Note: If the allocated buffer size is too small to fit a bitstream of a frame, then those extra bits will be left out
+    *                 which can cause syntactic error at the decoder side.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  vid_in is the pointer to VideoEncFrameIO structure containing the YUV input data
+    *   @param  vid_out is the pointer to VideoEncFrameIO structure containing the reconstructed YUV output data after encoding
+    *   @param  nextModTime is the timestamp encoder expects from the next input
+    *   @param  bstream is the pointer to MPEG4 bitstream buffer
+    *   @param  size is the size of bitstream buffer allocated (input) and size of the encoded bitstream (output).
+    *   @param  nLayer is the layer of the encoded frame either 0 for base or 1 for enhancement layer. The value -1 indicates skipped frame due to buffer overflow.
+    *   @return true newfor correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVEncodeVideoFrame(VideoEncControls *encCtrl, VideoEncFrameIO *vid_in, VideoEncFrameIO *vid_out,
+            ULong *nextModTime, UChar *bstream, Int *size, Int *nLayer);
+
+
+    /**
+    *   @brief  This function is used to query overrun buffer. It is used when PVEncodeVideoFrame.returns size that is
+    *           larger than the input size.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @return Pointer to the overrun buffer. NULL if overrun buffer is not used.
+    */
+    OSCL_IMPORT_REF UChar* PVGetOverrunBuffer(VideoEncControls *encCtrl);
+
+#ifndef NO_SLICE_ENCODE   /* This set of APIs are not working. This functionality has been partially 
+    replaced by the introduction of overrun buffer. */
+
+    /* slice-based coding */
+    /**
+    *   @brief  This function sets the input YUV frame and timestamp to be encoded by the slice-based encoding function PVEncodeSlice().
+    *           It also return the memory address the reconstructed frame will be copied to (in advance) and the coded layer number.
+    *           The encoder library processes the timestamp and determine if this frame is to be encoded or not. If the current frame
+    *           is not encoded, nLayer=-1. For frame-based motion estimation, the motion estimation of the entire frame is also performed
+    *           in this function. For MB-based motion estimation, the motion vector is searched while coding each MB in PVEncodeSlice().
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  vid_in is the pointer to VideoEncFrameIO structure containing the YUV input data
+    *   @param  nextModTime is the timestamp encoder expects from the next input if this input is rejected and nLayer is set to -1.
+    *   @param  nLayer is the layer of the encoded frame either 0 for base or 1 for enhancement layer. The value -1 indicates skipped frame due to buffer overflow.
+    *   @return true newfor correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVEncodeFrameSet(VideoEncControls *encCtrl, VideoEncFrameIO *vid_in, ULong *nextModTime, Int *nLayer);
+    /**
+    *   @brief  This function encodes a GOB (short header mode) or a packet (data partitioning mode or combined mode with resync marker)
+    *           and output the reconstructed frame and MPEG4 bitstream. The application is required to allocate memory for the bitstream buffer.
+    *           The size of the input bitstream memory and the returned output buffer are specified in the size field.  If the buffer size is
+    *           smaller than the requested packet size, user has to call PVEncodeSlice again to get the rest of that pending packet before moving
+    *           on to the next packet. For the combined mode without resync marker, the function returns when the buffer is full.
+    *           The end-of-frame flag  indicates the completion of the frame encoding.  Next frame must be sent in with PVEncodeFrameSet().
+    *           At the end-of-frame, the next video input address and the next video modulo timestamp will be set.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  bstream is the pointer to MPEG4 bitstream buffer.
+    *   @param  size is the size of bitstream buffer allocated (input) and size of the encoded bitstream (output).
+    *   @param  endofFrame is a flag indicating the end-of-frame, '1'. Otherwise, '0'.  When PVSetNoCurrentFrameSkip is OFF,
+    *           end-of-frame '-1' indicates current frame bitstream must be disregarded.
+    *   @param  vid_out is the pointer to VideoEncFrameIO structure containing the reconstructed YUV output data after encoding
+    *   @param  nextModTime is the timestamp encoder expects from the next input
+    *   @return true newfor correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVEncodeSlice(VideoEncControls *encCtrl, UChar *bstream, Int *size,
+                                          Int *endofFrame, VideoEncFrameIO *vid_out, ULong *nextModTime);
+#endif
+
+    /**
+    *   @brief  This function returns MP4 file format hint track information.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  info is the structure for MP4 hint track information
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVGetHintTrack(VideoEncControls *encCtrl, MP4HintTrack *info);
+
+#ifndef LIMITED_API
+    /**
+    *   @brief  updates target frame rates of the encoded base and enhance layer (if any) while encoding operation is ongoing.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  frameRate is the pointers to array of target frame rates in frames per second,
+    *           frameRate[n] represents the n-th layer's target frame rate.
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVUpdateEncFrameRate(VideoEncControls *encCtrl, float *frameRate); /* for 2-way */
+
+
+    /**
+    *   @brief  updates target bit rates of the encoded base and enhance layer (if any) while encoding operation is ongoing.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  bitRate is the pointers to array of target bit rates in bits per second unit,
+    *           bitRate[n] represents the n-th layer's target bit rate.
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVUpdateBitRate(VideoEncControls *encCtrl, Int *bitRate);           /* for 2-way */
+
+
+    /**
+    *   @brief  updates the INTRA frame refresh interval while encoding operation is ongoing.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  aIFramePeriod is a new value of INTRA frame interval in the unit of number of coded frames.
+    *   @return true for correct operation; false if error happens
+    */
+
+    OSCL_IMPORT_REF Bool    PVUpdateIFrameInterval(VideoEncControls *encCtrl, Int aIFramePeriod);/* for 2-way */
+
+    /**
+    *   @brief  specifies the number Intra MBs to be refreshed
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @param  numMB is the number of Intra MBs to be refreshed
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVUpdateNumIntraMBRefresh(VideoEncControls *encCtrl, Int numMB);  /* for 2-way */
+
+    /**
+    *   @brief  This function is called whenever users want the next base frame to be encoded as an I-Vop.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVIFrameRequest(VideoEncControls *encCtrl);                         /* for 2-way */
+
+#endif // LIMITED_API
+
+    /* finishing encoder */
+    /**
+    *   @brief  This function frees up all the memory allocated by the encoder library.
+    *   @param  encCtrl is video encoder control structure that is always passed as input in all APIs
+    *   @return true for correct operation; false if error happens
+    */
+    OSCL_IMPORT_REF Bool    PVCleanUpVideoEncoder(VideoEncControls *encCtrl);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MP4ENC_API_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp
new file mode 100644
index 0000000..5c4c4ab
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp
@@ -0,0 +1,859 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/* Date: 8/02/04                                                                */
+/* Description:                                                                 */
+/*  Change the bitstream parsing algorithm. Use temporary word of 2 or 4 bytes  */
+/*  before writing it to the bitstream buffer.                                  */
+/*  Note byteCount doesn't have to be multiple of 2 or 4                        */
+/*********************************************************************************/
+
+#include "bitstream_io.h"
+#include "m4venc_oscl.h"
+#include <stdlib.h>
+
+static const UChar Mask[ ] =
+{
+    0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
+};
+
+#define WORD_SIZE   4   /* for 32-bit machine */
+
+/*Note:
+    1. There is a problem when output the last bits(which can not form a byte yet
+    so when you output, you need to stuff to make sure it is a byte
+    2.  I now hard coded byte to be 8 bits*/
+
+
+/* ======================================================================== */
+/*  Function : BitStreamCreateEnc(Int bufferSize )                          */
+/*  Date     : 08/29/2000                                                   */
+/*  Purpose  : Create a bitstream to hold one encoded video packet or frame */
+/*  In/out   :                                                              */
+/*      bufferSize  :   size of the bitstream buffer in bytes               */
+/*  Return   : Pointer to the BitstreamEncVideo                             */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+BitstreamEncVideo *BitStreamCreateEnc(Int bufferSize)
+{
+    BitstreamEncVideo *stream;
+    stream = (BitstreamEncVideo *) M4VENC_MALLOC(sizeof(BitstreamEncVideo));
+    if (stream == NULL)
+    {
+        return NULL;
+    }
+    stream->bufferSize = bufferSize;
+    stream->bitstreamBuffer = (UChar *) M4VENC_MALLOC(stream->bufferSize * sizeof(UChar));
+    if (stream->bitstreamBuffer == NULL)
+    {
+        M4VENC_FREE(stream);
+        stream = NULL;
+        return NULL;
+    }
+    M4VENC_MEMSET(stream->bitstreamBuffer, 0, stream->bufferSize*sizeof(UChar));
+    stream->word = 0;
+#if WORD_SIZE==4
+    stream->bitLeft = 32;
+#else
+    stream->bitLeft = 16;
+#endif
+    stream->byteCount = 0;
+
+    stream->overrunBuffer = NULL;
+    stream->oBSize = 0;
+
+    return stream;
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamCloseEnc( )                                         */
+/*  Date     : 08/29/2000                                                   */
+/*  Purpose  : close a bitstream                                            */
+/*  In/out   :
+        stream  :   the bitstream to be closed                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+Void  BitstreamCloseEnc(BitstreamEncVideo *stream)
+{
+    if (stream)
+    {
+        if (stream->bitstreamBuffer)
+        {
+            M4VENC_FREE(stream->bitstreamBuffer);
+        }
+
+        M4VENC_FREE(stream);
+    }
+}
+
+
+/* ======================================================================== */
+/*  Function : BitstreamPutBits(BitstreamEncVideo *stream, Int Length,
+                         Int Value)                                         */
+/*  Date     : 08/29/2000                                                   */
+/*  Purpose  : put Length (1-16) number of bits to the stream               */
+/*            for 32-bit machine this function can do upto 32 bit input     */
+/*  In/out   :                                                              */
+/*      stream      the bitstream where the bits are put in                 */
+/*      Length      bits length (should belong to 1 to 16)                  */
+/*      Value       those bits value                                        */
+/*  Return   :  PV_STATUS                                                   */
+/*  Modified :                                                              */
+/* ======================================================================== */
+PV_STATUS BitstreamPutBits(BitstreamEncVideo *stream, Int Length, UInt Value)
+{
+    PV_STATUS status;
+
+    if (stream->bitLeft > Length)
+    {
+        stream->word <<= Length;
+        stream->word |= Value;  /* assuming Value is not larger than Length */
+        stream->bitLeft -= Length;
+        return PV_SUCCESS;
+    }
+    else
+    {
+
+        stream->word <<= stream->bitLeft;
+        Length -= stream->bitLeft;
+        stream->word |= ((UInt)Value >> Length);
+
+        status = BitstreamSaveWord(stream);
+        if (status != PV_SUCCESS)
+        {
+            return status;
+        }
+
+        /* we got new Length and Value */
+        /* note that Value is not "clean" because of msb are not masked out */
+        stream->word = Value;
+        stream->bitLeft -= Length;
+        /* assuming that Length is no more than 16 bits */
+        /* stream->bitLeft should be greater than zero at this point */
+        //if(stream->bitLeft<=0)
+        //  exit(-1);
+        return PV_SUCCESS;
+    }
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, UInt32 Value)    */
+/*  Date     : 08/29/2000                                                   */
+/*  Purpose  : Use this function to put Length (17-32) number of bits to    */
+/*              for 16-bit machine  the stream.                             */
+/*  In/out   :                                                              */
+/*      stream      the bitstream where the bits are put in                 */
+/*      Length      bits length (should belong to 17 to 32)                 */
+/*      Value       those bits value                                        */
+/*  Return   :  PV_STATUS                                                   */
+/*  Modified :                                                              */
+/* ======================================================================== */
+PV_STATUS BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, ULong Value)
+{
+    PV_STATUS status;
+    UInt topValue;
+    Int topLength;
+
+    topValue = (Value >> 16);
+    topLength = Length - 16;
+
+    if (topLength > 0)
+    {
+        status = BitstreamPutBits(stream, topLength, topValue);
+
+        if (status != PV_SUCCESS)
+        {
+            return status;
+        }
+
+        status = BitstreamPutBits(stream, 16, (UInt)(Value & 0xFFFF));
+
+        return status;
+    }
+    else
+    {
+        status = BitstreamPutBits(stream, Length, (UInt)Value);
+        return status;
+    }
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamSaveWord                                            */
+/*  Date     : 08/03/2004                                                   */
+/*  Purpose  : save written word into the bitstream buffer.                 */
+/*  In/out   :                                                              */
+/*      stream      the bitstream where the bits are put in                 */
+/*  Return   :  PV_STATUS                                                   */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+PV_STATUS BitstreamSaveWord(BitstreamEncVideo *stream)
+{
+    UChar *ptr;
+    UInt word;
+
+    /* assume that stream->bitLeft is always zero when this function is called */
+    if (stream->byteCount + WORD_SIZE > stream->bufferSize)
+    {
+        if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, WORD_SIZE))
+        {
+            stream->byteCount += WORD_SIZE;
+            return PV_FAIL;
+        }
+    }
+
+    ptr = stream->bitstreamBuffer + stream->byteCount;
+    word = stream->word;
+    stream->word = 0; /* important to reset to zero */
+
+    /* NOTE: byteCount does not have to be multiple of 2 or 4 */
+#if (WORD_SIZE == 4)
+    *ptr++ = word >> 24;
+    *ptr++ = 0xFF & (word >> 16);
+#endif
+
+    *ptr++ = 0xFF & (word >> 8);
+    *ptr = 0xFF & word;
+
+#if (WORD_SIZE == 4)
+    stream->byteCount += 4;
+    stream->bitLeft = 32;
+#else
+    stream->byteCount += 2;
+    stream->bitLeft = 16;
+#endif
+
+    return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/*  Function : BitstreamSavePartial                                         */
+/*  Date     : 08/03/2004                                                   */
+/*  Purpose  : save unfinished written word into the bitstream buffer.      */
+/*  In/out   :                                                              */
+/*      stream      the bitstream where the bits are put in                 */
+/*  Return   :  PV_STATUS                                                   */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+PV_STATUS BitstreamSavePartial(BitstreamEncVideo *stream, Int *fraction)
+{
+    UChar *ptr;
+    UInt word, shift;
+    Int numbyte, bitleft, bitused;
+
+    bitleft = stream->bitLeft;
+    bitused = (WORD_SIZE << 3) - bitleft; /* number of bits used */
+    numbyte = bitused >> 3; /* number of byte fully used */
+
+    if (stream->byteCount + numbyte > stream->bufferSize)
+    {
+        if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, numbyte))
+        {
+            stream->byteCount += numbyte;
+            return PV_FAIL;
+        }
+    }
+
+    ptr = stream->bitstreamBuffer + stream->byteCount;
+    word = stream->word;
+    word <<= bitleft;   /* word is not all consumed */
+    bitleft = bitused - (numbyte << 3); /* number of bits used (fraction) */
+    stream->byteCount += numbyte;
+    if (bitleft)
+    {
+        *fraction = 1;
+    }
+    else
+    {
+        *fraction = 0;
+    }
+    bitleft = (WORD_SIZE << 3) - bitleft;
+    /* save new value */
+    stream->bitLeft = bitleft;
+
+    shift = ((WORD_SIZE - 1) << 3);
+    while (numbyte)
+    {
+        *ptr++ = (UChar)((word >> shift) & 0xFF);
+        word <<= 8;
+        numbyte--;
+    }
+
+    if (*fraction)
+    {// this could lead to buffer overrun when ptr is already out of bound.
+        //  *ptr = (UChar)((word>>shift)&0xFF); /* need to do it for the last fractional byte */
+    }
+
+    /* save new values */
+    stream->word = word >> bitleft;
+
+    /* note we don't update byteCount, bitLeft and word */
+    /* so that encoder can continue PutBits if they don't */
+
+    return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/*  Function : BitstreamShortHeaderByteAlignStuffing(                       */
+/*                                      BitstreamEncVideo *stream)          */
+/*  Date     : 08/29/2000                                                   */
+/*  Purpose  : bit stuffing for next start code in short video header       */
+/*  In/out   :                                                              */
+/*  Return   :  number of bits to be stuffed                                */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+Int BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo *stream)
+{
+    UInt restBits;
+    Int fraction;
+
+    restBits = (stream->bitLeft & 0x7); /* modulo 8 */
+
+    if (restBits)  /*short_video_header[0] is 1 in h263 baseline*/
+    {
+        /* H.263 style stuffing */
+        BitstreamPutBits(stream, restBits, 0);
+    }
+
+    if (stream->bitLeft != (WORD_SIZE << 3))
+    {
+        BitstreamSavePartial(stream, &fraction);
+    }
+
+    return restBits;
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)   */
+/*  Date     : 08/29/2000                                                   */
+/*  Purpose  : bit stuffing for next start code in MPEG-4                  */
+/*  In/out   :                                                              */
+/*  Return   :  number of bits to be stuffed                                */
+/*  Modified :                                                              */
+/* ======================================================================== */
+Int BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)
+{
+
+    UInt restBits;
+    Int fraction;
+    /* Question: in MPEG-4 , short_video_header[0]==0 => even already byte aligned, will still stuff 8 bits
+       need to check with  */
+    /*if (!(getPointerENC(index1, index2)%8) && short_video_header[0]) return 0;*/
+
+    /* need stuffing bits, */
+    BitstreamPutBits(stream, 1, 0);
+
+    restBits = (stream->bitLeft & 0x7); /* modulo 8 */
+
+    if (restBits)  /*short_video_header[0] is 1 in h263 baseline*/
+    {
+        /* need stuffing bits, */
+        BitstreamPutBits(stream, restBits, Mask[restBits]);
+    }
+
+    if (stream->bitLeft != (WORD_SIZE << 3))
+    {
+        BitstreamSavePartial(stream, &fraction);
+    }
+
+    return (restBits);
+}
+
+/*does bit stuffing for next resync marker*/
+/*  does bit stuffing for next resync marker
+ *                                            "0"
+ *                                           "01"
+ *                                          "011"
+ *                                         "0111"
+ *                                        "01111"
+ *                                       "011111"
+ *                                      "0111111"
+ *                                     "01111111"   (8-bit codeword)
+ */
+
+/*Int BitstreamNextResyncMarkerEnc(BitstreamEncVideo *stream)
+{
+  Int count;
+  BitstreamPut1Bits(stream,0);
+  count=8-stream->totalBits & 8;
+  BitstreamPutBits(stream,count,Mask[count]);
+  return count;
+}*/
+
+/* ======================================================================== */
+/*  Function : BitstreamAppendEnc( BitstreamEncVideo *bitstream1,           */
+/*                                      BitstreamEncVideo *bitstream2   )   */
+/*  Date     : 08/29/2000                                                   */
+/*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
+/*                              output bitstream(bitstream1)                */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+
+PV_STATUS BitstreamAppendEnc(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
+{
+    PV_STATUS status;
+    UChar *ptrBS2, *ptrBS1;
+    UChar byteBS2, byteBS1;
+    Int  numbyte2;
+    Int bitused, bitleft, offset, fraction;
+
+    status = BitstreamSavePartial(bitstream1, &fraction);
+    if (status != PV_SUCCESS)
+    {
+        return status;
+    }
+
+    offset = fraction;
+    status = BitstreamSavePartial(bitstream2, &fraction);
+    if (status != PV_SUCCESS)
+    {
+        return status;
+    }
+
+    if (!offset) /* bitstream1 is byte-aligned */
+    {
+        return BitstreamAppendPacket(bitstream1, bitstream2);
+    }
+
+    offset += fraction;
+
+    /* since bitstream1 doesn't have to be byte-aligned, we have to process byte by byte */
+    /* we read one byte from bitstream2 and use BitstreamPutBits to do the job */
+    if (bitstream1->byteCount + bitstream2->byteCount + offset > bitstream1->bufferSize)
+    {
+        if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount + offset))
+        {
+            bitstream1->byteCount += (bitstream2->byteCount + offset);
+            return PV_FAIL;
+        }
+    }
+
+    ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
+    ptrBS2 = bitstream2->bitstreamBuffer;
+
+    bitused = (WORD_SIZE << 3) - bitstream1->bitLeft; /* this must be between 1-7 */
+    bitleft = 8 - bitused;
+
+    numbyte2 = bitstream2->byteCount;   /* number of byte to copy from bs2 */
+    bitstream1->byteCount += numbyte2;  /* new byteCount */
+
+    byteBS1 = ((UChar) bitstream1->word) << bitleft;    /* fraction byte from bs1 */
+
+    while (numbyte2)
+    {
+        byteBS2 = *ptrBS2++;
+        byteBS1 |= (byteBS2 >> bitused);
+        *ptrBS1++ = byteBS1;
+        byteBS1 = byteBS2 << bitleft;
+        numbyte2--;
+    }
+
+    bitstream1->word = byteBS1 >> bitleft;  /* bitstream->bitLeft remains the same */
+
+    /* now save bs2->word in bs1 */
+    status = BitstreamPutBits(bitstream1, (WORD_SIZE << 3) - bitstream2->bitLeft, bitstream2->word);
+
+    return status;
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamAppendPacket( BitstreamEncVideo *bitstream1,        */
+/*                                      BitstreamEncVideo *bitstream2   )   */
+/*  Date     : 05/31/2001                                                   */
+/*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
+/*              output bitstream(bitstream1) knowing that bitstream1 is byte-aligned*/
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+PV_STATUS BitstreamAppendPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
+{
+    UChar *ptrBS2, *ptrBS1;
+    Int  numbyte2;
+
+    if (bitstream1->byteCount + bitstream2->byteCount  > bitstream1->bufferSize)
+    {
+        if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount))
+        {
+            bitstream1->byteCount += bitstream2->byteCount; /* legacy, to keep track of total bytes */
+            return PV_FAIL;
+        }
+    }
+
+    ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
+    ptrBS2 = bitstream2->bitstreamBuffer;
+
+    numbyte2 = bitstream2->byteCount;
+    bitstream1->byteCount += numbyte2; /* new byteCount */
+
+    /*copy all the bytes in bitstream2*/
+    M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
+
+    bitstream1->word = bitstream2->word;  /* bitstream1->bitLeft is the same */
+    bitstream1->bitLeft = bitstream2->bitLeft;
+
+    return PV_SUCCESS;
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamAppendPacketNoOffset( BitstreamEncVideo *bitstream1,*/
+/*                                      BitstreamEncVideo *bitstream2   )   */
+/*  Date     : 04/23/2002                                                   */
+/*  Purpose  : Append the intermediate bitstream (bitstream2) to the end of */
+/*              output bitstream(bitstream1) , for slice-based coding only */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+PV_STATUS BitstreamAppendPacketNoOffset(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
+{
+    PV_STATUS status = PV_SUCCESS;
+    UChar *ptrBS2, *ptrBS1;
+    Int  numbyte2;
+    Int  byteleft;
+
+    numbyte2 = bitstream2->byteCount;
+
+    if (bitstream1->byteCount + bitstream2->byteCount > bitstream1->bufferSize)
+    {
+        numbyte2 =  bitstream1->bufferSize - bitstream1->byteCount;
+        status =  PV_END_OF_BUF;    /* signal end of buffer */
+    }
+
+    ptrBS1 = bitstream1->bitstreamBuffer; /* move ptr bs1*/
+    ptrBS2 = bitstream2->bitstreamBuffer;
+
+    bitstream1->byteCount += numbyte2; /* should be equal to bufferSize */
+
+    /*copy all the bytes in bitstream2*/
+    M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
+    bitstream1->word = 0;
+    bitstream1->bitLeft = (WORD_SIZE << 3);
+
+    if (status == PV_END_OF_BUF) /* re-position bitstream2 */
+    {
+        byteleft = bitstream2->byteCount - numbyte2;
+
+        M4VENC_MEMCPY(ptrBS2, ptrBS2 + numbyte2, sizeof(UChar)*byteleft);
+
+        bitstream2->byteCount = byteleft;
+        /* bitstream2->word and bitstream->bitLeft are unchanged.
+           they should be 0 and (WORD_SIZE<<3) */
+    }
+
+    return status;
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/*  Function : BitstreamRepos( BitstreamEncVideo *bitstream,                */
+/*                                      Int byteCount, Int bitCount)        */
+/*  Date     : 04/28/2002                                                   */
+/*  Purpose  : Reposition the size of the buffer content (curtail)          */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+PV_STATUS   BitstreamRepos(BitstreamEncVideo *bitstream, Int byteCount, Int bitCount)
+{
+    UChar *ptr, byte;
+    UInt word;
+    Int fraction;
+
+    BitstreamSavePartial(bitstream, &fraction);
+
+    bitstream->byteCount = byteCount;
+    ptr = bitstream->bitstreamBuffer + byteCount; /* get fraction of the byte */
+    if (bitCount)
+    {
+        bitstream->bitLeft = (WORD_SIZE << 3) - bitCount; /* bitCount should be 0-31 */
+        word = *ptr++;
+        byte = *ptr++;
+        word = byte | (word << 8);
+#if (WORD_SIZE == 4)
+        byte = *ptr++;
+        word = byte | (word << 8);
+        byte = *ptr++;
+        word = byte | (word << 8);
+#endif
+        bitstream->word = word >> (bitstream->bitLeft);
+    }
+    else
+    {
+        bitstream->word = 0;
+        bitstream->bitLeft = (WORD_SIZE << 3);
+    }
+
+    return PV_SUCCESS;
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamFlushBits(BitstreamEncVideo *bitstream1,            */
+/*                              Int num_bit_left)                           */
+/*  Date     : 04/24/2002                                                   */
+/*  Purpose  : Flush buffer except the last num_bit_left bits.              */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+
+PV_STATUS BitstreamFlushBits(BitstreamEncVideo *bitstream1, Int num_bit_left)
+{
+    Int i;
+    UChar *ptrDst, *ptrSrc;
+    Int leftover, bitused;
+    Int new_byte = (num_bit_left >> 3);
+    Int new_bit = num_bit_left - (new_byte << 3); /* between 0-7 */
+
+    ptrSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
+    ptrDst = bitstream1->bitstreamBuffer;
+
+    bitused = (WORD_SIZE << 3) - bitstream1->bitLeft;
+
+    leftover = 8 - bitused; /* bitused should be between 0-7 */
+
+    bitstream1->byteCount = new_byte;
+    bitstream1->bitLeft = (WORD_SIZE << 3) - new_bit;
+
+    if (!bitused) /* byte aligned */
+    {
+        M4VENC_MEMCPY(ptrDst, ptrSrc, new_byte + 1);
+    }
+    else
+    {
+        /*copy all the bytes in bitstream2*/
+        for (i = 0; i < new_byte; i++)
+        {
+            *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
+            ptrSrc++;
+        }
+        /* copy for the last byte of ptrSrc, copy extra bits doesn't hurt */
+        if (new_bit)
+        {
+            *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
+            ptrSrc++;
+        }
+    }
+    if (new_bit)
+    {
+        ptrSrc = bitstream1->bitstreamBuffer + new_byte;
+        bitstream1->word = (*ptrSrc) >> (8 - new_bit);
+    }
+
+    return PV_SUCCESS;
+}
+
+/* ======================================================================== */
+/*  Function : BitstreamPrependPacket( BitstreamEncVideo *bitstream1,       */
+/*                                      BitstreamEncVideo *bitstream2   )   */
+/*  Date     : 04/26/2002                                                   */
+/*  Purpose  : Prepend the intermediate bitstream (bitstream2) to the beginning of */
+/*              output bitstream(bitstream1) */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+PV_STATUS BitstreamPrependPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
+{
+    UChar *pSrc, *pDst, byte;
+    Int     movebyte, bitused, leftover, i, fraction;
+
+    BitstreamSavePartial(bitstream2, &fraction); /* make sure only fraction of byte left */
+    BitstreamSavePartial(bitstream1, &fraction);
+
+    if (bitstream1->byteCount + bitstream2->byteCount >= bitstream1->bufferSize)
+    {
+        bitstream1->byteCount += bitstream2->byteCount;
+        return PV_END_OF_BUF;
+    }
+
+    movebyte = bitstream1->byteCount;
+    if (movebyte < bitstream2->byteCount)
+        movebyte = bitstream2->byteCount;
+    movebyte++;
+
+    /* shift bitstream1 to the right by movebyte */
+    pSrc = bitstream1->bitstreamBuffer;
+    pDst = pSrc + movebyte;
+
+    M4VENC_MEMCPY(pDst, pSrc, bitstream1->byteCount + 1);
+
+    /* copy bitstream2 to the beginning of bitstream1 */
+    M4VENC_MEMCPY(pSrc, bitstream2->bitstreamBuffer, bitstream2->byteCount + 1);
+
+    /* now shift back previous bitstream1 buffer to the end */
+    pSrc = pDst;
+    pDst = bitstream1->bitstreamBuffer + bitstream2->byteCount;
+
+    bitused = (WORD_SIZE << 3) - bitstream2->bitLeft;
+    leftover = 8 - bitused;     /* bitused should be 0-7 */
+
+    byte = (bitstream2->word) << leftover;
+
+    *pDst++ = byte | (pSrc[0] >> bitused);
+
+    for (i = 0; i < bitstream1->byteCount + 1; i++)
+    {
+        *pDst++ = ((pSrc[0] << leftover) | (pSrc[1] >> bitused));
+        pSrc++;
+    }
+
+    bitstream1->byteCount += bitstream2->byteCount;
+    //bitstream1->bitCount += bitstream2->bitCount;
+    bitused = (WORD_SIZE << 4) - (bitstream1->bitLeft + bitstream2->bitLeft);
+
+    if (bitused >= 8)
+    {
+        bitused -= 8;
+        bitstream1->byteCount++;
+    }
+
+    bitstream1->bitLeft = (WORD_SIZE << 3) - bitused;
+
+    bitstream2->byteCount = bitstream2->word = 0;
+    bitstream2->bitLeft = (WORD_SIZE << 3);
+
+    pSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
+    leftover = 8 - bitused;
+    //*pSrc = (pSrc[0]>>leftover)<<leftover; /* make sure the rest of bits are zeros */
+
+    bitstream1->word = (UInt)((pSrc[0]) >> leftover);
+
+    return PV_SUCCESS;
+}
+#endif  /* NO_SLICE_ENCODE */
+
+
+/* ======================================================================== */
+/*  Function : BitstreamGetPos( BitstreamEncVideo *stream                   */
+/*  Date     : 08/05/2004                                                   */
+/*  Purpose  : Get the bit position.                                        */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+Int BitstreamGetPos(BitstreamEncVideo *stream)
+{
+
+    return stream->byteCount*8 + (WORD_SIZE << 3) - stream->bitLeft;
+}
+
+void BitstreamEncReset(BitstreamEncVideo *stream)
+{
+    stream->bitLeft = (WORD_SIZE << 3);
+    stream->word = 0;
+    stream->byteCount = 0;
+    return ;
+}
+
+/* This function set the overrun buffer, and VideoEncData context for callback to reallocate
+overrun buffer.  */
+Void  BitstreamSetOverrunBuffer(BitstreamEncVideo* stream, UChar* overrunBuffer, Int oBSize, VideoEncData *video)
+{
+    stream->overrunBuffer = overrunBuffer;
+    stream->oBSize = oBSize;
+    stream->video = video;
+
+    return ;
+}
+
+
+/* determine whether overrun buffer can be used or not */
+PV_STATUS BitstreamUseOverrunBuffer(BitstreamEncVideo* stream, Int numExtraBytes)
+{
+    VideoEncData *video = stream->video;
+
+    if (stream->overrunBuffer != NULL) // overrunBuffer is set
+    {
+        if (stream->bitstreamBuffer != stream->overrunBuffer) // not already used
+        {
+            if (stream->byteCount + numExtraBytes >= stream->oBSize)
+            {
+                stream->oBSize = stream->byteCount + numExtraBytes + 100;
+                stream->oBSize &= (~0x3); // make it multiple of 4
+
+                // allocate new overrun Buffer
+                if (video->overrunBuffer)
+                {
+                    M4VENC_FREE(video->overrunBuffer);
+                }
+                video->oBSize = stream->oBSize;
+                video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
+                stream->overrunBuffer = video->overrunBuffer;
+                if (stream->overrunBuffer == NULL)
+                {
+                    return PV_FAIL;
+                }
+            }
+
+            // copy everything to overrun buffer and start using it.
+            memcpy(stream->overrunBuffer, stream->bitstreamBuffer, stream->byteCount);
+            stream->bitstreamBuffer = stream->overrunBuffer;
+            stream->bufferSize = stream->oBSize;
+        }
+        else // overrun buffer is already used
+        {
+            if (stream->byteCount + numExtraBytes >= stream->oBSize)
+            {
+                stream->oBSize = stream->byteCount + numExtraBytes + 100;
+            }
+
+            // allocate new overrun buffer
+            stream->oBSize &= (~0x3); // make it multiple of 4
+            video->oBSize = stream->oBSize;
+            video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
+            if (video->overrunBuffer == NULL)
+            {
+                return PV_FAIL;
+            }
+
+            // copy from the old buffer to new buffer
+            memcpy(video->overrunBuffer, stream->overrunBuffer, stream->byteCount);
+            // free old buffer
+            M4VENC_FREE(stream->overrunBuffer);
+            // assign pointer to new buffer
+            stream->overrunBuffer = video->overrunBuffer;
+            stream->bitstreamBuffer = stream->overrunBuffer;
+            stream->bufferSize = stream->oBSize;
+        }
+
+        return PV_SUCCESS;
+    }
+    else // overrunBuffer is not enable.
+    {
+        return PV_FAIL;
+    }
+
+}
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h b/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h
new file mode 100644
index 0000000..0bce257
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h
@@ -0,0 +1,57 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _BITSTREAM_IO_H_
+#define _BITSTREAM_IO_H_
+
+#define BitstreamPut1Bits(x,y)  BitstreamPutBits(x,1,y)
+#define BitstreamPutGT8Bits(x,y,z) BitstreamPutBits(x,y,z)
+
+#include "mp4lib_int.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    BitstreamEncVideo *BitStreamCreateEnc(Int bufferSize);
+    Void  BitstreamCloseEnc(BitstreamEncVideo *stream);
+    PV_STATUS BitstreamPutBits(BitstreamEncVideo *stream, Int Length, UInt Value);
+    PV_STATUS BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, ULong Value);
+    PV_STATUS BitstreamSaveWord(BitstreamEncVideo *stream);
+    PV_STATUS BitstreamSavePartial(BitstreamEncVideo *stream, Int *fraction);
+    Int BitstreamGetPos(BitstreamEncVideo *stream);
+    void BitstreamEncReset(BitstreamEncVideo *stream);
+
+    Int BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo *stream);
+    Int BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream);
+    PV_STATUS BitstreamAppendEnc(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2);
+    PV_STATUS BitstreamAppendPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2);
+    PV_STATUS BitstreamAppendPacketNoOffset(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2);
+    PV_STATUS BitstreamRepos(BitstreamEncVideo *bitstream, Int byteCount, Int bitCount);
+    PV_STATUS BitstreamFlushBits(BitstreamEncVideo *bitstream1, Int num_bit_left);
+    PV_STATUS BitstreamPrependPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2);
+
+
+    Void  BitstreamSetOverrunBuffer(BitstreamEncVideo *stream, UChar *overrunBuffer, Int oBSize, VideoEncData *video);
+    PV_STATUS BitstreamUseOverrunBuffer(BitstreamEncVideo* stream, Int numExtraBytes);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BITSTREAM_IO_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp
new file mode 100644
index 0000000..e725680
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp
@@ -0,0 +1,693 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "bitstream_io.h"
+#include "vlc_encode.h"
+#include "m4venc_oscl.h"
+
+PV_STATUS EncodeGOBHeader(VideoEncData *video, Int GOB_number, Int quant_scale, Int bs1stream);
+
+/* ======================================================================== */
+/*  Function : EncodeFrameCombinedMode()                                    */
+/*  Date     : 09/01/2000                                                   */
+/*  History  :                                                              */
+/*  Purpose  : Encode a frame of MPEG4 bitstream in Combined mode.          */
+/*  In/out   :                                                              */
+/*  Return   :  PV_SUCCESS if successful else PV_FAIL                       */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+PV_STATUS EncodeFrameCombinedMode(VideoEncData *video)
+{
+    PV_STATUS status = PV_SUCCESS;
+    Vol *currVol = video->vol[video->currLayer];
+    Vop *currVop = video->currVop;
+    VideoEncParams *encParams = video->encParams;
+    Int width = currVop->width; /* has to be Vop, for multiple of 16 */
+    Int lx = currVop->pitch; /* with padding */
+    Int offset = 0;
+    Int ind_x, ind_y;
+    Int start_packet_header = 0;
+    UChar *QPMB = video->QPMB;
+    Int QP;
+    Int mbnum = 0, slice_counter = 0, curr_slice_counter = 0;
+    Int num_bits, packet_size = encParams->ResyncPacketsize;
+    Int GOB_Header_Interval = encParams->GOB_Header_Interval;
+    BitstreamEncVideo *bs1 = video->bitstream1;
+    Int numHeaderBits;
+    approxDCT fastDCTfunction;
+    Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB,  5/18/2001 */
+    PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
+    void (*MBVlcEncode)(VideoEncData*, Int[], void *);
+    void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
+
+    /* for H263 GOB changes */
+//MP4RateControlType rc_type = encParams->RC_Type;
+
+    video->QP_prev = currVop->quantizer;
+
+    numHeaderBits = BitstreamGetPos(bs1);
+
+    /* determine type of quantization   */
+#ifndef NO_MPEG_QUANT
+    if (currVol->quantType == 0)
+        CodeMB = &CodeMB_H263;
+    else
+        CodeMB = &CodeMB_MPEG;
+#else
+    CodeMB = &CodeMB_H263;
+#endif
+
+    /* determine which functions to be used, in MB-level */
+    if (currVop->predictionType == P_VOP)
+        MBVlcEncode = &MBVlcEncodeCombined_P_VOP;
+    else if (currVop->predictionType == I_VOP)
+        MBVlcEncode = &MBVlcEncodeCombined_I_VOP;
+    else /* B_VOP not implemented yet */
+        return PV_FAIL;
+
+    /* determine which VLC table to be used */
+#ifndef H263_ONLY
+    if (currVol->shortVideoHeader)
+        BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#ifndef NO_RVLC
+    else if (currVol->useReverseVLC)
+        BlockCodeCoeff = &BlockCodeCoeff_RVLC;
+#endif
+    else
+        BlockCodeCoeff = &BlockCodeCoeff_Normal;
+#else
+    BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#endif
+
+    /* gob_frame_id is the same for different vop types - the reason should be SCD */
+    if (currVol->shortVideoHeader && currVop->gobFrameID != currVop->predictionType)
+        currVop->gobFrameID = currVop->predictionType;
+
+
+    video->usePrevQP = 0;
+
+    for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++)    /* Col MB Loop */
+    {
+
+        video->outputMB->mb_y = ind_y; /*  5/28/01 */
+
+        if (currVol->shortVideoHeader)  /* ShortVideoHeader Mode */
+        {
+
+            if (slice_counter && GOB_Header_Interval && (ind_y % GOB_Header_Interval == 0))     /* Encode GOB Header */
+            {
+                QP = QPMB[mbnum];    /* Get quant_scale */
+                video->header_bits -= BitstreamGetPos(currVol->stream); /* Header Bits */
+                status = EncodeGOBHeader(video, slice_counter, QP, 0);  //ind_y     /* Encode GOB Header */
+                video->header_bits += BitstreamGetPos(currVol->stream); /* Header Bits */
+                curr_slice_counter = slice_counter;
+            }
+        }
+
+        for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++)  /* Row MB Loop */
+        {
+            video->outputMB->mb_x = ind_x; /*  5/28/01 */
+            video->mbnum = mbnum;
+            QP = QPMB[mbnum];   /* always read new QP */
+
+            if (GOB_Header_Interval)
+                video->sliceNo[mbnum] = curr_slice_counter; /* Update MB slice number */
+            else
+                video->sliceNo[mbnum] = slice_counter;
+
+            /****************************************************************************************/
+            /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
+            /****************************************************************************************/
+            getMotionCompensatedMB(video, ind_x, ind_y, offset);
+
+#ifndef H263_ONLY
+            if (start_packet_header)
+            {
+                slice_counter++;                        /* Increment slice counter */
+                video->sliceNo[mbnum] = slice_counter;  /* Update MB slice number*/
+                video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+                video->QP_prev = currVop->quantizer;
+                status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
+                video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+                numHeaderBits = BitstreamGetPos(bs1);
+                start_packet_header = 0;
+                video->usePrevQP = 0;
+            }
+#endif
+            /***********************************************/
+            /* Code_MB:  DCT, Q, Q^(-1), IDCT, Motion Comp */
+            /***********************************************/
+
+            status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
+
+            /************************************/
+            /* MB VLC Encode: VLC Encode MB     */
+            /************************************/
+
+            (*MBVlcEncode)(video, ncoefblck, (void*)BlockCodeCoeff);
+
+            /*************************************************************/
+            /* Assemble Packets:  Assemble the MB VLC codes into Packets */
+            /*************************************************************/
+
+            /* Assemble_Packet(video) */
+#ifndef H263_ONLY
+            if (!currVol->shortVideoHeader) /* Not in ShortVideoHeader mode */
+            {
+                if (!currVol->ResyncMarkerDisable) /* RESYNC MARKER MODE */
+                {
+                    num_bits = BitstreamGetPos(bs1) - numHeaderBits;
+                    if (num_bits > packet_size)
+                    {
+                        video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+
+                        status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
+                        /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+                        BitstreamEncReset(bs1);
+
+                        start_packet_header = 1;
+                    }
+                }
+                else   /* NO RESYNC MARKER MODE */
+                {
+                    status = BitstreamAppendEnc(currVol->stream, bs1); /* Initialize to 0 */
+                    /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+                    BitstreamEncReset(bs1);
+                }
+            }
+            else
+#endif /* H263_ONLY */
+            {   /* ShortVideoHeader Mode */
+                status = BitstreamAppendEnc(currVol->stream, bs1);  /* Initialize to 0 */
+                /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+                BitstreamEncReset(bs1);
+            }
+            mbnum++;
+            offset += 16;
+        } /* End of For ind_x */
+
+        offset += (lx << 4) - width;
+        if (currVol->shortVideoHeader)  /* ShortVideoHeader = 1 */
+        {
+
+            if (GOB_Header_Interval)  slice_counter++;
+        }
+
+    } /* End of For ind_y */
+
+    if (currVol->shortVideoHeader) /* ShortVideoHeader = 1 */
+    {
+
+        video->header_bits += BitstreamShortHeaderByteAlignStuffing(currVol->stream); /* Byte Align */
+    }
+#ifndef H263_ONLY
+    else   /* Combined Mode*/
+    {
+        if (!currVol->ResyncMarkerDisable) /* Resync Markers */
+        {
+
+            if (!start_packet_header)
+            {
+                video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1);/* Byte Align  */
+
+                status = BitstreamAppendPacket(currVol->stream, bs1);   /* Put Packet to Buffer */
+                /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+                BitstreamEncReset(bs1);
+            }
+        }
+        else   /* No Resync Markers */
+        {
+            video->header_bits += BitstreamMpeg4ByteAlignStuffing(currVol->stream); /* Byte Align */
+        }
+    }
+#endif /* H263_ONLY */
+
+    return status; /* if status == PV_END_OF_BUF, this frame will be pre-skipped */
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/*  Function : EncodeSliceCombinedMode()                                    */
+/*  Date     : 04/19/2002                                                   */
+/*  History  :                                                              */
+/*  Purpose  : Encode a slice of MPEG4 bitstream in Combined mode and save  */
+/*              the current MB to continue next time it is called.          */
+/*  In/out   :                                                              */
+/*  Return   :  PV_SUCCESS if successful else PV_FAIL                       */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+PV_STATUS EncodeSliceCombinedMode(VideoEncData *video)
+{
+    PV_STATUS status = PV_SUCCESS;
+    Vol *currVol = video->vol[video->currLayer];
+    Vop *currVop = video->currVop;
+    UChar mode = MODE_INTRA;
+    UChar *Mode = video->headerInfo.Mode;
+    VideoEncParams *encParams = video->encParams;
+    Int nTotalMB = currVol->nTotalMB;
+    Int width = currVop->width; /* has to be Vop, for multiple of 16 */
+    Int lx = currVop->pitch; /* , with padding */
+//  rateControl *rc = encParams->rc[video->currLayer];
+    UChar *QPMB = video->QPMB;
+    Int QP;
+    Int ind_x = video->outputMB->mb_x, ind_y = video->outputMB->mb_y;
+    Int offset = video->offset;                 /* get current MB location */
+    Int mbnum = video->mbnum, slice_counter = video->sliceNo[mbnum]; /* get current MB location */
+    Int firstMB = mbnum;
+    Int start_packet_header = 0;
+    Int num_bits = 0;
+    Int packet_size = encParams->ResyncPacketsize - 1;
+    Int resync_marker = ((!currVol->shortVideoHeader) && (!currVol->ResyncMarkerDisable));
+    BitstreamEncVideo *bs1 = video->bitstream1;
+    Int byteCount = 0, byteCount1 = 0, bitCount = 0;
+    Int numHeaderBits = 0;
+    approxDCT fastDCTfunction;
+    Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB,  5/18/2001 */
+    UChar CBP = 0;
+    Short outputMB[6][64];
+    Int k;
+    PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
+    void (*MBVlcEncode)(VideoEncData*, Int[], void *);
+    void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
+
+    video->QP_prev = 31;
+
+#define H263_GOB_CHANGES
+
+
+    if (video->end_of_buf) /* left-over from previous run */
+    {
+        status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+        if (status != PV_END_OF_BUF)
+        {
+            BitstreamEncReset(bs1);
+            video->end_of_buf = 0;
+        }
+        return status;
+    }
+
+
+    if (mbnum == 0) /* only do this at the start of a frame */
+    {
+        QPMB[0] = video->QP_prev = QP = currVop->quantizer;
+        video->usePrevQP = 0;
+
+        numHeaderBits = BitstreamGetPos(bs1);
+    }
+
+    /* Re-assign fast functions on every slice, don't have to put it in the memory */
+    QP = QPMB[mbnum];
+    if (mbnum > 0)   video->QP_prev = QPMB[mbnum-1];
+
+    /* determine type of quantization   */
+#ifndef NO_MPEG_QUANT
+    if (currVol->quantType == 0)
+        CodeMB = &CodeMB_H263;
+    else
+        CodeMB = &CodeMB_MPEG;
+#else
+    CodeMB = &CodeMB_H263;
+#endif
+
+    /* determine which functions to be used, in MB-level */
+    if (currVop->predictionType == P_VOP)
+        MBVlcEncode = &MBVlcEncodeCombined_P_VOP;
+    else if (currVop->predictionType == I_VOP)
+        MBVlcEncode = &MBVlcEncodeCombined_I_VOP;
+    else /* B_VOP not implemented yet */
+        return PV_FAIL;
+
+    /* determine which VLC table to be used */
+#ifndef H263_ONLY
+    if (currVol->shortVideoHeader)
+        BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#ifndef NO_RVLC
+    else if (currVol->useReverseVLC)
+        BlockCodeCoeff = &BlockCodeCoeff_RVLC;
+#endif
+    else
+        BlockCodeCoeff = &BlockCodeCoeff_Normal;
+#else
+    BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#endif
+
+    /*  (gob_frame_id is the same for different vop types) The reason should be SCD */
+    if (currVol->shortVideoHeader && currVop->gobFrameID != currVop->predictionType)
+        currVop->gobFrameID = currVop->predictionType;
+
+
+    if (mbnum != 0)
+    {
+        if (currVol->shortVideoHeader)
+        {
+            /* Encode GOB Header */
+            bitCount = BitstreamGetPos(bs1);
+            byteCount1 = byteCount = bitCount >> 3; /* save the position before GOB header */
+            bitCount = bitCount & 0x7;
+
+#ifdef H263_GOB_CHANGES
+            video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+            status = EncodeGOBHeader(video, slice_counter, QP, 1);  //ind_y    /* Encode GOB Header */
+            video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+#endif
+            goto JUMP_IN_SH;
+        }
+        else if (currVol->ResyncMarkerDisable)
+        {
+            goto JUMP_IN_SH;
+        }
+        else
+        {
+            start_packet_header = 1;
+            goto JUMP_IN;
+        }
+    }
+
+    for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++)    /* Col MB Loop */
+    {
+
+        video->outputMB->mb_y = ind_y; /*  5/28/01, do not remove */
+
+        for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++)  /* Row MB Loop */
+        {
+
+            video->outputMB->mb_x = ind_x; /*  5/28/01, do not remove */
+            video->mbnum = mbnum;
+            video->sliceNo[mbnum] = slice_counter;      /* Update MB slice number */
+JUMP_IN_SH:
+            /****************************************************************************************/
+            /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
+            /****************************************************************************************/
+            getMotionCompensatedMB(video, ind_x, ind_y, offset);
+
+JUMP_IN:
+            QP = QPMB[mbnum];   /* always read new QP */
+#ifndef H263_ONLY
+            if (start_packet_header)
+            {
+                slice_counter++;                        /* Increment slice counter */
+                video->sliceNo[mbnum] = slice_counter;  /* Update MB slice number*/
+                video->QP_prev = currVop->quantizer;                        /* store QP */
+                num_bits = BitstreamGetPos(bs1);
+                status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 1);
+                numHeaderBits = BitstreamGetPos(bs1) - num_bits;
+                video->header_bits += numHeaderBits; /* Header Bits */
+                start_packet_header = 0;
+                video->usePrevQP = 0;
+            }
+            else  /* don't encode the first MB in packet again */
+#endif /* H263_ONLY */
+            {
+                /***********************************************/
+                /* Code_MB:  DCT, Q, Q^(-1), IDCT, Motion Comp */
+                /***********************************************/
+                status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
+            }
+
+            /************************************/
+            /* MB VLC Encode: VLC Encode MB     */
+            /************************************/
+
+            /* save the state before VLC encoding */
+            if (resync_marker)
+            {
+                bitCount = BitstreamGetPos(bs1);
+                byteCount = bitCount >> 3; /* save the state before encoding */
+                bitCount = bitCount & 0x7;
+                mode = Mode[mbnum];
+                CBP = video->headerInfo.CBP[mbnum];
+                for (k = 0; k < 6; k++)
+                {
+                    M4VENC_MEMCPY(outputMB[k], video->outputMB->block[k], sizeof(Short) << 6);
+                }
+            }
+            /*************************************/
+
+            (*MBVlcEncode)(video, ncoefblck, (void*)BlockCodeCoeff);
+
+            /*************************************************************/
+            /* Assemble Packets:  Assemble the MB VLC codes into Packets */
+            /*************************************************************/
+
+            /* Assemble_Packet(video) */
+#ifndef H263_ONLY
+            if (!currVol->shortVideoHeader)
+            {
+                if (!currVol->ResyncMarkerDisable)
+                {
+                    /* Not in ShortVideoHeader mode and RESYNC MARKER MODE */
+
+                    num_bits = BitstreamGetPos(bs1) ;//- numHeaderBits; // include header
+
+                    /* Assemble packet and return when size reached */
+                    if (num_bits > packet_size && mbnum != firstMB)
+                    {
+
+                        BitstreamRepos(bs1, byteCount, bitCount); /* rewind one MB */
+
+                        video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+
+                        status = BitstreamAppendPacketNoOffset(currVol->stream, bs1); /* Put Packet to Buffer */
+
+                        if (status == PV_END_OF_BUF)
+                        {
+                            video->end_of_buf = 1;
+                        }
+                        else
+                        {
+                            BitstreamEncReset(bs1);
+                        }
+
+                        start_packet_header = 1;
+
+                        if (mbnum < nTotalMB || video->end_of_buf) /* return here */
+                        {
+                            video->mbnum = mbnum;
+                            video->sliceNo[mbnum] = slice_counter;
+                            video->offset = offset;
+                            Mode[mbnum] = mode;
+                            video->headerInfo.CBP[mbnum] = CBP;
+
+                            for (k = 0; k < 6; k++)
+                            {
+                                M4VENC_MEMCPY(video->outputMB->block[k], outputMB[k], sizeof(Short) << 6);
+                            }
+
+                            return status;
+                        }
+                    }
+                }
+                else  /* NO RESYNC MARKER , return when buffer is full*/
+                {
+
+                    if (mbnum < nTotalMB - 1 && currVol->stream->byteCount + bs1->byteCount + 1 >= currVol->stream->bufferSize)
+                    {
+                        /* find maximum bytes to fit in the buffer */
+                        byteCount = currVol->stream->bufferSize - currVol->stream->byteCount - 1;
+
+                        num_bits = BitstreamGetPos(bs1) - (byteCount << 3);
+                        BitstreamRepos(bs1, byteCount, 0);
+                        status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+                        BitstreamFlushBits(bs1, num_bits);
+
+                        /* move on to next MB */
+                        mbnum++ ;
+                        offset += 16;
+                        video->outputMB->mb_x++;
+                        if (video->outputMB->mb_x >= currVol->nMBPerRow)
+                        {
+                            video->outputMB->mb_x = 0;
+                            video->outputMB->mb_y++;
+                            offset += (lx << 4) - width;
+                        }
+                        video->mbnum = mbnum;
+                        video->offset = offset;
+                        video->sliceNo[mbnum] = slice_counter;
+                        return status;
+                    }
+                }
+            }
+#endif /* H263_ONLY */
+            offset += 16;
+            mbnum++; /* has to increment before SCD, to preserve Mode[mbnum] */
+
+        } /* End of For ind_x */
+
+        offset += (lx << 4) - width;
+
+        if (currVol->shortVideoHeader)  /* ShortVideoHeader = 1 */
+        {
+#ifdef H263_GOB_CHANGES
+            slice_counter++;
+            video->header_bits += BitstreamShortHeaderByteAlignStuffing(bs1);
+#endif
+            //video->header_bits+=BitstreamShortHeaderByteAlignStuffing(bs1);
+
+            /* check if time to packetize */
+            if (currVol->stream->byteCount + bs1->byteCount > currVol->stream->bufferSize)
+            {
+                if (byteCount == byteCount1) /* a single GOB bigger than packet size */
+                {
+                    status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+                    status = PV_END_OF_BUF;
+                    video->end_of_buf = 1;
+                    start_packet_header = 1;
+                }
+                else    /* for short_header scooch back to previous GOB */
+                {
+                    num_bits = ((bs1->byteCount - byteCount) << 3);
+                    //num_bits = ((bs1->byteCount<<3) + bs1->bitCount) - ((byteCount<<3) + bitCount);
+                    BitstreamRepos(bs1, byteCount, 0);
+                    //BitstreamRepos(bs1,byteCount,bitCount);
+//                  k = currVol->stream->byteCount; /* save state before appending */
+                    status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+                    BitstreamFlushBits(bs1, num_bits);
+//                  if(mbnum == nTotalMB || k + bs1->byteCount >= currVol->stream->bufferSize){
+                    /* last GOB or current one with larger size will be returned next run */
+//                      status = PV_END_OF_BUF;
+//                      video->end_of_buf = 1;
+//                  }
+                    start_packet_header = 1;
+                    if (mbnum == nTotalMB) /* there's one more GOB to packetize for the next round */
+                    {
+                        status = PV_END_OF_BUF;
+                        video->end_of_buf = 1;
+                    }
+                }
+
+                if (mbnum < nTotalMB) /* return here */
+                {
+                    /* move on to next MB */
+                    video->outputMB->mb_x = 0;
+                    video->outputMB->mb_y++;
+                    video->mbnum = mbnum;
+                    video->offset = offset;
+                    video->sliceNo[mbnum] = slice_counter;
+                    return status;
+                }
+            }
+            else if (mbnum < nTotalMB) /* do not write GOB header if end of vop */
+            {
+                bitCount = BitstreamGetPos(bs1);
+                byteCount = bitCount >> 3;  /* save the position before GOB header */
+                bitCount = bitCount & 0x7;
+#ifdef H263_GOB_CHANGES
+                video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+                status = EncodeGOBHeader(video, slice_counter, QP, 1);         /* Encode GOB Header */
+                video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+#endif
+            }
+        }
+
+    } /* End of For ind_y */
+#ifndef H263_ONLY
+    if (!currVol->shortVideoHeader) /* Combined Mode*/
+    {
+        if (!currVol->ResyncMarkerDisable) /* Resync Markers */
+        {
+
+            if (!start_packet_header)
+            {
+
+                video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1);/* Byte Align  */
+
+                status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);   /* Put Packet to Buffer */
+                if (status == PV_END_OF_BUF)
+                {
+                    video->end_of_buf = 1;
+                }
+                else
+                {
+                    BitstreamEncReset(bs1);
+                }
+            }
+        }
+        else   /* No Resync Markers */
+        {
+            video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte Align */
+            status = BitstreamAppendPacketNoOffset(currVol->stream, bs1); /* Initialize to 0 */
+            if (status == PV_END_OF_BUF)
+            {
+                video->end_of_buf = 1;
+            }
+            else
+            {
+                BitstreamEncReset(bs1);
+            }
+        }
+    }
+    else
+#endif /* H263_ONLY */
+    {
+        if (!start_packet_header) /* not yet packetized */
+        {
+            video->header_bits += BitstreamShortHeaderByteAlignStuffing(bs1);
+            status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+            if (status == PV_END_OF_BUF)
+            {
+                video->end_of_buf = 1;
+            }
+            else
+            {
+                BitstreamEncReset(bs1);
+                video->end_of_buf = 0;
+            }
+        }
+    }
+
+    video->mbnum = mbnum;
+    if (mbnum < nTotalMB)
+        video->sliceNo[mbnum] = slice_counter;
+    video->offset = offset;
+
+    return status;
+}
+#endif  /* NO_SLICE_ENCODE */
+
+/* ======================================================================== */
+/*  Function : EncodeGOBHeader()                                            */
+/*  Date     : 09/05/2000                                                   */
+/*  History  :                                                              */
+/*  Purpose  : Encode a frame of MPEG4 bitstream in Combined mode.          */
+/*  In/out   :                                                              */
+/*  Return   :  PV_SUCCESS if successful else PV_FAIL                       */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+PV_STATUS EncodeGOBHeader(VideoEncData *video, Int GOB_number, Int quant_scale, Int bs1stream)
+{
+    PV_STATUS status = PV_SUCCESS;
+    BitstreamEncVideo *stream = (bs1stream ? video->bitstream1 : video->vol[video->currLayer]->stream);
+
+    status = BitstreamPutGT16Bits(stream, 17, GOB_RESYNC_MARKER); /* gob_resync_marker */
+    status = BitstreamPutBits(stream, 5, GOB_number);           /* Current gob_number */
+    status = BitstreamPutBits(stream, 2, video->currVop->gobFrameID); /* gob_frame_id */
+    status = BitstreamPutBits(stream, 5, quant_scale);              /* quant_scale */
+    return status;
+}
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp
new file mode 100644
index 0000000..16c8e79
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp
@@ -0,0 +1,482 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 H263_ONLY
+
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "bitstream_io.h"
+#include "mp4enc_lib.h"
+#include "m4venc_oscl.h"
+
+/* ======================================================================== */
+/*  Function : EncodeFrameDataPartMode()                                    */
+/*  Date     : 09/6/2000                                                    */
+/*  History  :                                                              */
+/*  Purpose  : Encode a frame of MPEG4 bitstream in datapartitioning mode.  */
+/*  In/out   :                                                              */
+/*  Return   :  PV_SUCCESS if successful else PV_FAIL                       */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+PV_STATUS EncodeFrameDataPartMode(VideoEncData *video)
+{
+    PV_STATUS status = PV_SUCCESS;
+    Vol *currVol = video->vol[video->currLayer];
+    Vop *currVop = video->currVop;
+    VideoEncParams *encParams = video->encParams;
+    Int width = currVop->width; /* has to be Vop, for multiple of 16 */
+    Int lx = currVop->pitch; /*  with padding */
+    Int offset = 0;
+    Int ind_x, ind_y;
+    Int start_packet_header = 0;
+    UChar *QPMB = video->QPMB;
+    Int QP;
+    Int mbnum = 0, slice_counter = 0;
+    Int num_bits, packet_size = encParams->ResyncPacketsize;
+    BitstreamEncVideo *bs1 = video->bitstream1;
+    BitstreamEncVideo *bs2 = video->bitstream2;
+    BitstreamEncVideo *bs3 = video->bitstream3;
+    Int numHeaderBits;
+    approxDCT fastDCTfunction;
+    Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB,  5/18/2001 */
+    PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
+    void (*MBVlcEncode)(VideoEncData*, Int[], void *);
+    void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
+
+    video->QP_prev = currVop->quantizer;
+
+    numHeaderBits = BitstreamGetPos(bs1); /* Number of bits in VOP Header */
+
+    /* determine type of quantization   */
+#ifndef NO_MPEG_QUANT
+    if (currVol->quantType == 0)
+        CodeMB = &CodeMB_H263;
+    else
+        CodeMB = &CodeMB_MPEG;
+#else
+    CodeMB = &CodeMB_H263;
+#endif
+
+    /* determine which functions to be used, in MB-level */
+    if (currVop->predictionType == P_VOP)
+        MBVlcEncode = &MBVlcEncodeDataPar_P_VOP;
+    else if (currVop->predictionType == I_VOP)
+        MBVlcEncode = &MBVlcEncodeDataPar_I_VOP;
+    else /* B_VOP not implemented yet */
+        return PV_FAIL;
+
+    /* determine which VLC table to be used */
+    if (currVol->shortVideoHeader)
+        BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#ifndef NO_RVLC
+    else if (currVol->useReverseVLC)
+        BlockCodeCoeff = &BlockCodeCoeff_RVLC;
+#endif
+    else
+        BlockCodeCoeff = &BlockCodeCoeff_Normal;
+
+    video->usePrevQP = 0;
+
+    for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++)    /* Col MB Loop */
+    {
+
+        video->outputMB->mb_y = ind_y; /*  5/28/01 */
+
+        for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++)  /* Row MB Loop */
+        {
+            video->outputMB->mb_x = ind_x; /*  5/28/01 */
+            video->mbnum = mbnum;
+            video->sliceNo[mbnum] = slice_counter;      /* Update MB slice number */
+            QP = QPMB[mbnum];   /* always read new QP */
+
+            /****************************************************************************************/
+            /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
+            /****************************************************************************************/
+
+            getMotionCompensatedMB(video, ind_x, ind_y, offset);
+
+            if (start_packet_header)
+            {
+                slice_counter++;                        /* Increment slice counter */
+                video->sliceNo[mbnum] = slice_counter;  /* Update MB slice number*/
+                video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+                video->QP_prev = currVop->quantizer;                        /* store QP */
+                status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
+                video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+                numHeaderBits = BitstreamGetPos(bs1);
+                start_packet_header = 0;
+                video->usePrevQP = 0;
+            }
+
+            /***********************************************/
+            /* Code_MB:  DCT, Q, Q^(-1), IDCT, Motion Comp */
+            /***********************************************/
+
+            status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
+
+            /************************************/
+            /* MB VLC Encode: VLC Encode MB     */
+            /************************************/
+
+            MBVlcEncode(video, ncoefblck, (void*)BlockCodeCoeff);
+
+            /*************************************************************/
+            /* Assemble Packets:  Assemble the MB VLC codes into Packets */
+            /*************************************************************/
+
+            /* INCLUDE VOP HEADER IN COUNT */
+
+            num_bits = BitstreamGetPos(bs1) + BitstreamGetPos(bs2) +
+                       BitstreamGetPos(bs3) - numHeaderBits;
+
+            /* Assemble_Packet(video) */
+
+            if (num_bits > packet_size)
+            {
+                if (video->currVop->predictionType == I_VOP)
+                    BitstreamPutGT16Bits(bs1, 19, DC_MARKER);   /* Add dc_marker */
+                else
+                    BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
+                BitstreamAppendEnc(bs1, bs2);   /* Combine bs1 and bs2 */
+                BitstreamAppendEnc(bs1, bs3);   /* Combine bs1 and bs3 */
+                video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+
+                status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
+                /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+                BitstreamEncReset(bs1); /* Initialize to 0 */
+                BitstreamEncReset(bs2);
+                BitstreamEncReset(bs3);
+                start_packet_header = 1;
+            }
+            mbnum++;
+            offset += 16;
+        } /* End of For ind_x */
+
+        offset += (lx << 4) - width;
+    } /* End of For ind_y */
+
+    if (!start_packet_header)
+    {
+        if (video->currVop->predictionType == I_VOP)
+        {
+            BitstreamPutGT16Bits(bs1, 19, DC_MARKER);   /* Add dc_marker */
+            video->header_bits += 19;
+        }
+        else
+        {
+            BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /* Add motion_marker */
+            video->header_bits += 17;
+        }
+        BitstreamAppendEnc(bs1, bs2);
+        BitstreamAppendEnc(bs1, bs3);
+        video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+        status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
+        /* continue even if status == PV_END_OF_BUF, to get the stats */
+        BitstreamEncReset(bs1); /* Initialize to 0 */
+        BitstreamEncReset(bs2);
+        BitstreamEncReset(bs3);
+    }
+
+    return status; /* if status == PV_END_OF_BUF, this frame will be pre-skipped */
+}
+
+#ifndef  NO_SLICE_ENCODE
+/* ======================================================================== */
+/*  Function : EncodeSliceDataPartMode()                                    */
+/*  Date     : 04/19/2002                                                   */
+/*  History  :                                                              */
+/*  Purpose  : Encode a slice of MPEG4 bitstream in DataPar mode and save   */
+/*              the current MB to continue next time it is called.          */
+/*  In/out   :                                                              */
+/*  Return   :  PV_SUCCESS if successful else PV_FAIL                       */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+PV_STATUS EncodeSliceDataPartMode(VideoEncData *video)
+{
+    PV_STATUS status = PV_SUCCESS;
+    Vol *currVol = video->vol[video->currLayer];
+    Vop *currVop = video->currVop;
+    UChar mode, *Mode = video->headerInfo.Mode;
+    VideoEncParams *encParams = video->encParams;
+    Int nTotalMB = currVol->nTotalMB;
+    Int width = currVop->width; /* has to be Vop, for multiple of 16 */
+    Int lx = currVop->pitch; /* , with pading */
+    UChar *QPMB = video->QPMB;
+    Int QP;
+    Int ind_x = video->outputMB->mb_x, ind_y = video->outputMB->mb_y;
+    Int offset = video->offset;                 /* get current MB location */
+    Int mbnum = video->mbnum, slice_counter = video->sliceNo[mbnum]; /* get current MB location */
+    Int firstMB = mbnum;
+    Int start_packet_header = (mbnum != 0);
+    Int num_bits = 0;
+    Int packet_size = encParams->ResyncPacketsize - 1 - (currVop->predictionType == I_VOP ? 19 : 17);
+    BitstreamEncVideo *bs1 = video->bitstream1;
+    BitstreamEncVideo *bs2 = video->bitstream2;
+    BitstreamEncVideo *bs3 = video->bitstream3;
+    Int bitCount1 = 0, bitCount2 = 0, bitCount3 = 0, byteCount1 = 0, byteCount2 = 0, byteCount3 = 0;
+    Int numHeaderBits = 0;
+    approxDCT fastDCTfunction;
+    Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB,  5/18/2001 */
+    UChar CBP;
+    Short outputMB[6][64];
+    PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
+    void (*MBVlcEncode)(VideoEncData*, Int[], void *);
+    void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
+    Int k;
+
+    video->QP_prev = 31;
+
+    if (video->end_of_buf) /* left-over from previous run */
+    {
+        status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+        if (status != PV_END_OF_BUF)
+        {
+            BitstreamEncReset(bs1);
+            video->end_of_buf = 0;
+        }
+        return status;
+    }
+
+    if (mbnum == 0) /* only do this at the start of a frame */
+    {
+        QPMB[0] = video->QP_prev = QP = currVop->quantizer;
+        video->usePrevQP = 0;
+
+        numHeaderBits = BitstreamGetPos(bs1); /* Number of bits in VOP Header */
+
+    }
+
+
+    /* Re-assign fast functions on every slice, don't have to put it in the memory */
+    QP = QPMB[mbnum];
+    if (mbnum > 0)   video->QP_prev = QPMB[mbnum-1];
+
+    /* determine type of quantization   */
+#ifndef NO_MPEG_QUANT
+    if (currVol->quantType == 0)
+        CodeMB = &CodeMB_H263;
+    else
+        CodeMB = &CodeMB_MPEG;
+#else
+    CodeMB = &CodeMB_H263;
+#endif
+
+    /* determine which functions to be used, in MB-level */
+    if (currVop->predictionType == P_VOP)
+        MBVlcEncode = &MBVlcEncodeDataPar_P_VOP;
+    else if (currVop->predictionType == I_VOP)
+        MBVlcEncode = &MBVlcEncodeDataPar_I_VOP;
+    else /* B_VOP not implemented yet */
+        return PV_FAIL;
+
+    /* determine which VLC table to be used */
+#ifndef NO_RVLC
+    if (currVol->useReverseVLC)
+        BlockCodeCoeff = &BlockCodeCoeff_RVLC;
+    else
+#endif
+        BlockCodeCoeff = &BlockCodeCoeff_Normal;
+
+    if (mbnum != 0)
+    {
+        goto JUMP_IN;
+    }
+
+    for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++)    /* Col MB Loop */
+    {
+
+        video->outputMB->mb_y = ind_y; /*  5/28/01 */
+
+        for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++)  /* Row MB Loop */
+        {
+
+            video->outputMB->mb_x = ind_x; /*  5/28/01 */
+            video->mbnum = mbnum;
+            video->sliceNo[mbnum] = slice_counter;      /* Update MB slice number */
+
+            /****************************************************************************************/
+            /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
+            /****************************************************************************************/
+            getMotionCompensatedMB(video, ind_x, ind_y, offset);
+
+JUMP_IN:
+
+            QP = QPMB[mbnum];   /* always read new QP */
+
+            if (start_packet_header)
+            {
+                slice_counter++;                        /* Increment slice counter */
+                video->sliceNo[mbnum] = slice_counter;  /* Update MB slice number*/
+                video->QP_prev = currVop->quantizer;                        /* store QP */
+                num_bits = BitstreamGetPos(bs1);
+                status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
+                numHeaderBits = BitstreamGetPos(bs1) - num_bits;
+                video->header_bits += numHeaderBits; /* Header Bits */
+                start_packet_header = 0;
+                video->usePrevQP = 0;
+            }
+            else  /* don't encode the first MB in packet again */
+            {
+                /***********************************************/
+                /* Code_MB:  DCT, Q, Q^(-1), IDCT, Motion Comp */
+                /***********************************************/
+
+                status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
+                for (k = 0; k < 6; k++)
+                {
+                    M4VENC_MEMCPY(outputMB[k], video->outputMB->block[k], sizeof(Short) << 6);
+                }
+            }
+
+            /************************************/
+            /* MB VLC Encode: VLC Encode MB     */
+            /************************************/
+
+            /* save the state before VLC encoding */
+            bitCount1 = BitstreamGetPos(bs1);
+            bitCount2 = BitstreamGetPos(bs2);
+            bitCount3 = BitstreamGetPos(bs3);
+            byteCount1 = bitCount1 >> 3;
+            byteCount2 = bitCount2 >> 3;
+            byteCount3 = bitCount3 >> 3;
+            bitCount1 &= 0x7;
+            bitCount2 &= 0x7;
+            bitCount3 &= 0x7;
+            mode = Mode[mbnum];
+            CBP = video->headerInfo.CBP[mbnum];
+
+            /*************************************/
+
+            MBVlcEncode(video, ncoefblck, (void*)BlockCodeCoeff);
+
+            /*************************************************************/
+            /* Assemble Packets:  Assemble the MB VLC codes into Packets */
+            /*************************************************************/
+
+            num_bits = BitstreamGetPos(bs1) + BitstreamGetPos(bs2) +
+                       BitstreamGetPos(bs3);// - numHeaderBits; //include header bits
+
+            /* Assemble_Packet(video) */
+            if (num_bits > packet_size && mbnum != firstMB)  /* encoding at least one more MB*/
+            {
+
+                BitstreamRepos(bs1, byteCount1, bitCount1); /* rewind one MB */
+                BitstreamRepos(bs2, byteCount2, bitCount2); /* rewind one MB */
+                BitstreamRepos(bs3, byteCount3, bitCount3); /* rewind one MB */
+
+                if (video->currVop->predictionType == I_VOP)
+                {
+                    BitstreamPutGT16Bits(bs1, 19, DC_MARKER);   /* Add dc_marker */
+                    video->header_bits += 19;
+                }
+                else
+                {
+                    BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
+                    video->header_bits += 17;
+                }
+
+                status = BitstreamAppendEnc(bs1, bs2);  /* Combine with bs2 */
+                status = BitstreamAppendEnc(bs1, bs3);  /* Combine with bs3 */
+
+                video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+                status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+
+                BitstreamEncReset(bs2);
+                BitstreamEncReset(bs3);
+
+                if (status == PV_END_OF_BUF) /* if cannot fit a buffer */
+                {
+                    video->end_of_buf = 1;
+                }
+                else
+                {
+                    BitstreamEncReset(bs1);
+                }
+
+                start_packet_header = 1;
+
+                if (mbnum < nTotalMB || video->end_of_buf) /* return here */
+                {
+                    video->mbnum = mbnum;
+                    video->sliceNo[mbnum] = slice_counter;
+                    video->offset = offset;
+                    Mode[mbnum] = mode;
+                    video->headerInfo.CBP[mbnum] = CBP;
+
+                    for (k = 0; k < 6; k++)
+                    {
+                        M4VENC_MEMCPY(video->outputMB->block[k], outputMB[k], sizeof(Short) << 6);
+                    }
+
+                    return status;
+                }
+            }
+
+            offset += 16;
+            mbnum++; /* has to increment before SCD, to preserve Mode[mbnum] */
+        } /* End of For ind_x */
+
+        offset += (lx << 4) - width;
+
+    } /* End of For ind_y */
+
+    if (!start_packet_header)
+    {
+        if (video->currVop->predictionType == I_VOP)
+        {
+            BitstreamPutGT16Bits(bs1, 19, DC_MARKER);   /* Add dc_marker */
+            video->header_bits += 19;
+        }
+        else
+        {
+            BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
+            video->header_bits += 17;
+        }
+
+        status = BitstreamAppendEnc(bs1, bs2);  /* Combine with bs2 */
+        status = BitstreamAppendEnc(bs1, bs3);  /* Combine with bs3 */
+
+        video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+        status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+
+        BitstreamEncReset(bs2);
+        BitstreamEncReset(bs3);
+
+        if (status == PV_END_OF_BUF)
+        {
+            video->end_of_buf = 1;
+        }
+        else
+        {
+            BitstreamEncReset(bs1);
+        }
+    }
+
+    video->mbnum = mbnum;
+    if (mbnum < nTotalMB)
+        video->sliceNo[mbnum] = slice_counter;
+    video->offset = offset;
+
+    return status;
+}
+#endif /* NO_SLICE_ENCODE */
+#endif /* H263_ONLY */
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp
new file mode 100644
index 0000000..fa50eeb
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp
@@ -0,0 +1,1283 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "dct_inline.h"
+
+#define FDCT_SHIFT 10
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /**************************************************************************/
+    /*  Function:   BlockDCT_AANwSub
+        Date:       7/31/01
+        Input:
+        Output:     out[64] ==> next block
+        Purpose:    Do subtraction for zero MV first
+        Modified:
+    **************************************************************************/
+
+    Void BlockDCT_AANwSub(Short *out, UChar *cur, UChar *pred, Int width)
+    {
+        Short *dst;
+        Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int round;
+        Int k12 = 0x022A02D4;
+        Int k14 = 0x0188053A;
+        Int abs_sum;
+        Int mask;
+        Int tmp, tmp2;
+        Int ColTh;
+
+        dst = out + 64 ;
+        ColTh = *dst;
+        out += 128;
+        round = 1 << (FDCT_SHIFT - 1);
+
+        do  /* fdct_nextrow */
+        {
+            /* assuming the block is word-aligned */
+            mask = 0x1FE;
+            tmp = *((Int*) cur);    /* contains 4 pixels */
+            tmp2 = *((Int*) pred); /* prediction 4 pixels */
+            k0 = tmp2 & 0xFF;
+            k1 = mask & (tmp << 1);
+            k0 = k1 - (k0 << 1);
+            k1 = (tmp2 >> 8) & 0xFF;
+            k2 = mask & (tmp >> 7);
+            k1 = k2 - (k1 << 1);
+            k2 = (tmp2 >> 16) & 0xFF;
+            k3 = mask & (tmp >> 15);
+            k2 = k3 - (k2 << 1);
+            k3 = (tmp2 >> 24) & 0xFF;
+            k4 = mask & (tmp >> 23);
+            k3 = k4 - (k3 << 1);
+            tmp = *((Int*)(cur + 4));   /* another 4 pixels */
+            tmp2 = *((Int*)(pred + 4));
+            k4 = tmp2 & 0xFF;
+            k5 = mask & (tmp << 1);
+            k4 = k5 - (k4 << 1);
+            k5 = (tmp2 >> 8) & 0xFF;
+            k6 = mask & (tmp >> 7);
+            k5 = k6 - (k5 << 1);
+            k6 = (tmp2 >> 16) & 0xFF;
+            k7 = mask & (tmp >> 15);
+            k6 = k7 - (k6 << 1);
+            k7 = (tmp2 >> 24) & 0xFF;
+            tmp = mask & (tmp >> 23);
+            k7 = tmp - (k7 << 1);
+            cur += width;
+            pred += 16;
+
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            k1 = k0 - (k1 << 1);
+            /**********/
+            dst[0] = k0;
+            dst[4] = k1; /* col. 4 */
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            k2 = k2 + k3;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+            k0 = mla724(k12, k2, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            k2 = k0 >> FDCT_SHIFT;
+            /*****************/
+            k2 = k2 + k3;
+            k3 = (k3 << 1) - k2;
+            /********/
+            dst[2] = k2;        /* col. 2 */
+            k3 <<= 1;       /* scale up col. 6 */
+            dst[6] = k3; /* col. 6 */
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k0 = k4 - k6;
+
+            k1 = mla392(k0, k14, round);
+            k0 = mla554(k4, k12, k1);
+            k1 = mla1338(k6, k14, k1);
+
+            k4 = k0 >> FDCT_SHIFT;
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k7 = (k7 << 1) - k5;
+            k4 = k4 + k7;
+            k7 = (k7 << 1) - k4;
+            k5 = k5 + k6;
+            k4 <<= 1;       /* scale up col.5 */
+            k6 = k5 - (k6 << 1);
+            /********/
+            dst[5] = k4;    /* col. 5 */
+            k6 <<= 2;       /* scale up col. 7 */
+            dst[1] = k5;    /* col. 1 */
+            dst[7] = k6;    /* col. 7 */
+            dst[3] = k7;    /* col. 3 */
+            dst += 8;
+        }
+        while (dst < out);
+
+        out -= 64;
+        dst = out + 8;
+
+        /*  Vertical Block Loop  */
+        do  /* Vertical 8xDCT loop */
+        {
+            k0 = out[0];
+            k1 = out[8];
+            k2 = out[16];
+            k3 = out[24];
+            k4 = out[32];
+            k5 = out[40];
+            k6 = out[48];
+            k7 = out[56];
+            /* deadzone thresholding for column */
+
+            abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+            if (abs_sum < ColTh)
+            {
+                out[0] = 0x7fff;
+                out++;
+                continue;
+            }
+
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            k1 = k0 - (k1 << 1);
+            /**********/
+            out[32] = k1; /* row 4 */
+            out[0] = k0; /* row 0 */
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            k2 = k2 + k3;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+            k0 = mla724(k12, k2, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            k2 = k0 >> FDCT_SHIFT;
+            /*****************/
+            k2 = k2 + k3;
+            k3 = (k3 << 1) - k2;
+            k3 <<= 1;       /* scale up col. 6 */
+            /********/
+            out[48] = k3;   /* row 6 */
+            out[16] = k2;   /* row 2 */
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k0 = k4 - k6;
+
+            k1 = mla392(k0, k14, round);
+            k0 = mla554(k4, k12, k1);
+            k1 = mla1338(k6, k14, k1);
+
+            k4 = k0 >> FDCT_SHIFT;
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k7 = (k7 << 1) - k5;
+            k4 = k4 + k7;
+            k7 = (k7 << 1) - k4;
+            k5 = k5 + k6;
+            k4 <<= 1;       /* scale up col. 5 */
+            k6 = k5 - (k6 << 1);
+            /********/
+            out[24] = k7 ;    /* row 3 */
+            k6 <<= 2;       /* scale up col. 7 */
+            out[56] = k6 ;   /* row 7 */
+            out[8] = k5 ;    /* row 1 */
+            out[40] = k4 ;   /* row 5 */
+            out++;
+        }
+        while ((UInt)out < (UInt)dst) ;
+
+        return ;
+    }
+
+    /**************************************************************************/
+    /*  Function:   Block4x4DCT_AANwSub
+        Date:       7/31/01
+        Input:
+        Output:     out[64] ==> next block
+        Purpose:    Do subtraction for zero MV first before 4x4 DCT
+        Modified:
+    **************************************************************************/
+
+    Void Block4x4DCT_AANwSub(Short *out, UChar *cur, UChar *pred, Int width)
+    {
+        Short *dst;
+        register Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int round;
+        Int k12 = 0x022A02D4;
+        Int k14 = 0x0188053A;
+        Int mask;
+        Int tmp, tmp2;
+        Int abs_sum;
+        Int ColTh;
+
+        dst = out + 64 ;
+        ColTh = *dst;
+        out += 128;
+        round = 1 << (FDCT_SHIFT - 1);
+
+        do  /* fdct_nextrow */
+        {
+            /* assuming the block is word-aligned */
+            mask = 0x1FE;
+            tmp = *((Int*) cur);    /* contains 4 pixels */
+            tmp2 = *((Int*) pred); /* prediction 4 pixels */
+            k0 = tmp2 & 0xFF;
+            k1 = mask & (tmp << 1);
+            k0 = k1 - (k0 << 1);
+            k1 = (tmp2 >> 8) & 0xFF;
+            k2 = mask & (tmp >> 7);
+            k1 = k2 - (k1 << 1);
+            k2 = (tmp2 >> 16) & 0xFF;
+            k3 = mask & (tmp >> 15);
+            k2 = k3 - (k2 << 1);
+            k3 = (tmp2 >> 24) & 0xFF;
+            k4 = mask & (tmp >> 23);
+            k3 = k4 - (k3 << 1);
+            tmp = *((Int*)(cur + 4));   /* another 4 pixels */
+            tmp2 = *((Int*)(pred + 4));
+            k4 = tmp2 & 0xFF;
+            k5 = mask & (tmp << 1);
+            k4 = k5 - (k4 << 1);
+            k5 = (tmp2 >> 8) & 0xFF;
+            k6 = mask & (tmp >> 7);
+            k5 = k6 - (k5 << 1);
+            k6 = (tmp2 >> 16) & 0xFF;
+            k7 = mask & (tmp >> 15);
+            k6 = k7 - (k6 << 1);
+            k7 = (tmp2 >> 24) & 0xFF;
+            tmp = mask & (tmp >> 23);
+            k7 = tmp - (k7 << 1);
+            cur += width;
+            pred += 16;
+
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            /**********/
+            dst[0] = k0;
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            k2 = k2 + k3;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+            k0 = mla724(k12, k2, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            k2 = k0 >> FDCT_SHIFT;
+            /*****************/
+            k2 = k2 + k3;
+            /********/
+            dst[2] = k2;        /* col. 2 */
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k0 = k4 - k6;
+
+            k1 = mla392(k0, k14, round);
+            k0 = mla554(k4, k12, k1);
+            k1 = mla1338(k6, k14, k1);
+
+            k4 = k0 >> FDCT_SHIFT;
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k7 = (k7 << 1) - k5;
+            k7 = k7 - k4;
+            k5 = k5 + k6;
+            /********/
+            dst[1] = k5;        /* col. 1 */
+            dst[3] = k7;        /* col. 3 */
+            dst += 8;
+        }
+        while (dst < out);
+
+        out -= 64;
+        dst = out + 4;
+
+        /*  Vertical Block Loop  */
+        do  /* Vertical 8xDCT loop */
+        {
+            k0 = out[0];
+            k1 = out[8];
+            k2 = out[16];
+            k3 = out[24];
+            k4 = out[32];
+            k5 = out[40];
+            k6 = out[48];
+            k7 = out[56];
+
+            abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+            if (abs_sum < ColTh)
+            {
+                out[0] = 0x7fff;
+                out++;
+                continue;
+            }
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            /**********/
+            out[0] = k0;   /* row 0 */
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            k2 = k2 + k3;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+            k0 = mla724(k12, k2, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            k2 = k0 >> FDCT_SHIFT;
+            /*****************/
+            k2 = k2 + k3;
+            /********/
+            out[16] = k2;           /* row 2 */
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k0 = k4 - k6;
+
+            k1 = mla392(k0, k14, round);
+            k0 = mla554(k4, k12, k1);
+            k1 = mla1338(k6, k14, k1);
+
+            k4 = k0 >> FDCT_SHIFT;
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k7 = (k7 << 1) - k5;
+            k7 = k7 - k4 ;
+            k5 = k5 + k6;
+            /********/
+            out[24] = k7 ;      /* row 3 */
+            out[8] = k5 ;       /* row 1 */
+            out++;
+        }
+        while ((UInt)out < (UInt)dst) ;
+
+        return ;
+    }
+
+    /**************************************************************************/
+    /*  Function:   Block2x2DCT_AANwSub
+        Date:       7/31/01
+        Input:
+        Output:     out[64] ==> next block
+        Purpose:    Do subtraction for zero MV first before 2x2 DCT
+        Modified:
+    **************************************************************************/
+
+
+    Void Block2x2DCT_AANwSub(Short *out, UChar *cur, UChar *pred, Int width)
+    {
+        Short *dst;
+        register Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int round;
+        Int k12 = 0x022A02D4;
+        Int k14 = 0x018803B2;
+        Int mask;
+        Int tmp, tmp2;
+        Int abs_sum;
+        Int ColTh;
+
+        dst = out + 64 ;
+        ColTh = *dst;
+        out += 128;
+        round = 1 << (FDCT_SHIFT - 1);
+
+        do  /* fdct_nextrow */
+        {
+            /* assuming the block is word-aligned */
+            mask = 0x1FE;
+            tmp = *((Int*) cur);    /* contains 4 pixels */
+            tmp2 = *((Int*) pred); /* prediction 4 pixels */
+            k0 = tmp2 & 0xFF;
+            k1 = mask & (tmp << 1);
+            k0 = k1 - (k0 << 1);
+            k1 = (tmp2 >> 8) & 0xFF;
+            k2 = mask & (tmp >> 7);
+            k1 = k2 - (k1 << 1);
+            k2 = (tmp2 >> 16) & 0xFF;
+            k3 = mask & (tmp >> 15);
+            k2 = k3 - (k2 << 1);
+            k3 = (tmp2 >> 24) & 0xFF;
+            k4 = mask & (tmp >> 23);
+            k3 = k4 - (k3 << 1);
+            tmp = *((Int*)(cur + 4));   /* another 4 pixels */
+            tmp2 = *((Int*)(pred + 4));
+            k4 = tmp2 & 0xFF;
+            k5 = mask & (tmp << 1);
+            k4 = k5 - (k4 << 1);
+            k5 = (tmp2 >> 8) & 0xFF;
+            k6 = mask & (tmp >> 7);
+            k5 = k6 - (k5 << 1);
+            k6 = (tmp2 >> 16) & 0xFF;
+            k7 = mask & (tmp >> 15);
+            k6 = k7 - (k6 << 1);
+            k7 = (tmp2 >> 24) & 0xFF;
+            tmp = mask & (tmp >> 23);
+            k7 = tmp - (k7 << 1);
+            cur += width;
+            pred += 16;
+
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            /**********/
+            dst[0] = k0;
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            /*****************/
+            /********/
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k1 = mla392(k4, k14, round);
+            k1 = mla946(k6, k14, k1);
+
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k5 = k5 + k6;
+            /********/
+            dst[1] = k5;
+            dst += 8;
+        }
+        while (dst < out);
+        out -= 64;
+        dst = out + 2;
+        /*  Vertical Block Loop  */
+        do  /* Vertical 8xDCT loop */
+        {
+            k0 = out[0];
+            k1 = out[8];
+            k2 = out[16];
+            k3 = out[24];
+            k4 = out[32];
+            k5 = out[40];
+            k6 = out[48];
+            k7 = out[56];
+
+            abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+            if (abs_sum < ColTh)
+            {
+                out[0] = 0x7fff;
+                out++;
+                continue;
+            }
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            /**********/
+            out[0] = k0;        /* row 0 */
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            /*****************/
+            /********/
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k1 = mla392(k4, k14, round);
+            k1 = mla946(k6, k14, k1);
+
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k5 = k5 + k6;
+            /********/
+            out[8] = k5 ;       /* row 1 */
+            out++;
+        }
+        while ((UInt)out < (UInt)dst) ;
+
+        return ;
+    }
+
+    /**************************************************************************/
+    /*  Function:   BlockDCT_AANIntra
+        Date:       8/9/01
+        Input:      rec
+        Output:     out[64] ==> next block
+        Purpose:    Input directly from rec frame.
+        Modified:
+    **************************************************************************/
+
+    Void BlockDCT_AANIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
+    {
+        Short *dst;
+        Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int round;
+        Int k12 = 0x022A02D4;
+        Int k14 = 0x0188053A;
+        Int abs_sum;
+        Int mask;
+        Int *curInt, tmp;
+        Int ColTh;
+
+        OSCL_UNUSED_ARG(dummy2);
+
+        dst = out + 64 ;
+        ColTh = *dst;
+        out += 128;
+        round = 1 << (FDCT_SHIFT - 1);
+
+        do  /* fdct_nextrow */
+        {
+            mask = 0x1FE;
+            curInt = (Int*) cur;
+            tmp = curInt[0];    /* contains 4 pixels */
+            k0 = mask & (tmp << 1);
+            k1 = mask & (tmp >> 7);
+            k2 = mask & (tmp >> 15);
+            k3 = mask & (tmp >> 23);
+            tmp = curInt[1];    /* another 4 pixels */
+            k4 =  mask & (tmp << 1);
+            k5 =  mask & (tmp >> 7);
+            k6 =  mask & (tmp >> 15);
+            k7 =  mask & (tmp >> 23);
+            cur += width;
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            k1 = k0 - (k1 << 1);
+            /**********/
+            dst[0] = k0;
+            dst[4] = k1; /* col. 4 */
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            k2 = k2 + k3;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+            k0 = mla724(k12, k2, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            k2 = k0 >> FDCT_SHIFT;
+            /*****************/
+            k2 = k2 + k3;
+            k3 = (k3 << 1) - k2;
+            /********/
+            dst[2] = k2;        /* col. 2 */
+            k3 <<= 1;       /* scale up col. 6 */
+            dst[6] = k3; /* col. 6 */
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k0 = k4 - k6;
+
+            k1 = mla392(k0, k14, round);
+            k0 = mla554(k4, k12, k1);
+            k1 = mla1338(k6, k14, k1);
+
+            k4 = k0 >> FDCT_SHIFT;
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k7 = (k7 << 1) - k5;
+            k4 = k4 + k7;
+            k7 = (k7 << 1) - k4;
+            k5 = k5 + k6;
+            k4 <<= 1;       /* scale up col.5 */
+            k6 = k5 - (k6 << 1);
+            /********/
+            dst[5] = k4;    /* col. 5 */
+            k6 <<= 2;       /* scale up col. 7 */
+            dst[1] = k5;    /* col. 1 */
+            dst[7] = k6;    /* col. 7 */
+            dst[3] = k7;    /* col. 3 */
+            dst += 8;
+        }
+        while (dst < out);
+
+        out -= 64;
+        dst = out + 8;
+
+        /*  Vertical Block Loop  */
+        do  /* Vertical 8xDCT loop */
+        {
+            k0 = out[0];
+            k1 = out[8];
+            k2 = out[16];
+            k3 = out[24];
+            k4 = out[32];
+            k5 = out[40];
+            k6 = out[48];
+            k7 = out[56];
+            /* deadzone thresholding for column */
+
+            abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+            if (abs_sum < ColTh)
+            {
+                out[0] = 0x7fff;
+                out++;
+                continue;
+            }
+
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            k1 = k0 - (k1 << 1);
+            /**********/
+            out[32] = k1; /* row 4 */
+            out[0] = k0; /* row 0 */
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            k2 = k2 + k3;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+            k0 = mla724(k12, k2, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            k2 = k0 >> FDCT_SHIFT;
+            /*****************/
+            k2 = k2 + k3;
+            k3 = (k3 << 1) - k2;
+            k3 <<= 1;       /* scale up col. 6 */
+            /********/
+            out[48] = k3;   /* row 6 */
+            out[16] = k2;   /* row 2 */
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k0 = k4 - k6;
+
+            k1 = mla392(k0, k14, round);
+            k0 = mla554(k4, k12, k1);
+            k1 = mla1338(k6, k14, k1);
+
+            k4 = k0 >> FDCT_SHIFT;
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k7 = (k7 << 1) - k5;
+            k4 = k4 + k7;
+            k7 = (k7 << 1) - k4;
+            k5 = k5 + k6;
+            k4 <<= 1;       /* scale up col. 5 */
+            k6 = k5 - (k6 << 1);
+            /********/
+            out[24] = k7 ;    /* row 3 */
+            k6 <<= 2;       /* scale up col. 7 */
+            out[56] = k6 ;   /* row 7 */
+            out[8] = k5 ;    /* row 1 */
+            out[40] = k4 ;   /* row 5 */
+            out++;
+        }
+        while ((UInt)out < (UInt)dst) ;
+
+        return ;
+    }
+
+    /**************************************************************************/
+    /*  Function:   Block4x4DCT_AANIntra
+        Date:       8/9/01
+        Input:      prev
+        Output:     out[64] ==> next block
+        Purpose:    Input directly from prev frame. output 2x2 DCT
+        Modified:
+    **************************************************************************/
+
+    Void Block4x4DCT_AANIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
+    {
+        Short *dst;
+        register Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int round;
+        Int k12 = 0x022A02D4;
+        Int k14 = 0x0188053A;
+        Int mask;
+        Int *curInt, tmp;
+        Int abs_sum;
+        Int ColTh;
+
+        OSCL_UNUSED_ARG(dummy2);
+
+        dst = out + 64 ;
+        ColTh = *dst;
+        out += 128;
+        round = 1 << (FDCT_SHIFT - 1);
+
+        do  /* fdct_nextrow */
+        {
+            mask = 0x1FE;
+            curInt = (Int*) cur;
+            tmp = curInt[0];    /* contains 4 pixels */
+            k0 = mask & (tmp << 1);
+            k1 = mask & (tmp >> 7);
+            k2 = mask & (tmp >> 15);
+            k3 = mask & (tmp >> 23);
+            tmp = curInt[1];    /* another 4 pixels */
+            k4 =  mask & (tmp << 1);
+            k5 =  mask & (tmp >> 7);
+            k6 =  mask & (tmp >> 15);
+            k7 =  mask & (tmp >> 23);
+            cur += width;
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            /**********/
+            dst[0] = k0;
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            k2 = k2 + k3;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+            k0 = mla724(k12, k2, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            k2 = k0 >> FDCT_SHIFT;
+            /*****************/
+            k2 = k2 + k3;
+            /********/
+            dst[2] = k2;        /* col. 2 */
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k0 = k4 - k6;
+
+            k1 = mla392(k0, k14, round);
+            k0 = mla554(k4, k12, k1);
+            k1 = mla1338(k6, k14, k1);
+
+            k4 = k0 >> FDCT_SHIFT;
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k7 = (k7 << 1) - k5;
+            k7 = k7 - k4;
+            k5 = k5 + k6;
+            /********/
+            dst[1] = k5;        /* col. 1 */
+            dst[3] = k7;        /* col. 3 */
+            dst += 8;
+        }
+        while (dst < out);
+
+        out -= 64;
+        dst = out + 4;
+
+        /*  Vertical Block Loop  */
+        do  /* Vertical 8xDCT loop */
+        {
+            k0 = out[0];
+            k1 = out[8];
+            k2 = out[16];
+            k3 = out[24];
+            k4 = out[32];
+            k5 = out[40];
+            k6 = out[48];
+            k7 = out[56];
+
+            abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+            if (abs_sum < ColTh)
+            {
+                out[0] = 0x7fff;
+                out++;
+                continue;
+            }
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            /**********/
+            out[0] = k0;   /* row 0 */
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            k2 = k2 + k3;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+            k0 = mla724(k12, k2, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            k2 = k0 >> FDCT_SHIFT;
+            /*****************/
+            k2 = k2 + k3;
+            /********/
+            out[16] = k2;           /* row 2 */
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k0 = k4 - k6;
+
+            k1 = mla392(k0, k14, round);
+            k0 = mla554(k4, k12, k1);
+            k1 = mla1338(k6, k14, k1);
+
+            k4 = k0 >> FDCT_SHIFT;
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k7 = (k7 << 1) - k5;
+            k7 = k7 - k4 ;
+            k5 = k5 + k6;
+            /********/
+            out[24] = k7 ;      /* row 3 */
+            out[8] = k5 ;       /* row 1 */
+            out++;
+        }
+        while ((UInt)out < (UInt)dst) ;
+
+        return ;
+    }
+
+    /**************************************************************************/
+    /*  Function:   Block2x2DCT_AANIntra
+        Date:       8/9/01
+        Input:      prev
+        Output:     out[64] ==> next block
+        Purpose:    Input directly from prev frame. output 2x2 DCT
+        Modified:
+    **************************************************************************/
+
+    Void Block2x2DCT_AANIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
+    {
+        Short *dst;
+        register Int k0, k1, k2, k3, k4, k5, k6, k7;
+        Int round;
+        Int k12 = 0x022A02D4;
+        Int k14 = 0x018803B2;
+        Int mask;
+        Int *curInt, tmp;
+        Int abs_sum;
+        Int ColTh;
+
+        OSCL_UNUSED_ARG(dummy2);
+
+        dst = out + 64 ;
+        ColTh = *dst;
+        out += 128;
+        round = 1 << (FDCT_SHIFT - 1);
+
+        do  /* fdct_nextrow */
+        {
+            mask = 0x1FE;
+            curInt = (Int*) cur;
+            tmp = curInt[0];    /* contains 4 pixels */
+            k0 = mask & (tmp << 1);
+            k1 = mask & (tmp >> 7);
+            k2 = mask & (tmp >> 15);
+            k3 = mask & (tmp >> 23);
+            tmp = curInt[1];    /* another 4 pixels */
+            k4 =  mask & (tmp << 1);
+            k5 =  mask & (tmp >> 7);
+            k6 =  mask & (tmp >> 15);
+            k7 =  mask & (tmp >> 23);
+            cur += width;
+
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            /**********/
+            dst[0] = k0;
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            /*****************/
+            /********/
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k1 = mla392(k4, k14, round);
+            k1 = mla946(k6, k14, k1);
+
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k5 = k5 + k6;
+            /********/
+            dst[1] = k5;
+            dst += 8;
+        }
+        while (dst < out);
+        out -= 64;
+        dst = out + 2;
+        /*  Vertical Block Loop  */
+        do  /* Vertical 8xDCT loop */
+        {
+            k0 = out[0];
+            k1 = out[8];
+            k2 = out[16];
+            k3 = out[24];
+            k4 = out[32];
+            k5 = out[40];
+            k6 = out[48];
+            k7 = out[56];
+
+            abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+            if (abs_sum < ColTh)
+            {
+                out[0] = 0x7fff;
+                out++;
+                continue;
+            }
+            /* fdct_1 */
+            k0 = k0 + k7;
+            k7 = k0 - (k7 << 1);
+            k1 = k1 + k6;
+            k6 = k1 - (k6 << 1);
+            k2 = k2 + k5;
+            k5 = k2 - (k5 << 1);
+            k3 = k3 + k4;
+            k4 = k3 - (k4 << 1);
+
+            k0 = k0 + k3;
+            k3 = k0 - (k3 << 1);
+            k1 = k1 + k2;
+            k2 = k1 - (k2 << 1);
+
+            k0 = k0 + k1;
+            /**********/
+            out[0] = k0;        /* row 0 */
+            /* fdct_2 */
+            k4 = k4 + k5;
+            k5 = k5 + k6;
+            k6 = k6 + k7;
+            /* MUL2C k2,k5,724,FDCT_SHIFT */
+            /* k0, k1 become scratch */
+            /* assume FAST MULTIPLY */
+            k1 = mla724(k12, k5, round);
+
+            k5 = k1 >> FDCT_SHIFT;
+            /*****************/
+            /********/
+            /* fdct_3 */
+            /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+            /* assume FAST MULTIPLY */
+            /* k0, k1 are output */
+            k1 = mla392(k4, k14, round);
+            k1 = mla946(k6, k14, k1);
+
+            k6 = k1 >> FDCT_SHIFT;
+            /***********************/
+            k5 = k5 + k7;
+            k5 = k5 + k6;
+            /********/
+            out[8] = k5 ;       /* row 1 */
+            out++;
+        }
+        while ((UInt)out < (UInt)dst) ;
+
+        return ;
+    }
+    /**************************************************************************/
+    /*  Function:   Block1x1DCTwSub
+        Date:       8/9/01
+        Input:      block
+        Output:     y
+        Purpose:    Compute DC value only
+        Modified:
+    **************************************************************************/
+    void Block1x1DCTwSub(Short *out, UChar *cur, UChar *pred, Int width)
+    {
+        UChar *end;
+        Int temp = 0;
+        Int offset2;
+
+        offset2 = width - 8;
+        end = pred + (16 << 3);
+        do
+        {
+            temp += (*cur++ - *pred++);
+            temp += (*cur++ - *pred++);
+            temp += (*cur++ - *pred++);
+            temp += (*cur++ - *pred++);
+            temp += (*cur++ - *pred++);
+            temp += (*cur++ - *pred++);
+            temp += (*cur++ - *pred++);
+            temp += (*cur++ - *pred++);
+            cur += offset2;
+            pred += 8;
+        }
+        while (pred < end) ;
+
+        out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0;
+        out[0] = temp >> 3;
+
+        return ;
+    }
+
+    /**************************************************************************/
+    /*  Function:   Block1x1DCTIntra
+        Date:       8/9/01
+        Input:      prev
+        Output:     out
+        Purpose:    Compute DC value only
+        Modified:
+    **************************************************************************/
+    void Block1x1DCTIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
+    {
+        UChar *end;
+        Int temp = 0;
+        ULong word;
+
+        OSCL_UNUSED_ARG(dummy2);
+
+        end = cur + (width << 3);
+        do
+        {
+            word = *((ULong*)cur);
+            temp += (word >> 24);
+            temp += ((word >> 16) & 0xFF);
+            temp += ((word >> 8) & 0xFF);
+            temp += (word & 0xFF);
+
+            word = *((ULong*)(cur + 4));
+            temp += (word >> 24);
+            temp += ((word >> 16) & 0xFF);
+            temp += ((word >> 8) & 0xFF);
+            temp += (word & 0xFF);
+
+            cur += width;
+        }
+        while (cur < end) ;
+
+        out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0;
+        out[0] = temp >> 3;
+
+        return ;
+    }
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.h b/media/libstagefright/codecs/m4v_h263/enc/src/dct.h
new file mode 100644
index 0000000..3dceb66
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct.h
@@ -0,0 +1,191 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _DCT_H_
+#define _DCT_H_
+
+const static Int ColThInter[32] = {0, 0x1C, 0x4C, 0x6C, 0x9C, 0xBC, 0xEC, 0x10C,
+                                   0x13C, 0x15C, 0x18C, 0x1AC, 0x1DC, 0x1FC, 0x22C, 0x24C,
+                                   0x27C, 0x29C, 0x2CC, 0x2EC, 0x31C, 0x33C, 0x36C, 0x38C,
+                                   0x3BC, 0x3DC, 0x40C, 0x42C, 0x45C, 0x47C, 0x4AC, 0x4CC
+                                  };
+
+const static Int ColThIntra[32] = {0, 0x1C, 0x3C, 0x5C, 0x7C, 0x9C, 0xBC, 0xDC,
+                                   0xFC, 0x11C, 0x13C, 0x15C, 0x17C, 0x19C, 0x1BC, 0x1DC,
+                                   0x1FC, 0x21C, 0x23C, 0x25C, 0x27C, 0x29C, 0x2BC, 0x2DC,
+                                   0x2FC, 0x31C, 0x33C, 0x35C, 0x37C, 0x39C, 0x3BC, 0x3DC
+                                  };
+
+/******************************************************/
+/********** IDCT part **************************/
+const static unsigned char imask[8] = {128, 64, 32, 16, 8, 4, 2, 1};
+const static unsigned char mask[8] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe};
+
+#define W1 2841                 /* 2048*sqrt(2)*cos(1*pi/16) */
+#define W2 2676                 /* 2048*sqrt(2)*cos(2*pi/16) */
+#define W3 2408                 /* 2048*sqrt(2)*cos(3*pi/16) */
+#define W5 1609                 /* 2048*sqrt(2)*cos(5*pi/16) */
+#define W6 1108                 /* 2048*sqrt(2)*cos(6*pi/16) */
+#define W7 565                  /* 2048*sqrt(2)*cos(7*pi/16) */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /* Reduced input IDCT */
+    void idct_col0(Short *blk);
+    void idct_col1(Short *blk);
+    void idct_col2(Short *blk);
+    void idct_col3(Short *blk);
+    void idct_col4(Short *blk);
+    void idct_col0x40(Short *blk);
+    void idct_col0x20(Short *blk);
+    void idct_col0x10(Short *blk);
+
+    void idct_rowInter(Short *srce, UChar *rec, Int lx);
+    void idct_row0Inter(Short *blk, UChar *rec, Int lx);
+    void idct_row1Inter(Short *blk, UChar *rec, Int lx);
+    void idct_row2Inter(Short *blk, UChar *rec, Int lx);
+    void idct_row3Inter(Short *blk, UChar *rec, Int lx);
+    void idct_row4Inter(Short *blk, UChar *rec, Int lx);
+    void idct_row0x40Inter(Short *blk, UChar *rec, Int lx);
+    void idct_row0x20Inter(Short *blk, UChar *rec, Int lx);
+    void idct_row0x10Inter(Short *blk, UChar *rec, Int lx);
+    void idct_row0xCCInter(Short *blk, UChar *rec, Int lx);
+    void idct_rowIntra(Short *srce, UChar *rec, Int lx);
+    void idct_row0Intra(Short *blk, UChar *rec, Int lx);
+    void idct_row1Intra(Short *blk, UChar *rec, Int lx);
+    void idct_row2Intra(Short *blk, UChar *rec, Int lx);
+    void idct_row3Intra(Short *blk, UChar *rec, Int lx);
+    void idct_row4Intra(Short *blk, UChar *rec, Int lx);
+    void idct_row0x40Intra(Short *blk, UChar *rec, Int lx);
+    void idct_row0x20Intra(Short *blk, UChar *rec, Int lx);
+    void idct_row0x10Intra(Short *blk, UChar *rec, Int lx);
+    void idct_row0xCCIntra(Short *blk, UChar *rec, Int lx);
+    void idct_rowzmv(Short *srce, UChar *rec, UChar *prev, Int lx);
+    void idct_row0zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+    void idct_row1zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+    void idct_row2zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+    void idct_row3zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+    void idct_row4zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+    void idct_row0x40zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+    void idct_row0x20zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+    void idct_row0x10zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+    void idct_row0xCCzmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Look-up table mapping to RIDCT from bitmap */
+#ifdef SMALL_DCT
+
+static void (*const idctcolVCA[16])(Short*) =
+{
+    &idct_col0, &idct_col4, &idct_col3, &idct_col4,
+    &idct_col2, &idct_col4, &idct_col3, &idct_col4,
+    &idct_col1, &idct_col4, &idct_col3, &idct_col4,
+    &idct_col2, &idct_col4, &idct_col3, &idct_col4
+};
+
+static void (*const idctrowVCAInter[16])(Short*, UChar*, Int) =
+{
+    &idct_row0Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+    &idct_row2Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+    &idct_row1Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+    &idct_row2Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter
+};
+
+static void (*const idctrowVCAzmv[16])(Short*, UChar*, UChar*, Int) =
+{
+    &idct_row0zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+    &idct_row2zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+    &idct_row1zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+    &idct_row2zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv
+};
+
+
+static void (*const idctrowVCAIntra[16])(Short*, UChar*, Int) =
+{
+    &idct_row0Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+    &idct_row2Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+    &idct_row1Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+    &idct_row2Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra
+};
+
+#else /* SMALL_DCT */
+
+static void (*const idctcolVCA[16])(Short*) =
+{
+    &idct_col0, &idct_col0x10, &idct_col0x20, &idct_col4,
+    &idct_col0x40, &idct_col4, &idct_col3, &idct_col4,
+    &idct_col1, &idct_col4, &idct_col3, &idct_col4,
+    &idct_col2, &idct_col4, &idct_col3, &idct_col4
+};
+
+static void (*const idctrowVCAInter[16])(Short*, UChar*, Int) =
+{
+    &idct_row0Inter, &idct_row0x10Inter, &idct_row0x20Inter, &idct_row4Inter,
+    &idct_row0x40Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+    &idct_row1Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+    &idct_row2Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter
+};
+
+static void (*const idctrowVCAzmv[16])(Short*, UChar*, UChar*, Int) =
+{
+    &idct_row0zmv, &idct_row0x10zmv, &idct_row0x20zmv, &idct_row4zmv,
+    &idct_row0x40zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+    &idct_row1zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+    &idct_row2zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv
+};
+
+static void (*const idctrowVCAIntra[16])(Short*, UChar*, Int) =
+{
+    &idct_row0Intra, &idct_row0x10Intra, &idct_row0x20Intra, &idct_row4Intra,
+    &idct_row0x40Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+    &idct_row1Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+    &idct_row2Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra
+};
+
+#endif /* SMALL_DCT */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    /* part in AppVCA_dct.c */
+//void Block1x1DCTzmv (Short *out,UChar *prev,UChar *cur,UChar *rec,Int lx,Int chroma);
+    void Block1x1DCTwSub(Short *out, UChar *cur, UChar *prev, Int pitch_chroma);
+    void Block1x1DCTIntra(Short *out, UChar *cur, UChar *dummy1, Int pitch_chroma);
+    /* This part is in dct_aan.c */
+    Void BlockDCT_AANwSub(Short *out, UChar *cur, UChar *prev, Int pitch_chroma);
+    Void Block4x4DCT_AANwSub(Short *out, UChar *cur, UChar *prev, Int pitch_chroma);
+    Void Block2x2DCT_AANwSub(Short *out, UChar *cur, UChar *prev, Int pitch_chroma);
+//Void BlockDCT_AANzmv(Short *out,UChar *prev,UChar *cur,UChar *rec,Int ColTh,Int lx,Int chroma);
+//Void Block4x4DCT_AANzmv(Short *out,UChar *prev,UChar *cur,UChar *rec,Int ColTh,Int lx,Int chroma);
+//Void Block2x2DCT_AANzmv(Short *out,UChar *prev,UChar *cur,UChar *rec,Int ColTh,Int lx,Int chroma);
+    Void BlockDCT_AANIntra(Short *out, UChar *cur, UChar *dummy1, Int pitch_chroma);
+    Void Block4x4DCT_AANIntra(Short *out, UChar *cur, UChar *dummy1, Int pitch_chroma);
+    Void Block2x2DCT_AANIntra(Short *out, UChar *cur, UChar *dummy1, Int pitch_chroma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_DCT_H_
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h
new file mode 100644
index 0000000..f795bd9
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h
@@ -0,0 +1,395 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*  Filename: dct_inline.h                                                      */
+/*  Description: Implementation for in-line functions used in dct.cpp           */
+/*  Modified:                                                                   */
+/*********************************************************************************/
+#ifndef _DCT_INLINE_H_
+#define _DCT_INLINE_H_
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4)
+
+__inline int32 mla724(int32 op1, int32 op2, int32 op3)
+{
+    int32 out;
+
+    OSCL_UNUSED_ARG(op1);
+
+    out = op2 * 724 + op3; /* op1 is not used here */
+
+    return out;
+}
+
+__inline int32 mla392(int32 k0, int32 k14, int32 round)
+{
+    int32 k1;
+
+    OSCL_UNUSED_ARG(k14);
+
+    k1 = k0 * 392 + round;
+
+    return k1;
+}
+
+__inline int32 mla554(int32 k4, int32 k12, int32 k1)
+{
+    int32 k0;
+
+    OSCL_UNUSED_ARG(k12);
+
+    k0 = k4 * 554 + k1;
+
+    return k0;
+}
+
+__inline int32 mla1338(int32 k6, int32 k14, int32 k1)
+{
+    int32 out;
+
+    OSCL_UNUSED_ARG(k14);
+
+    out = k6 * 1338 + k1;
+
+    return out;
+}
+
+__inline int32 mla946(int32 k6, int32 k14, int32 k1)
+{
+    int32 out;
+
+    OSCL_UNUSED_ARG(k14);
+
+    out = k6 * 946 + k1;
+
+    return out;
+}
+
+__inline int32 sum_abs(int32 k0, int32 k1, int32 k2, int32 k3,
+                       int32 k4, int32 k5, int32 k6, int32 k7)
+{
+    int32 carry, abs_sum;
+
+    carry = k0 >> 31;
+    abs_sum = (k0 ^ carry);
+    carry = k1 >> 31;
+    abs_sum += (k1 ^ carry) - carry;
+    carry = k2 >> 31;
+    abs_sum += (k2 ^ carry) - carry;
+    carry = k3 >> 31;
+    abs_sum += (k3 ^ carry) - carry;
+    carry = k4 >> 31;
+    abs_sum += (k4 ^ carry) - carry;
+    carry = k5 >> 31;
+    abs_sum += (k5 ^ carry) - carry;
+    carry = k6 >> 31;
+    abs_sum += (k6 ^ carry) - carry;
+    carry = k7 >> 31;
+    abs_sum += (k7 ^ carry) - carry;
+
+    return abs_sum;
+}
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+#if defined(__TARGET_ARCH_5TE)
+
+__inline int32 mla724(int32 op1, int32 op2, int32 op3)
+{
+    int32 out;
+
+    __asm
+    {
+        smlabb out, op1, op2, op3
+    }
+
+    return out;
+}
+
+__inline int32 mla392(int32 k0, int32 k14, int32 round)
+{
+    int32 k1;
+
+    __asm
+    {
+        smlabt k1, k0, k14, round
+    }
+
+    return k1;
+}
+
+__inline int32 mla554(int32 k4, int32 k12, int32 k1)
+{
+    int32 k0;
+
+    __asm
+    {
+        smlabt k0, k4, k12, k1
+    }
+
+    return k0;
+}
+
+__inline int32 mla1338(int32 k6, int32 k14, int32 k1)
+{
+    int32 out;
+
+    __asm
+    {
+        smlabb out, k6, k14, k1
+    }
+
+    return out;
+}
+
+__inline int32 mla946(int32 k6, int32 k14, int32 k1)
+{
+    int32 out;
+
+    __asm
+    {
+        smlabb out, k6, k14, k1
+    }
+
+    return out;
+}
+
+#else // not ARM5TE
+
+
+__inline int32 mla724(int32 op1, int32 op2, int32 op3)
+{
+    int32 out;
+
+    __asm
+    {
+        and out, op2, #0xFFFF
+        mla out, op1, out, op3
+    }
+
+    return out;
+}
+
+__inline int32 mla392(int32 k0, int32 k14, int32 round)
+{
+    int32 k1;
+
+    __asm
+    {
+        mov k1, k14, asr #16
+        mla k1, k0, k1, round
+    }
+
+    return k1;
+}
+
+__inline int32 mla554(int32 k4, int32 k12, int32 k1)
+{
+    int32 k0;
+
+    __asm
+    {
+        mov  k0, k12, asr #16
+        mla k0, k4, k0, k1
+    }
+
+    return k0;
+}
+
+__inline int32 mla1338(int32 k6, int32 k14, int32 k1)
+{
+    int32 out;
+
+    __asm
+    {
+        and out, k14, 0xFFFF
+        mla out, k6, out, k1
+    }
+
+    return out;
+}
+
+__inline int32 mla946(int32 k6, int32 k14, int32 k1)
+{
+    int32 out;
+
+    __asm
+    {
+        and out, k14, 0xFFFF
+        mla out, k6, out, k1
+    }
+
+    return out;
+}
+
+#endif
+
+__inline int32 sum_abs(int32 k0, int32 k1, int32 k2, int32 k3,
+                       int32 k4, int32 k5, int32 k6, int32 k7)
+{
+    int32 carry, abs_sum;
+    __asm
+    {
+        eor     carry, k0, k0, asr #31 ;
+        eors    abs_sum, k1, k1, asr #31 ;
+        adc     abs_sum, abs_sum, carry ;
+        eors    carry,  k2, k2, asr #31 ;
+        adc     abs_sum, abs_sum, carry ;
+        eors    carry,  k3, k3, asr #31 ;
+        adc     abs_sum, abs_sum, carry ;
+        eors    carry,  k4, k4, asr #31 ;
+        adc     abs_sum, abs_sum, carry ;
+        eors    carry,  k5, k5, asr #31 ;
+        adc     abs_sum, abs_sum, carry ;
+        eors    carry,  k6, k6, asr #31 ;
+        adc     abs_sum, abs_sum, carry ;
+        eors    carry,  k7, k7, asr #31 ;
+        adc     abs_sum, abs_sum, carry ;
+    }
+
+    return abs_sum;
+}
+
+#elif ( defined(PV_ARM_GCC_V5) || defined(PV_ARM_GCC_V4) )  /* ARM GNU COMPILER  */
+
+__inline int32 mla724(int32 op1, int32 op2, int32 op3)
+{
+    register int32 out;
+    register int32 aa = (int32)op1;
+    register int32 bb = (int32)op2;
+    register int32 cc = (int32)op3;
+
+    asm volatile("smlabb %0, %1, %2, %3"
+             : "=&r"(out)
+                         : "r"(aa),
+                         "r"(bb),
+                         "r"(cc));
+    return out;
+}
+
+
+__inline int32 mla392(int32 k0, int32 k14, int32 round)
+{
+    register int32 out;
+    register int32 aa = (int32)k0;
+    register int32 bb = (int32)k14;
+    register int32 cc = (int32)round;
+
+    asm volatile("smlabt %0, %1, %2, %3"
+             : "=&r"(out)
+                         : "r"(aa),
+                         "r"(bb),
+                         "r"(cc));
+
+    return out;
+}
+
+__inline int32 mla554(int32 k4, int32 k12, int32 k1)
+{
+    register int32 out;
+    register int32 aa = (int32)k4;
+    register int32 bb = (int32)k12;
+    register int32 cc = (int32)k1;
+
+    asm volatile("smlabt %0, %1, %2, %3"
+             : "=&r"(out)
+                         : "r"(aa),
+                         "r"(bb),
+                         "r"(cc));
+
+    return out;
+}
+
+__inline int32 mla1338(int32 k6, int32 k14, int32 k1)
+{
+    register int32 out;
+    register int32 aa = (int32)k6;
+    register int32 bb = (int32)k14;
+    register int32 cc = (int32)k1;
+
+    asm volatile("smlabb %0, %1, %2, %3"
+             : "=&r"(out)
+                         : "r"(aa),
+                         "r"(bb),
+                         "r"(cc));
+    return out;
+}
+
+__inline int32 mla946(int32 k6, int32 k14, int32 k1)
+{
+    register int32 out;
+    register int32 aa = (int32)k6;
+    register int32 bb = (int32)k14;
+    register int32 cc = (int32)k1;
+
+    asm volatile("smlabb %0, %1, %2, %3"
+             : "=&r"(out)
+                         : "r"(aa),
+                         "r"(bb),
+                         "r"(cc));
+    return out;
+}
+
+__inline int32 sum_abs(int32 k0, int32 k1, int32 k2, int32 k3,
+                       int32 k4, int32 k5, int32 k6, int32 k7)
+{
+    register int32 carry;
+    register int32 abs_sum;
+    register int32 aa = (int32)k0;
+    register int32 bb = (int32)k1;
+    register int32 cc = (int32)k2;
+    register int32 dd = (int32)k3;
+    register int32 ee = (int32)k4;
+    register int32 ff = (int32)k5;
+    register int32 gg = (int32)k6;
+    register int32 hh = (int32)k7;
+
+    asm volatile("eor  %0, %2, %2, asr #31\n\t"
+                 "eors %1, %3, %3, asr #31\n\t"
+                 "adc  %1, %1, %0\n\t"
+                 "eors %0, %4, %4, asr #31\n\t"
+                 "adc  %1, %1, %0\n\t"
+                 "eors %0, %5, %5, asr #31\n\t"
+                 "adc  %1, %1, %0\n\t"
+                 "eors %0, %6, %6, asr #31\n\t"
+                 "adc  %1, %1, %0\n\t"
+                 "eors %0, %7, %7, asr #31\n\t"
+                 "adc  %1, %1, %0\n\t"
+                 "eors %0, %8, %8, asr #31\n\t"
+                 "adc  %1, %1, %0\n\t"
+                 "eors %0, %9, %9, asr #31\n\t"
+                 "adc  %1, %1, %0\n\t"
+
+             : "=&r"(carry),
+                 "=&r"(abs_sum):
+                         "r"(aa),
+                         "r"(bb),
+                         "r"(cc),
+                         "r"(dd),
+                         "r"(ee),
+                         "r"(ff),
+                         "r"(gg),
+                         "r"(hh));
+
+    return abs_sum;
+}
+
+#endif // Diff. OS
+
+#endif //_DCT_INLINE_H_
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp
new file mode 100644
index 0000000..6fd41c3
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp
@@ -0,0 +1,622 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "mp4enc_lib.h"
+#include "dct.h"
+#include "m4venc_oscl.h"
+
+/* ======================================================================== */
+/*  Function : CodeMB_H263( )                                               */
+/*  Date     : 8/15/2001                                                    */
+/*  Purpose  : Perform residue calc (only zero MV), DCT, H263 Quant/Dequant,*/
+/*              IDCT and motion compensation.Modified from FastCodeMB()     */
+/*  Input    :                                                              */
+/*      video       Video encoder data structure                            */
+/*      function    Approximate DCT function, scaling and threshold         */
+/*      ncoefblck   Array for last nonzero coeff for speedup in VlcEncode   */
+/*      QP      Combined offset from the origin to the current          */
+/*                  macroblock  and QP  for current MB.                     */
+/*    Output     :                                                          */
+/*      video->outputMB     Quantized DCT coefficients.                     */
+/*      currVop->yChan,uChan,vChan  Reconstructed pixels                    */
+/*                                                                          */
+/*  Return   :   PV_STATUS                                                  */
+/*  Modified :                                                              */
+/*           2/26/01
+            -modified threshold based on correlation coeff 0.75 only for mode H.263
+            -ncoefblck[] as input,  to keep position of last non-zero coeff*/
+/*           8/10/01
+            -modified threshold based on correlation coeff 0.5
+            -used column threshold to speedup column DCT.
+            -used bitmap zigzag to speedup RunLevel().                      */
+/* ======================================================================== */
+
+PV_STATUS CodeMB_H263(VideoEncData *video, approxDCT *function, Int QP, Int ncoefblck[])
+{
+    Int sad, k, CBP, mbnum = video->mbnum;
+    Short *output, *dataBlock;
+    UChar Mode = video->headerInfo.Mode[mbnum];
+    UChar *bitmapcol, *bitmaprow = video->bitmaprow;
+    UInt  *bitmapzz ;
+    UChar shortHeader = video->vol[video->currLayer]->shortVideoHeader;
+    Int dc_scaler = 8;
+    Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+    struct QPstruct QuantParam;
+    Int dctMode, DctTh1;
+    Int ColTh;
+    Int(*BlockQuantDequantH263)(Short *, Short *, struct QPstruct *,
+                                UChar[], UChar *, UInt *, Int, Int, Int, UChar);
+    Int(*BlockQuantDequantH263DC)(Short *, Short *, struct QPstruct *,
+                                  UChar *, UInt *, Int, UChar);
+    void (*BlockDCT1x1)(Short *, UChar *, UChar *, Int);
+    void (*BlockDCT2x2)(Short *, UChar *, UChar *, Int);
+    void (*BlockDCT4x4)(Short *, UChar *, UChar *, Int);
+    void (*BlockDCT8x8)(Short *, UChar *, UChar *, Int);
+
+    /* motion comp. related var. */
+    Vop *currVop = video->currVop;
+    VideoEncFrameIO *inputFrame = video->input;
+    Int ind_x = video->outputMB->mb_x;
+    Int ind_y = video->outputMB->mb_y;
+    Int lx = currVop->pitch;
+    Int width = currVop->width;
+    UChar *rec, *input, *pred;
+    Int offset = QP >> 5;  /* QP is combined offset and QP */
+    Int offsetc = (offset >> 2) + (ind_x << 2); /* offset for chrom */
+    /*****************************/
+
+    OSCL_UNUSED_ARG(function);
+
+    output = video->outputMB->block[0];
+    CBP = 0;
+    QP = QP & 0x1F;
+//  M4VENC_MEMSET(output,0,(sizeof(Short)<<6)*6); /* reset quantized coeff. to zero , 7/24/01*/
+
+    QuantParam.QPx2 = QP << 1;
+    QuantParam.QP = QP;
+    QuantParam.QPdiv2 = QP >> 1;
+    QuantParam.QPx2plus = QuantParam.QPx2 + QuantParam.QPdiv2;
+    QuantParam.Addition = QP - 1 + (QP & 0x1);
+
+    if (intra)
+    {
+        BlockDCT1x1 = &Block1x1DCTIntra;
+        BlockDCT2x2 = &Block2x2DCT_AANIntra;
+        BlockDCT4x4 = &Block4x4DCT_AANIntra;
+        BlockDCT8x8 = &BlockDCT_AANIntra;
+        BlockQuantDequantH263 = &BlockQuantDequantH263Intra;
+        BlockQuantDequantH263DC = &BlockQuantDequantH263DCIntra;
+        if (shortHeader)
+        {
+            dc_scaler = 8;
+        }
+        else
+        {
+            dc_scaler = cal_dc_scalerENC(QP, 1); /* luminance blocks */
+        }
+        DctTh1 = (Int)(dc_scaler * 3);//*1.829
+        ColTh = ColThIntra[QP];
+    }
+    else
+    {
+        BlockDCT1x1 = &Block1x1DCTwSub;
+        BlockDCT2x2 = &Block2x2DCT_AANwSub;
+        BlockDCT4x4 = &Block4x4DCT_AANwSub;
+        BlockDCT8x8 = &BlockDCT_AANwSub;
+
+        BlockQuantDequantH263 = &BlockQuantDequantH263Inter;
+        BlockQuantDequantH263DC = &BlockQuantDequantH263DCInter;
+        ColTh = ColThInter[QP];
+        DctTh1 = (Int)(16 * QP);  //9*QP;
+    }
+
+    rec = currVop->yChan + offset;
+    input = inputFrame->yChan + offset;
+    if (lx != width) input -= (ind_y << 9);  /* non-padded offset */
+
+    dataBlock = video->dataBlock;
+    pred = video->predictedMB;
+
+    for (k = 0; k < 6; k++)
+    {
+        CBP <<= 1;
+        bitmapcol = video->bitmapcol[k];
+        bitmapzz = video->bitmapzz[k];  /*  7/30/01 */
+        if (k < 4)
+        {
+            sad = video->mot[mbnum][k+1].sad;
+            if (k&1)
+            {
+                rec += 8;
+                input += 8;
+            }
+            else if (k == 2)
+            {
+                dctMode = ((width << 3) - 8);
+                input += dctMode;
+                dctMode = ((lx << 3) - 8);
+                rec += dctMode;
+            }
+        }
+        else
+        {
+            if (k == 4)
+            {
+                rec = currVop->uChan + offsetc;
+                input = inputFrame->uChan + offsetc;
+                if (lx != width) input -= (ind_y << 7);
+                lx >>= 1;
+                width >>= 1;
+                if (intra)
+                {
+                    sad = getBlockSum(input, width);
+                    if (shortHeader)
+                        dc_scaler = 8;
+                    else
+                    {
+                        dc_scaler = cal_dc_scalerENC(QP, 2); /* chrominance blocks */
+                    }
+                    DctTh1 = (Int)(dc_scaler * 3);//*1.829
+                }
+                else
+                    sad = Sad8x8(input, pred, width);
+            }
+            else
+            {
+                rec = currVop->vChan + offsetc;
+                input = inputFrame->vChan + offsetc;
+                if (lx != width) input -= (ind_y << 7);
+                if (intra)
+                {
+                    sad = getBlockSum(input, width);
+                }
+                else
+                    sad = Sad8x8(input, pred, width);
+            }
+        }
+
+        if (sad < DctTh1 && !(shortHeader && intra)) /* all-zero */
+        {                       /* For shortHeader intra block, DC value cannot be zero */
+            dctMode = 0;
+            CBP |= 0;
+            ncoefblck[k] = 0;
+        }
+        else if (sad < 18*QP/*(QP<<4)*/) /* DC-only */
+        {
+            dctMode = 1;
+            BlockDCT1x1(dataBlock, input, pred, width);
+
+            CBP |= (*BlockQuantDequantH263DC)(dataBlock, output, &QuantParam,
+                                              bitmaprow + k, bitmapzz, dc_scaler, shortHeader);
+            ncoefblck[k] = 1;
+        }
+        else
+        {
+
+            dataBlock[64] = ColTh;
+
+            if (sad < 22*QP/*(QP<<4)+(QP<<1)*/)  /* 2x2 DCT */
+            {
+                dctMode = 2;
+                BlockDCT2x2(dataBlock, input, pred, width);
+                ncoefblck[k] = 6;
+            }
+            else if (sad < (QP << 5)) /* 4x4 DCT */
+            {
+                dctMode = 4;
+                BlockDCT4x4(dataBlock, input, pred, width);
+                ncoefblck[k] = 26;
+            }
+            else /* Full-DCT */
+            {
+                dctMode = 8;
+                BlockDCT8x8(dataBlock, input, pred, width);
+                ncoefblck[k] = 64;
+            }
+
+            CBP |= (*BlockQuantDequantH263)(dataBlock, output, &QuantParam,
+                                            bitmapcol, bitmaprow + k, bitmapzz, dctMode, k, dc_scaler, shortHeader);
+        }
+        BlockIDCTMotionComp(dataBlock, bitmapcol, bitmaprow[k], dctMode, rec, pred, (lx << 1) | intra);
+        output += 64;
+        if (!(k&1))
+        {
+            pred += 8;
+        }
+        else
+        {
+            pred += 120;
+        }
+    }
+
+    video->headerInfo.CBP[mbnum] = CBP; /*  5/18/2001 */
+    return PV_SUCCESS;
+}
+
+#ifndef NO_MPEG_QUANT
+/* ======================================================================== */
+/*  Function : CodeMB_MPEG( )                                               */
+/*  Date     : 8/15/2001                                                    */
+/*  Purpose  : Perform residue calc (only zero MV), DCT, MPEG Quant/Dequant,*/
+/*              IDCT and motion compensation.Modified from FastCodeMB()     */
+/*  Input    :                                                              */
+/*      video       Video encoder data structure                            */
+/*      function    Approximate DCT function, scaling and threshold         */
+/*      ncoefblck   Array for last nonzero coeff for speedup in VlcEncode   */
+/*      QP      Combined offset from the origin to the current          */
+/*                  macroblock  and QP  for current MB.                     */
+/*    Output     :                                                          */
+/*      video->outputMB     Quantized DCT coefficients.                     */
+/*      currVop->yChan,uChan,vChan  Reconstructed pixels                    */
+/*                                                                          */
+/*  Return   :   PV_STATUS                                                  */
+/*  Modified :                                                              */
+/*           2/26/01
+            -modified threshold based on correlation coeff 0.75 only for mode H.263
+            -ncoefblck[] as input, keep position of last non-zero coeff*/
+/*           8/10/01
+            -modified threshold based on correlation coeff 0.5
+            -used column threshold to speedup column DCT.
+            -used bitmap zigzag to speedup RunLevel().                      */
+/* ======================================================================== */
+
+PV_STATUS CodeMB_MPEG(VideoEncData *video, approxDCT *function, Int QP, Int ncoefblck[])
+{
+    Int sad, k, CBP, mbnum = video->mbnum;
+    Short *output, *dataBlock;
+    UChar Mode = video->headerInfo.Mode[mbnum];
+    UChar *bitmapcol, *bitmaprow = video->bitmaprow;
+    UInt  *bitmapzz ;
+    Int dc_scaler = 8;
+    Vol *currVol = video->vol[video->currLayer];
+    Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+    Int *qmat;
+    Int dctMode, DctTh1, DctTh2, DctTh3, DctTh4;
+    Int ColTh;
+
+    Int(*BlockQuantDequantMPEG)(Short *, Short *, Int, Int *,
+                                UChar [], UChar *, UInt *, Int,  Int, Int);
+    Int(*BlockQuantDequantMPEGDC)(Short *, Short *, Int, Int *,
+                                  UChar [], UChar *, UInt *, Int);
+
+    void (*BlockDCT1x1)(Short *, UChar *, UChar *, Int);
+    void (*BlockDCT2x2)(Short *, UChar *, UChar *, Int);
+    void (*BlockDCT4x4)(Short *, UChar *, UChar *, Int);
+    void (*BlockDCT8x8)(Short *, UChar *, UChar *, Int);
+
+    /* motion comp. related var. */
+    Vop *currVop = video->currVop;
+    VideoEncFrameIO *inputFrame = video->input;
+    Int ind_x = video->outputMB->mb_x;
+    Int ind_y = video->outputMB->mb_y;
+    Int lx = currVop->pitch;
+    Int width = currVop->width;
+    UChar *rec, *input, *pred;
+    Int offset = QP >> 5;
+    Int offsetc = (offset >> 2) + (ind_x << 2); /* offset for chrom */
+    /*****************************/
+
+    OSCL_UNUSED_ARG(function);
+
+    output = video->outputMB->block[0];
+    CBP = 0;
+    QP = QP & 0x1F;
+//  M4VENC_MEMSET(output,0,(sizeof(Short)<<6)*6); /* reset quantized coeff. to zero ,  7/24/01*/
+
+    if (intra)
+    {
+        BlockDCT1x1 = &Block1x1DCTIntra;
+        BlockDCT2x2 = &Block2x2DCT_AANIntra;
+        BlockDCT4x4 = &Block4x4DCT_AANIntra;
+        BlockDCT8x8 = &BlockDCT_AANIntra;
+
+        BlockQuantDequantMPEG = &BlockQuantDequantMPEGIntra;
+        BlockQuantDequantMPEGDC = &BlockQuantDequantMPEGDCIntra;
+        dc_scaler = cal_dc_scalerENC(QP, 1); /* luminance blocks */
+        qmat = currVol->iqmat;
+        DctTh1 = (Int)(3 * dc_scaler);//2*dc_scaler);
+        DctTh2 = (Int)((1.25 * QP - 1) * qmat[1] * 0.45);//0.567);//0.567);
+        DctTh3 = (Int)((1.25 * QP - 1) * qmat[2] * 0.55);//1.162); /*  8/2/2001 */
+        DctTh4 = (Int)((1.25 * QP - 1) * qmat[32] * 0.8);//1.7583);//0.7942);
+        ColTh = ColThIntra[QP];
+    }
+    else
+    {
+        BlockDCT1x1 = &Block1x1DCTwSub;
+        BlockDCT2x2 = &Block2x2DCT_AANwSub;
+        BlockDCT4x4 = &Block4x4DCT_AANwSub;
+        BlockDCT8x8 = &BlockDCT_AANwSub;
+
+        BlockQuantDequantMPEG = &BlockQuantDequantMPEGInter;
+        BlockQuantDequantMPEGDC = &BlockQuantDequantMPEGDCInter;
+        qmat = currVol->niqmat;
+        DctTh1 = (Int)(((QP << 1) - 0.5) * qmat[0] * 0.4);//0.2286);//0.3062);
+        DctTh2 = (Int)(((QP << 1) - 0.5) * qmat[1] * 0.45);//0.567);//0.4);
+        DctTh3 = (Int)(((QP << 1) - 0.5) * qmat[2] * 0.55);//1.162); /*  8/2/2001 */
+        DctTh4 = (Int)(((QP << 1) - 0.5) * qmat[32] * 0.8);//1.7583);//0.7942);
+        ColTh = ColThInter[QP];
+    }// get qmat, DctTh1, DctTh2, DctTh3
+
+    rec = currVop->yChan + offset;
+    input = inputFrame->yChan + offset;
+    if (lx != width) input -= (ind_y << 9);  /* non-padded offset */
+
+    dataBlock = video->dataBlock;
+    pred = video->predictedMB;
+
+    for (k = 0; k < 6; k++)
+    {
+        CBP <<= 1;
+        bitmapcol = video->bitmapcol[k];
+        bitmapzz = video->bitmapzz[k];  /*  8/2/01 */
+        if (k < 4)
+        {//Y block
+            sad = video->mot[mbnum][k+1].sad;
+            if (k&1)
+            {
+                rec += 8;
+                input += 8;
+            }
+            else if (k == 2)
+            {
+                dctMode = ((width << 3) - 8);
+                input += dctMode;
+                dctMode = ((lx << 3) - 8);
+                rec += dctMode;
+            }
+        }
+        else
+        {// U, V block
+            if (k == 4)
+            {
+                rec = currVop->uChan + offsetc;
+                input = inputFrame->uChan + offsetc;
+                if (lx != width) input -= (ind_y << 7);
+                lx >>= 1;
+                width >>= 1;
+                if (intra)
+                {
+                    dc_scaler = cal_dc_scalerENC(QP, 2); /* luminance blocks */
+                    DctTh1 = dc_scaler * 3;
+                    sad = getBlockSum(input, width);
+                }
+                else
+                    sad = Sad8x8(input, pred, width);
+            }
+            else
+            {
+                rec = currVop->vChan + offsetc;
+                input = inputFrame->vChan + offsetc;
+                if (lx != width) input -= (ind_y << 7);
+                if (intra)
+                    sad = getBlockSum(input, width);
+                else
+                    sad = Sad8x8(input, pred, width);
+            }
+        }
+
+        if (sad < DctTh1) /* all-zero */
+        {
+            dctMode = 0;
+            CBP |= 0;
+            ncoefblck[k] = 0;
+        }
+        else if (sad < DctTh2) /* DC-only */
+        {
+            dctMode = 1;
+            BlockDCT1x1(dataBlock, input, pred, width);
+
+            CBP |= (*BlockQuantDequantMPEGDC)(dataBlock, output, QP, qmat,
+                                              bitmapcol, bitmaprow + k, bitmapzz, dc_scaler);
+            ncoefblck[k] = 1;
+        }
+        else
+        {
+            dataBlock[64] = ColTh;
+
+            if (sad < DctTh3) /* 2x2-DCT */
+            {
+                dctMode = 2;
+                BlockDCT2x2(dataBlock, input, pred, width);
+                ncoefblck[k] = 6;
+            }
+            else if (sad < DctTh4) /* 4x4 DCT */
+            {
+                dctMode = 4;
+                BlockDCT4x4(dataBlock, input, pred, width);
+                ncoefblck[k] = 26;
+            }
+            else /* full-DCT */
+            {
+                dctMode = 8;
+                BlockDCT8x8(dataBlock, input, pred, width);
+                ncoefblck[k] = 64;
+            }
+
+            CBP |= (*BlockQuantDequantMPEG)(dataBlock, output, QP, qmat,
+                                            bitmapcol, bitmaprow + k, bitmapzz, dctMode, k, dc_scaler); //
+        }
+        dctMode = 8; /* for mismatch handle */
+        BlockIDCTMotionComp(dataBlock, bitmapcol, bitmaprow[k], dctMode, rec, pred, (lx << 1) | (intra));
+
+        output += 64;
+        if (!(k&1))
+        {
+            pred += 8;
+        }
+        else
+        {
+            pred += 120;
+        }
+    }
+
+    video->headerInfo.CBP[mbnum] = CBP; /*  5/18/2001 */
+    return PV_SUCCESS;
+}
+
+#endif
+
+/* ======================================================================== */
+/*  Function : getBlockSAV( )                                               */
+/*  Date     : 8/10/2000                                                    */
+/*  Purpose  : Get SAV for one block                                        */
+/*  In/out   : block[64] contain one block data                             */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+/* can be written in MMX or SSE,  2/22/2001 */
+Int getBlockSAV(Short block[])
+{
+    Int i, val, sav = 0;
+
+    i = 8;
+    while (i--)
+    {
+        val = *block++;
+        if (val > 0)    sav += val;
+        else        sav -= val;
+        val = *block++;
+        if (val > 0)    sav += val;
+        else        sav -= val;
+        val = *block++;
+        if (val > 0)    sav += val;
+        else        sav -= val;
+        val = *block++;
+        if (val > 0)    sav += val;
+        else        sav -= val;
+        val = *block++;
+        if (val > 0)    sav += val;
+        else        sav -= val;
+        val = *block++;
+        if (val > 0)    sav += val;
+        else        sav -= val;
+        val = *block++;
+        if (val > 0)    sav += val;
+        else        sav -= val;
+        val = *block++;
+        if (val > 0)    sav += val;
+        else        sav -= val;
+    }
+
+    return sav;
+
+}
+
+/* ======================================================================== */
+/*  Function : Sad8x8( )                                                    */
+/*  Date     : 8/10/2000                                                    */
+/*  Purpose  : Find SAD between prev block and current block                */
+/*  In/out   : Previous and current frame block pointers, and frame width   */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/*      8/15/01,  - do 4 pixel at a time    assuming 32 bit register        */
+/* ======================================================================== */
+Int Sad8x8(UChar *cur, UChar *prev, Int width)
+{
+    UChar *end = cur + (width << 3);
+    Int sad = 0;
+    Int *curInt = (Int*) cur;
+    Int *prevInt = (Int*) prev;
+    Int cur1, cur2, prev1, prev2;
+    UInt mask, sgn_msk = 0x80808080;
+    Int  sum2 = 0, sum4 = 0;
+    Int  tmp;
+    do
+    {
+        mask    = ~(0xFF00);
+        cur1    = curInt[1];        /* load cur[4..7] */
+        cur2    = curInt[0];
+        curInt += (width >> 2);     /* load cur[0..3] and +=lx */
+        prev1   = prevInt[1];
+        prev2   = prevInt[0];
+        prevInt += 4;
+
+        tmp     = prev2 ^ cur2;
+        cur2    = prev2 - cur2;
+        tmp     = tmp ^ cur2;       /* (^)^(-) last bit is one if carry */
+        tmp     = sgn_msk & ((UInt)tmp >> 1); /* check the sign of each byte */
+        if (cur2 < 0)   tmp = tmp | 0x80000000; /* corcurt sign of first byte */
+        tmp     = (tmp << 8) - tmp;     /* carry borrowed bytes are marked with 0x1FE */
+        cur2    = cur2 + (tmp >> 7);     /* negative bytes is added with 0xFF, -1 */
+        cur2    = cur2 ^(tmp >> 7); /* take absolute by inverting bits (EOR) */
+
+        tmp     = prev1 ^ cur1;
+        cur1    = prev1 - cur1;
+        tmp     = tmp ^ cur1;       /* (^)^(-) last bit is one if carry */
+        tmp     = sgn_msk & ((UInt)tmp >> 1); /* check the sign of each byte */
+        if (cur1 < 0)   tmp = tmp | 0x80000000; /* corcurt sign of first byte */
+        tmp     = (tmp << 8) - tmp;     /* carry borrowed bytes are marked with 0x1FE */
+        cur1    = cur1 + (tmp >> 7);     /* negative bytes is added with 0xFF, -1 */
+        cur1    = cur1 ^(tmp >> 7); /* take absolute by inverting bits (EOR) */
+
+        sum4    = sum4 + cur1;
+        cur1    = cur1 & (mask << 8);   /* mask first and third bytes */
+        sum2    = sum2 + ((UInt)cur1 >> 8);
+        sum4    = sum4 + cur2;
+        cur2    = cur2 & (mask << 8);   /* mask first and third bytes */
+        sum2    = sum2 + ((UInt)cur2 >> 8);
+    }
+    while ((UInt)curInt < (UInt)end);
+
+    cur1 = sum4 - (sum2 << 8);  /* get even-sum */
+    cur1 = cur1 + sum2;         /* add 16 bit even-sum and odd-sum*/
+    cur1 = cur1 + (cur1 << 16); /* add upper and lower 16 bit sum */
+    sad  = ((UInt)cur1 >> 16);  /* take upper 16 bit */
+    return sad;
+}
+
+/* ======================================================================== */
+/*  Function : getBlockSum( )                                               */
+/*  Date     : 8/10/2000                                                    */
+/*  Purpose  : Find summation of value within a block.                      */
+/*  In/out   : Pointer to current block in a frame and frame width          */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/*          8/15/01,  - SIMD 4 pixels at a time                         */
+/* ======================================================================== */
+
+Int getBlockSum(UChar *cur, Int width)
+{
+    Int sad = 0, sum4 = 0, sum2 = 0;
+    UChar *end = cur + (width << 3);
+    Int *curInt = (Int*)cur;
+    UInt mask   = ~(0xFF00);
+    Int load1, load2;
+
+    do
+    {
+        load1 = curInt[1];
+        load2 = curInt[0];
+        curInt += (width >> 2);
+        sum4 += load1;
+        load1 = load1 & (mask << 8); /* even bytes */
+        sum2 += ((UInt)load1 >> 8); /* sum even bytes, 16 bit */
+        sum4 += load2;
+        load2 = load2 & (mask << 8); /* even bytes */
+        sum2 += ((UInt)load2 >> 8); /* sum even bytes, 16 bit */
+    }
+    while ((UInt)curInt < (UInt)end);
+    load1 = sum4 - (sum2 << 8);     /* get even-sum */
+    load1 = load1 + sum2;           /* add 16 bit even-sum and odd-sum*/
+    load1 = load1 + (load1 << 16);  /* add upper and lower 16 bit sum */
+    sad  = ((UInt)load1 >> 16); /* take upper 16 bit */
+
+    return sad;
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h
new file mode 100644
index 0000000..686a66d
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h
@@ -0,0 +1,103 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*  =====================================================================   */
+/*  File: FastCodeMB.h                                                      */
+/*  Description: This file contains structure and function prototypes used
+            in FastCodeMB() function. When it is decided to use FastCodeMB
+            instead of CodeMB, all of this prototypes should be migrated to
+            mp4enc_lib.h.                                                   */
+/*  Rev:                                                                    */
+/*  Created: 8/14/01                                                        */
+/* //////////////////////////////////////////////////////////////////////// */
+
+typedef struct struct_approxDCT  approxDCT;
+struct struct_approxDCT
+{
+    const Int *scale;
+    Int(*DCT)(Int block[ ], Int coeff[ ], approxDCT *);
+
+    // Threshold value for H.263 Quantizer
+    Int th_app_all[8];
+    Int th_app_odd[8];
+    Int th_app_even[8];
+    Int th_app_even1[8];
+    Int th_app_even2[8];
+};
+
+struct QPstruct
+{
+    Int QPx2 ;
+    Int QP;
+    Int QPdiv2;
+    Int QPx2plus;
+    Int Addition;
+};
+
+/*---- FastCodeMB.c -----*/
+void initCodeMB(approxDCT *function, Int QP);
+PV_STATUS CodeMB_H263(VideoEncData *video, approxDCT *function, Int QP, Int ncoefblck[], Int offset);
+PV_STATUS CodeMB_MPEG(VideoEncData *video, approxDCT *function, Int QP, Int ncoefblck[], Int offset);
+Int getBlockSAV(Int block[]);
+Int Sad8x8(UChar *rec, UChar *prev, Int lx);
+Int getBlockSum(UChar *rec, Int lx);
+
+/*---- AppVCA_dct.c -----*/
+Int     AppVCA1_dct(Int block[], Int out[ ], approxDCT *function);
+Int     AppVCA2_dct(Int block[], Int out[ ], approxDCT *function);
+Int     AppVCA3_dct(Int block[], Int out[ ], approxDCT *function);
+Int     AppVCA4_dct(Int block[], Int out[ ], approxDCT *function);
+Int     AppVCA5_dct(Int block[], Int out[ ], approxDCT *function);
+
+/*---- FastQuant.c -----*/
+Int cal_dc_scalerENC(Int QP, Int type) ;
+Int BlockQuantDequantH263Inter(Int *rcoeff, Int *qcoeff, struct QPstruct *QuantParam,
+                               UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                               Int dctMode, Int comp, Int dummy);
+
+Int BlockQuantDequantH263Intra(Int *rcoeff, Int *qcoeff, struct QPstruct *QuantParam,
+                               UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                               Int dctMode, Int comp, Int dc_scaler);
+
+Int BlockQuantDequantH263DCInter(Int *rcoeff, Int *qcoeff, struct QPstruct *QuantParam,
+                                 UChar *bitmaprow, UInt *bitmapzz, Int dummy);
+
+Int BlockQuantDequantH263DCIntra(Int *rcoeff, Int *qcoeff, struct QPstruct *QuantParam,
+                                 UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler);
+
+Int BlockQuantDequantMPEGInter(Int *rcoeff, Int *qcoeff, Int QP, Int *qmat,
+                               UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                               Int DctMode, Int comp, Int dc_scaler);
+
+Int BlockQuantDequantMPEGIntra(Int *rcoeff, Int *qcoeff, Int QP, Int *qmat,
+                               UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                               Int DctMode, Int comp, Int dc_scaler);
+
+Int BlockQuantDequantMPEGDCInter(Int *rcoeff, Int *qcoeff, Int QP, Int *qmat,
+                                 UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dummy);
+
+Int BlockQuantDequantMPEGDCIntra(Int *rcoeff, Int *qcoeff, Int QP, Int *qmat,
+                                 UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler);
+
+/*---- FastIDCT.c -----*/
+void BlockIDCTMotionComp(Int *block, UChar *bitmapcol, UChar bitmaprow,
+                         Int dctMode, UChar *rec, Int lx, Int intra);
+
+/*---- motion_comp.c -----*/
+void PutSkippedBlock(UChar *rec, UChar *prev, Int lx);
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp
new file mode 100644
index 0000000..21d7427
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp
@@ -0,0 +1,2020 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+ Who:   Date: July/2001
+ Description:   1. Optimized BlockIDCT bitmap checking.
+                2. Rearranged functions.
+                3. Do column IDCT first, then row IDCT.
+                4. Combine motion comp and IDCT, require
+                   two sets of row IDCTs one for INTRA
+                   and one for INTER.
+                5. Add AAN IDCT
+
+ Who:   Date: 8/16/01
+                1. Increase the input precision to 8 bits, i.e. change RDCTBITS
+                   to 11, have to comment out all in-line assembly since 16 bit
+                    multiplication doesn't work. Try to use diffent precision with
+                    32 bit mult. but hasn't finished. Turns out that without in-line
+                    assembly the performance doesn't change much (only 1%).
+ Who:   Date: 9/04/05
+                1. Replace AAN IDCT with Chen's IDCT to accommodate 16 bit data type.
+
+*/
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "dct.h"
+
+#define ADD_CLIP    { \
+            tmp = *rec + tmp; \
+        if((UInt)tmp > mask) tmp = mask&(~(tmp>>31)); \
+        *rec++ = tmp;   \
+        }
+
+#define INTRA_CLIP  { \
+        if((UInt)tmp > mask) tmp = mask&(~(tmp>>31)); \
+        *rec++ = tmp;   \
+        }
+
+
+#define CLIP_RESULT(x)      if((UInt)x > 0xFF){x = 0xFF & (~(x>>31));}
+#define ADD_AND_CLIP1(x)    x += (pred_word&0xFF); CLIP_RESULT(x);
+#define ADD_AND_CLIP2(x)    x += ((pred_word>>8)&0xFF); CLIP_RESULT(x);
+#define ADD_AND_CLIP3(x)    x += ((pred_word>>16)&0xFF); CLIP_RESULT(x);
+#define ADD_AND_CLIP4(x)    x += ((pred_word>>24)&0xFF); CLIP_RESULT(x);
+
+
+void idct_col0(Short *blk)
+{
+    OSCL_UNUSED_ARG(blk);
+
+    return;
+}
+
+void idct_col1(Short *blk)
+{
+    blk[0] = blk[8] = blk[16] = blk[24] = blk[32] = blk[40] = blk[48] = blk[56] =
+                                              blk[0] << 3;
+    return ;
+}
+
+void idct_col2(Short *blk)
+{
+    int32 x0, x1, x3, x5, x7;//, x8;
+
+    x1 = blk[8];
+    x0 = ((int32)blk[0] << 11) + 128;
+    /* both upper and lower*/
+
+    x7 = W7 * x1;
+    x1 = W1 * x1;
+
+    x3 = x7;
+    x5 = (181 * (x1 - x7) + 128) >> 8;
+    x7 = (181 * (x1 + x7) + 128) >> 8;
+
+    blk[0] = (x0 + x1) >> 8;
+    blk[8] = (x0 + x7) >> 8;
+    blk[16] = (x0 + x5) >> 8;
+    blk[24] = (x0 + x3) >> 8;
+    blk[56] = (x0 - x1) >> 8;
+    blk[48] = (x0 - x7) >> 8;
+    blk[40] = (x0 - x5) >> 8;
+    blk[32] = (x0 - x3) >> 8;
+    return ;
+}
+
+void idct_col3(Short *blk)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+
+    x2 = blk[16];
+    x1 = blk[8];
+    x0 = ((int32)blk[0] << 11) + 128;
+
+    x4 = x0;
+    x6 = W6 * x2;
+    x2 = W2 * x2;
+    x8 = x0 - x2;
+    x0 += x2;
+    x2 = x8;
+    x8 = x4 - x6;
+    x4 += x6;
+    x6 = x8;
+
+    x7 = W7 * x1;
+    x1 = W1 * x1;
+    x3 = x7;
+    x5 = (181 * (x1 - x7) + 128) >> 8;
+    x7 = (181 * (x1 + x7) + 128) >> 8;
+
+    blk[0] = (x0 + x1) >> 8;
+    blk[8] = (x4 + x7) >> 8;
+    blk[16] = (x6 + x5) >> 8;
+    blk[24] = (x2 + x3) >> 8;
+    blk[56] = (x0 - x1) >> 8;
+    blk[48] = (x4 - x7) >> 8;
+    blk[40] = (x6 - x5) >> 8;
+    blk[32] = (x2 - x3) >> 8;
+    return ;
+}
+
+void idct_col4(Short *blk)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    x2 = blk[16];
+    x1 = blk[8];
+    x3 = blk[24];
+    x0 = ((int32)blk[0] << 11) + 128;
+
+    x4 = x0;
+    x6 = W6 * x2;
+    x2 = W2 * x2;
+    x8 = x0 - x2;
+    x0 += x2;
+    x2 = x8;
+    x8 = x4 - x6;
+    x4 += x6;
+    x6 = x8;
+
+    x7 = W7 * x1;
+    x1 = W1 * x1;
+    x5 = W3 * x3;
+    x3 = -W5 * x3;
+    x8 = x1 - x5;
+    x1 += x5;
+    x5 = x8;
+    x8 = x7 - x3;
+    x3 += x7;
+    x7 = (181 * (x5 + x8) + 128) >> 8;
+    x5 = (181 * (x5 - x8) + 128) >> 8;
+
+
+    blk[0] = (x0 + x1) >> 8;
+    blk[8] = (x4 + x7) >> 8;
+    blk[16] = (x6 + x5) >> 8;
+    blk[24] = (x2 + x3) >> 8;
+    blk[56] = (x0 - x1) >> 8;
+    blk[48] = (x4 - x7) >> 8;
+    blk[40] = (x6 - x5) >> 8;
+    blk[32] = (x2 - x3) >> 8;
+    return ;
+}
+
+#ifndef SMALL_DCT
+void idct_col0x40(Short *blk)
+{
+    int32 x1, x3, x5, x7;//, x8;
+
+    x1 = blk[8];
+    /* both upper and lower*/
+
+    x7 = W7 * x1;
+    x1 = W1 * x1;
+
+    x3 = x7;
+    x5 = (181 * (x1 - x7) + 128) >> 8;
+    x7 = (181 * (x1 + x7) + 128) >> 8;
+
+    blk[0] = (128 + x1) >> 8;
+    blk[8] = (128 + x7) >> 8;
+    blk[16] = (128 + x5) >> 8;
+    blk[24] = (128 + x3) >> 8;
+    blk[56] = (128 - x1) >> 8;
+    blk[48] = (128 - x7) >> 8;
+    blk[40] = (128 - x5) >> 8;
+    blk[32] = (128 - x3) >> 8;
+
+    return ;
+}
+
+void idct_col0x20(Short *blk)
+{
+    int32 x0, x2, x4, x6;
+
+    x2 = blk[16];
+    x6 = W6 * x2;
+    x2 = W2 * x2;
+    x0 = 128 + x2;
+    x2 = 128 - x2;
+    x4 = 128 + x6;
+    x6 = 128 - x6;
+
+    blk[0] = (x0) >> 8;
+    blk[56] = (x0) >> 8;
+    blk[8] = (x4) >> 8;
+    blk[48] = (x4) >> 8;
+    blk[16] = (x6) >> 8;
+    blk[40] = (x6) >> 8;
+    blk[24] = (x2) >> 8;
+    blk[32] = (x2) >> 8;
+
+    return ;
+}
+
+void idct_col0x10(Short *blk)
+{
+    int32 x1, x3, x5,  x7;
+
+    x3 = blk[24];
+    x1 = W3 * x3;
+    x3 = W5 * x3;
+
+    x7 = (181 * (x3 - x1) + 128) >> 8;
+    x5 = (-181 * (x1 + x3) + 128) >> 8;
+
+
+    blk[0] = (128 + x1) >> 8;
+    blk[8] = (128 + x7) >> 8;
+    blk[16] = (128 + x5) >> 8;
+    blk[24] = (128 - x3) >> 8;
+    blk[56] = (128 - x1) >> 8;
+    blk[48] = (128 - x7) >> 8;
+    blk[40] = (128 - x5) >> 8;
+    blk[32] = (128 + x3) >> 8;
+
+    return ;
+}
+
+#endif /* SMALL_DCT */
+
+void idct_col(Short *blk)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+
+    x1 = (int32)blk[32] << 11;
+    x2 = blk[48];
+    x3 = blk[16];
+    x4 = blk[8];
+    x5 = blk[56];
+    x6 = blk[40];
+    x7 = blk[24];
+    x0 = ((int32)blk[0] << 11) + 128;
+
+    /* first stage */
+    x8 = W7 * (x4 + x5);
+    x4 = x8 + (W1 - W7) * x4;
+    x5 = x8 - (W1 + W7) * x5;
+    x8 = W3 * (x6 + x7);
+    x6 = x8 - (W3 - W5) * x6;
+    x7 = x8 - (W3 + W5) * x7;
+
+    /* second stage */
+    x8 = x0 + x1;
+    x0 -= x1;
+    x1 = W6 * (x3 + x2);
+    x2 = x1 - (W2 + W6) * x2;
+    x3 = x1 + (W2 - W6) * x3;
+    x1 = x4 + x6;
+    x4 -= x6;
+    x6 = x5 + x7;
+    x5 -= x7;
+
+    /* third stage */
+    x7 = x8 + x3;
+    x8 -= x3;
+    x3 = x0 + x2;
+    x0 -= x2;
+    x2 = (181 * (x4 + x5) + 128) >> 8;
+    x4 = (181 * (x4 - x5) + 128) >> 8;
+
+    /* fourth stage */
+    blk[0]    = (x7 + x1) >> 8;
+    blk[8] = (x3 + x2) >> 8;
+    blk[16] = (x0 + x4) >> 8;
+    blk[24] = (x8 + x6) >> 8;
+    blk[32] = (x8 - x6) >> 8;
+    blk[40] = (x0 - x4) >> 8;
+    blk[48] = (x3 - x2) >> 8;
+    blk[56] = (x7 - x1) >> 8;
+
+    return ;
+}
+
+/* This function should not be called at all ****/
+void idct_row0Inter(Short *srce, UChar *rec, Int lx)
+{
+    OSCL_UNUSED_ARG(srce);
+
+    OSCL_UNUSED_ARG(rec);
+
+    OSCL_UNUSED_ARG(lx);
+
+    return;
+}
+
+void idct_row1Inter(Short *blk, UChar *rec, Int lx)
+{
+    int tmp;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    blk -= 8;
+
+    while (i--)
+    {
+        tmp = (*(blk += 8) + 32) >> 6;
+        *blk = 0;
+
+        pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+        res = tmp + (pred_word & 0xFF);
+        CLIP_RESULT(res);
+        res2 = tmp + ((pred_word >> 8) & 0xFF);
+        CLIP_RESULT(res2);
+        dst_word = (res2 << 8) | res;
+        res = tmp + ((pred_word >> 16) & 0xFF);
+        CLIP_RESULT(res);
+        dst_word |= (res << 16);
+        res = tmp + ((pred_word >> 24) & 0xFF);
+        CLIP_RESULT(res);
+        dst_word |= (res << 24);
+        *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+        res = tmp + (pred_word & 0xFF);
+        CLIP_RESULT(res);
+        res2 = tmp + ((pred_word >> 8) & 0xFF);
+        CLIP_RESULT(res2);
+        dst_word = (res2 << 8) | res;
+        res = tmp + ((pred_word >> 16) & 0xFF);
+        CLIP_RESULT(res);
+        dst_word |= (res << 16);
+        res = tmp + ((pred_word >> 24) & 0xFF);
+        CLIP_RESULT(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return;
+}
+
+void idct_row2Inter(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x1, x2, x4, x5;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    blk -= 8;
+
+    while (i--)
+    {
+        /* shortcut */
+        x4 = blk[9];
+        blk[9] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;  /* for proper rounding in the fourth stage */
+
+        /* first stage */
+        x5 = (W7 * x4 + 4) >> 3;
+        x4 = (W1 * x4 + 4) >> 3;
+
+        /* third stage */
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x1 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+        res = (x0 + x4) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x0 + x2) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x0 + x1) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0 + x5) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+        res = (x0 - x5) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x0 - x1) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x0 - x2) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0 - x4) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return ;
+}
+
+void idct_row3Inter(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    blk -= 8;
+
+    while (i--)
+    {
+        x2 = blk[10];
+        blk[10] = 0;
+        x1 = blk[9];
+        blk[9] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;  /* for proper rounding in the fourth stage */
+        /* both upper and lower*/
+        /* both x2orx6 and x0orx4 */
+
+        x4 = x0;
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x8 = x0 - x2;
+        x0 += x2;
+        x2 = x8;
+        x8 = x4 - x6;
+        x4 += x6;
+        x6 = x8;
+
+        x7 = (W7 * x1 + 4) >> 3;
+        x1 = (W1 * x1 + 4) >> 3;
+        x3 = x7;
+        x5 = (181 * (x1 - x7) + 128) >> 8;
+        x7 = (181 * (x1 + x7) + 128) >> 8;
+
+        pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+        res = (x0 + x1) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x4 + x7) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x6 + x5) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x2 + x3) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+        res = (x2 - x3) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x6 - x5) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x4 - x7) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0 - x1) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+
+    return ;
+}
+
+void idct_row4Inter(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    blk -= 8;
+
+    while (i--)
+    {
+        x2 = blk[10];
+        blk[10] = 0;
+        x1 = blk[9];
+        blk[9] = 0;
+        x3 = blk[11];
+        blk[11] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;   /* for proper rounding in the fourth stage */
+
+        x4 = x0;
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x8 = x0 - x2;
+        x0 += x2;
+        x2 = x8;
+        x8 = x4 - x6;
+        x4 += x6;
+        x6 = x8;
+
+        x7 = (W7 * x1 + 4) >> 3;
+        x1 = (W1 * x1 + 4) >> 3;
+        x5 = (W3 * x3 + 4) >> 3;
+        x3 = (- W5 * x3 + 4) >> 3;
+        x8 = x1 - x5;
+        x1 += x5;
+        x5 = x8;
+        x8 = x7 - x3;
+        x3 += x7;
+        x7 = (181 * (x5 + x8) + 128) >> 8;
+        x5 = (181 * (x5 - x8) + 128) >> 8;
+
+        pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+        res = (x0 + x1) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x4 + x7) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x6 + x5) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x2 + x3) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+        res = (x2 - x3) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x6 - x5) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x4 - x7) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0 - x1) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return ;
+}
+
+#ifndef SMALL_DCT
+void idct_row0x40Inter(Short *blk, UChar *rec, Int lx)
+{
+    int32 x1, x2, x4, x5;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+
+    while (i--)
+    {
+        /* shortcut */
+        x4 = blk[1];
+        blk[1] = 0;
+        blk += 8;  /* for proper rounding in the fourth stage */
+
+        /* first stage */
+        x5 = (W7 * x4 + 4) >> 3;
+        x4 = (W1 * x4 + 4) >> 3;
+
+        /* third stage */
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x1 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+        res = (8192 + x4) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (8192 + x2) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (8192 + x1) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (8192 + x5) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+        res = (8192 - x5) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (8192 - x1) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (8192 - x2) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (8192 - x4) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return ;
+}
+
+void idct_row0x20Inter(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x2, x4, x6;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+
+    while (i--)
+    {
+        x2 = blk[2];
+        blk[2] = 0;
+        blk += 8; /* for proper rounding in the fourth stage */
+        /* both upper and lower*/
+        /* both x2orx6 and x0orx4 */
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x0 = 8192 + x2;
+        x2 = 8192 - x2;
+        x4 = 8192 + x6;
+        x6 = 8192 - x6;
+
+        pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+        res = (x0) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x4) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x6) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x2) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+        res = (x2) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x6) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x4) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+
+    return ;
+}
+
+void idct_row0x10Inter(Short *blk, UChar *rec, Int lx)
+{
+    int32 x1, x3, x5, x7;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+
+    while (i--)
+    {
+        x3 = blk[3];
+        blk[3] = 0;
+        blk += 8;
+
+        x1 = (W3 * x3 + 4) >> 3;
+        x3 = (-W5 * x3 + 4) >> 3;
+
+        x7 = (-181 * (x3 + x1) + 128) >> 8;
+        x5 = (181 * (x3 - x1) + 128) >> 8;
+
+        pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+        res = (8192 + x1) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (8192 + x7) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (8192 + x5) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (8192 + x3) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+        res = (8192 - x3) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (8192 - x5) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (8192 - x7) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (8192 - x1) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return ;
+}
+
+#endif /* SMALL_DCT */
+
+void idct_rowInter(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    blk -= 8;
+
+    while (i--)
+    {
+        x1 = (int32)blk[12] << 8;
+        blk[12] = 0;
+        x2 = blk[14];
+        blk[14] = 0;
+        x3 = blk[10];
+        blk[10] = 0;
+        x4 = blk[9];
+        blk[9] = 0;
+        x5 = blk[15];
+        blk[15] = 0;
+        x6 = blk[13];
+        blk[13] = 0;
+        x7 = blk[11];
+        blk[11] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;   /* for proper rounding in the fourth stage */
+
+        /* first stage */
+        x8 = W7 * (x4 + x5) + 4;
+        x4 = (x8 + (W1 - W7) * x4) >> 3;
+        x5 = (x8 - (W1 + W7) * x5) >> 3;
+        x8 = W3 * (x6 + x7) + 4;
+        x6 = (x8 - (W3 - W5) * x6) >> 3;
+        x7 = (x8 - (W3 + W5) * x7) >> 3;
+
+        /* second stage */
+        x8 = x0 + x1;
+        x0 -= x1;
+        x1 = W6 * (x3 + x2) + 4;
+        x2 = (x1 - (W2 + W6) * x2) >> 3;
+        x3 = (x1 + (W2 - W6) * x3) >> 3;
+        x1 = x4 + x6;
+        x4 -= x6;
+        x6 = x5 + x7;
+        x5 -= x7;
+
+        /* third stage */
+        x7 = x8 + x3;
+        x8 -= x3;
+        x3 = x0 + x2;
+        x0 -= x2;
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x4 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+
+        res = (x7 + x1) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x3 + x2) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x0 + x4) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x8 + x6) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+
+        res = (x8 - x6) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x0 - x4) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x3 - x2) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x7 - x1) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return;
+}
+
+void idct_row0Intra(Short *srce, UChar *rec, Int lx)
+{
+    OSCL_UNUSED_ARG(srce);
+
+    OSCL_UNUSED_ARG(rec);
+
+    OSCL_UNUSED_ARG(lx);
+
+    return;
+}
+
+void idct_row1Intra(Short *blk, UChar *rec, Int lx)
+{
+    int32 tmp;
+    int i = 8;
+
+    rec -= lx;
+    blk -= 8;
+    while (i--)
+    {
+        tmp = ((*(blk += 8) + 32) >> 6);
+        *blk = 0;
+        CLIP_RESULT(tmp)
+
+        tmp |= (tmp << 8);
+        tmp |= (tmp << 16);
+        *((uint32*)(rec += lx)) = tmp;
+        *((uint32*)(rec + 4)) = tmp;
+    }
+    return;
+}
+
+void idct_row2Intra(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x1, x2, x4, x5;
+    int res, res2;
+    uint32 dst_word;
+    int i = 8;
+
+    rec -= lx;
+    blk -= 8;
+    while (i--)
+    {
+        /* shortcut */
+        x4 = blk[9];
+        blk[9] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;   /* for proper rounding in the fourth stage */
+
+        /* first stage */
+        x5 = (W7 * x4 + 4) >> 3;
+        x4 = (W1 * x4 + 4) >> 3;
+
+        /* third stage */
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x1 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        res = ((x0 + x4) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x0 + x2) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((x0 + x1) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x0 + x5) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word;
+
+        res = ((x0 - x5) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x0 - x1) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((x0 - x2) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x0 - x4) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word;
+    }
+    return ;
+}
+
+void idct_row3Intra(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int res, res2;
+    uint32 dst_word;
+    int i = 8;
+
+    rec -= lx;
+    blk -= 8;
+    while (i--)
+    {
+        x2 = blk[10];
+        blk[10] = 0;
+        x1 = blk[9];
+        blk[9] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;/* for proper rounding in the fourth stage */
+        /* both upper and lower*/
+        /* both x2orx6 and x0orx4 */
+
+        x4 = x0;
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x8 = x0 - x2;
+        x0 += x2;
+        x2 = x8;
+        x8 = x4 - x6;
+        x4 += x6;
+        x6 = x8;
+
+        x7 = (W7 * x1 + 4) >> 3;
+        x1 = (W1 * x1 + 4) >> 3;
+        x3 = x7;
+        x5 = (181 * (x1 - x7) + 128) >> 8;
+        x7 = (181 * (x1 + x7) + 128) >> 8;
+
+        res = ((x0 + x1) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x4 + x7) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((x6 + x5) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x2 + x3) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word;
+
+        res = ((x2 - x3) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x6 - x5) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((x4 - x7) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x0 - x1) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word;
+
+    }
+    return ;
+}
+
+void idct_row4Intra(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int res, res2;
+    uint32 dst_word;
+    int i = 8;
+
+    rec -= lx;
+    blk -= 8;
+    while (i--)
+    {
+        x2 = blk[10];
+        blk[10] = 0;
+        x1 = blk[9];
+        blk[9] = 0;
+        x3 = blk[11];
+        blk[11] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0; /* for proper rounding in the fourth stage */
+
+        x4 = x0;
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x8 = x0 - x2;
+        x0 += x2;
+        x2 = x8;
+        x8 = x4 - x6;
+        x4 += x6;
+        x6 = x8;
+
+        x7 = (W7 * x1 + 4) >> 3;
+        x1 = (W1 * x1 + 4) >> 3;
+        x5 = (W3 * x3 + 4) >> 3;
+        x3 = (- W5 * x3 + 4) >> 3;
+        x8 = x1 - x5;
+        x1 += x5;
+        x5 = x8;
+        x8 = x7 - x3;
+        x3 += x7;
+        x7 = (181 * (x5 + x8) + 128) >> 8;
+        x5 = (181 * (x5 - x8) + 128) >> 8;
+
+        res = ((x0 + x1) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x4 + x7) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((x6 + x5) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x2 + x3) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word;
+
+        res = ((x2 - x3) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x6 - x5) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((x4 - x7) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x0 - x1) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word;
+    }
+
+    return ;
+}
+
+#ifndef SMALL_DCT
+void idct_row0x40Intra(Short *blk, UChar *rec, Int lx)
+{
+    int32  x1, x2, x4, x5;
+    int res, res2;
+    uint32 dst_word;
+    int i = 8;
+
+    rec -= lx;
+
+    while (i--)
+    {
+        /* shortcut */
+        x4 = blk[1];
+        blk[1] = 0;
+        blk += 8;
+
+        /* first stage */
+        x5 = (W7 * x4 + 4) >> 3;
+        x4 = (W1 * x4 + 4) >> 3;
+
+        /* third stage */
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x1 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        res = ((8192 + x4) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((8192 + x2) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((8192 + x1) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((8192 + x5) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word;
+
+        res = ((8192 - x5) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((8192 - x1) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((8192 - x2) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((8192 - x4) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word;
+
+    }
+    return ;
+}
+
+void idct_row0x20Intra(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x2, x4, x6;
+    int res, res2;
+    uint32 dst_word;
+    int i = 8;
+
+    rec -= lx;
+    while (i--)
+    {
+        x2 = blk[2];
+        blk[2] = 0;
+        blk += 8;
+
+        /* both upper and lower*/
+        /* both x2orx6 and x0orx4 */
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x0 = 8192 + x2;
+        x2 = 8192 - x2;
+        x4 = 8192 + x6;
+        x6 = 8192 - x6;
+
+        res = ((x0) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x4) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((x6) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x2) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word;
+
+        res = ((x2) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x6) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((x4) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x0) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word;
+
+    }
+    return ;
+}
+
+void idct_row0x10Intra(Short *blk, UChar *rec, Int lx)
+{
+    int32 x1, x3, x5, x7;
+    int res, res2;
+    uint32 dst_word;
+    int i = 8;
+
+    rec -= lx;
+    while (i--)
+    {
+        x3 = blk[3];
+        blk[3] = 0 ;
+        blk += 8;
+
+        x1 = (W3 * x3 + 4) >> 3;
+        x3 = (W5 * x3 + 4) >> 3;
+
+        x7 = (181 * (x3 - x1) + 128) >> 8;
+        x5 = (-181 * (x1 + x3) + 128) >> 8;
+
+        res = ((8192 + x1) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((8192 + x7) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((8192 + x5) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((8192 - x3) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word;
+
+        res = ((8192 + x3) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((8192 - x5) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = (res2 << 8) | res;
+        res = ((8192 - x7) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((8192 - x1) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word;
+
+    }
+
+    return ;
+}
+
+#endif /* SMALL_DCT */
+void idct_rowIntra(Short *blk, UChar *rec, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int i = 8;
+    int res, res2;
+    uint32 dst_word;
+
+    blk -= 8;
+    rec -= lx;
+
+    while (i--)
+    {
+        x1 = (int32)blk[12] << 8;
+        blk[12] = 0;
+        x2 = blk[14];
+        blk[14] = 0;
+        x3 = blk[10];
+        blk[10] = 0;
+        x4 = blk[9];
+        blk[9] = 0;
+        x5 = blk[15];
+        blk[15] = 0;
+        x6 = blk[13];
+        blk[13] = 0;
+        x7 = blk[11];
+        blk[11] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;  /* for proper rounding in the fourth stage */
+
+        /* first stage */
+        x8 = W7 * (x4 + x5) + 4;
+        x4 = (x8 + (W1 - W7) * x4) >> 3;
+        x5 = (x8 - (W1 + W7) * x5) >> 3;
+        x8 = W3 * (x6 + x7) + 4;
+        x6 = (x8 - (W3 - W5) * x6) >> 3;
+        x7 = (x8 - (W3 + W5) * x7) >> 3;
+
+        /* second stage */
+        x8 = x0 + x1;
+        x0 -= x1;
+        x1 = W6 * (x3 + x2) + 4;
+        x2 = (x1 - (W2 + W6) * x2) >> 3;
+        x3 = (x1 + (W2 - W6) * x3) >> 3;
+        x1 = x4 + x6;
+        x4 -= x6;
+        x6 = x5 + x7;
+        x5 -= x7;
+
+        /* third stage */
+        x7 = x8 + x3;
+        x8 -= x3;
+        x3 = x0 + x2;
+        x0 -= x2;
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x4 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        res = ((x7 + x1) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x3 + x2) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = res | (res2 << 8);
+        res = ((x0 + x4) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x8 + x6) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word;
+
+        res = ((x8 - x6) >> 14);
+        CLIP_RESULT(res)
+        res2 = ((x0 - x4) >> 14);
+        CLIP_RESULT(res2)
+        dst_word = res | (res2 << 8);
+        res = ((x3 - x2) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 16);
+        res = ((x7 - x1) >> 14);
+        CLIP_RESULT(res)
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word;
+    }
+    return;
+}
+
+
+/* This function should not be called at all ****/
+void idct_row0zmv(Short *srce, UChar *rec, UChar *pred, Int lx)
+{
+    OSCL_UNUSED_ARG(srce);
+    OSCL_UNUSED_ARG(rec);
+    OSCL_UNUSED_ARG(pred);
+    OSCL_UNUSED_ARG(lx);
+
+    return;
+}
+
+void idct_row1zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+    int tmp;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    pred -= 16;
+    rec -= lx;
+    blk -= 8;
+
+    while (i--)
+    {
+        tmp = (*(blk += 8) + 32) >> 6;
+        *blk = 0;
+
+        pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+        res = tmp + (pred_word & 0xFF);
+        CLIP_RESULT(res);
+        res2 = tmp + ((pred_word >> 8) & 0xFF);
+        CLIP_RESULT(res2);
+        dst_word = (res2 << 8) | res;
+        res = tmp + ((pred_word >> 16) & 0xFF);
+        CLIP_RESULT(res);
+        dst_word |= (res << 16);
+        res = tmp + ((pred_word >> 24) & 0xFF);
+        CLIP_RESULT(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+        res = tmp + (pred_word & 0xFF);
+        CLIP_RESULT(res);
+        res2 = tmp + ((pred_word >> 8) & 0xFF);
+        CLIP_RESULT(res2);
+        dst_word = (res2 << 8) | res;
+        res = tmp + ((pred_word >> 16) & 0xFF);
+        CLIP_RESULT(res);
+        dst_word |= (res << 16);
+        res = tmp + ((pred_word >> 24) & 0xFF);
+        CLIP_RESULT(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return;
+}
+
+void idct_row2zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+    int32 x0, x1, x2, x4, x5;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    pred -= 16;
+    blk -= 8;
+
+    while (i--)
+    {
+        /* shortcut */
+        x4 = blk[9];
+        blk[9] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;  /* for proper rounding in the fourth stage */
+
+        /* first stage */
+        x5 = (W7 * x4 + 4) >> 3;
+        x4 = (W1 * x4 + 4) >> 3;
+
+        /* third stage */
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x1 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+        res = (x0 + x4) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x0 + x2) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x0 + x1) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0 + x5) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+        res = (x0 - x5) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x0 - x1) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x0 - x2) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0 - x4) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return ;
+}
+
+void idct_row3zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    pred -= 16;
+    blk -= 8;
+
+    while (i--)
+    {
+        x2 = blk[10];
+        blk[10] = 0;
+        x1 = blk[9];
+        blk[9] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;  /* for proper rounding in the fourth stage */
+        /* both upper and lower*/
+        /* both x2orx6 and x0orx4 */
+
+        x4 = x0;
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x8 = x0 - x2;
+        x0 += x2;
+        x2 = x8;
+        x8 = x4 - x6;
+        x4 += x6;
+        x6 = x8;
+
+        x7 = (W7 * x1 + 4) >> 3;
+        x1 = (W1 * x1 + 4) >> 3;
+        x3 = x7;
+        x5 = (181 * (x1 - x7) + 128) >> 8;
+        x7 = (181 * (x1 + x7) + 128) >> 8;
+
+        pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+        res = (x0 + x1) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x4 + x7) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x6 + x5) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x2 + x3) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+        res = (x2 - x3) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x6 - x5) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x4 - x7) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0 - x1) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+
+    return ;
+}
+
+void idct_row4zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    pred -= 16;
+    blk -= 8;
+
+    while (i--)
+    {
+        x2 = blk[10];
+        blk[10] = 0;
+        x1 = blk[9];
+        blk[9] = 0;
+        x3 = blk[11];
+        blk[11] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;   /* for proper rounding in the fourth stage */
+
+        x4 = x0;
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x8 = x0 - x2;
+        x0 += x2;
+        x2 = x8;
+        x8 = x4 - x6;
+        x4 += x6;
+        x6 = x8;
+
+        x7 = (W7 * x1 + 4) >> 3;
+        x1 = (W1 * x1 + 4) >> 3;
+        x5 = (W3 * x3 + 4) >> 3;
+        x3 = (- W5 * x3 + 4) >> 3;
+        x8 = x1 - x5;
+        x1 += x5;
+        x5 = x8;
+        x8 = x7 - x3;
+        x3 += x7;
+        x7 = (181 * (x5 + x8) + 128) >> 8;
+        x5 = (181 * (x5 - x8) + 128) >> 8;
+
+        pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+        res = (x0 + x1) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x4 + x7) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x6 + x5) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x2 + x3) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+        res = (x2 - x3) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x6 - x5) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x4 - x7) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0 - x1) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return ;
+}
+
+#ifndef SMALL_DCT
+void idct_row0x40zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+    int32 x1, x2, x4, x5;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    pred -= 16;
+
+    while (i--)
+    {
+        /* shortcut */
+        x4 = blk[1];
+        blk[1] = 0;
+        blk += 8;  /* for proper rounding in the fourth stage */
+
+        /* first stage */
+        x5 = (W7 * x4 + 4) >> 3;
+        x4 = (W1 * x4 + 4) >> 3;
+
+        /* third stage */
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x1 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+        res = (8192 + x4) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (8192 + x2) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (8192 + x1) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (8192 + x5) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+        res = (8192 - x5) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (8192 - x1) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (8192 - x2) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (8192 - x4) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return ;
+}
+
+void idct_row0x20zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+    int32 x0, x2, x4, x6;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    pred -= 16;
+
+    while (i--)
+    {
+        x2 = blk[2];
+        blk[2] = 0;
+        blk += 8; /* for proper rounding in the fourth stage */
+        /* both upper and lower*/
+        /* both x2orx6 and x0orx4 */
+        x6 = (W6 * x2 + 4) >> 3;
+        x2 = (W2 * x2 + 4) >> 3;
+        x0 = 8192 + x2;
+        x2 = 8192 - x2;
+        x4 = 8192 + x6;
+        x6 = 8192 - x6;
+
+        pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+        res = (x0) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x4) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x6) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x2) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+        res = (x2) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x6) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x4) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x0) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+
+    return ;
+}
+
+void idct_row0x10zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+    int32 x1, x3, x5, x7;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    pred -= 16;
+
+    while (i--)
+    {
+        x3 = blk[3];
+        blk[3] = 0;
+        blk += 8;
+
+        x1 = (W3 * x3 + 4) >> 3;
+        x3 = (-W5 * x3 + 4) >> 3;
+
+        x7 = (-181 * (x3 + x1) + 128) >> 8;
+        x5 = (181 * (x3 - x1) + 128) >> 8;
+
+        pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+        res = (8192 + x1) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (8192 + x7) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (8192 + x5) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (8192 + x3) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+        res = (8192 - x3) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (8192 - x5) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (8192 - x7) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (8192 - x1) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return ;
+}
+
+#endif /* SMALL_DCT */
+
+void idct_rowzmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+    int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+    int i = 8;
+    uint32 pred_word, dst_word;
+    int res, res2;
+
+    /* preset the offset, such that we can take advantage pre-offset addressing mode   */
+    rec -= lx;
+    pred -= 16;
+    blk -= 8;
+
+    while (i--)
+    {
+        x1 = (int32)blk[12] << 8;
+        blk[12] = 0;
+        x2 = blk[14];
+        blk[14] = 0;
+        x3 = blk[10];
+        blk[10] = 0;
+        x4 = blk[9];
+        blk[9] = 0;
+        x5 = blk[15];
+        blk[15] = 0;
+        x6 = blk[13];
+        blk[13] = 0;
+        x7 = blk[11];
+        blk[11] = 0;
+        x0 = ((*(blk += 8)) << 8) + 8192;
+        *blk = 0;   /* for proper rounding in the fourth stage */
+
+        /* first stage */
+        x8 = W7 * (x4 + x5) + 4;
+        x4 = (x8 + (W1 - W7) * x4) >> 3;
+        x5 = (x8 - (W1 + W7) * x5) >> 3;
+        x8 = W3 * (x6 + x7) + 4;
+        x6 = (x8 - (W3 - W5) * x6) >> 3;
+        x7 = (x8 - (W3 + W5) * x7) >> 3;
+
+        /* second stage */
+        x8 = x0 + x1;
+        x0 -= x1;
+        x1 = W6 * (x3 + x2) + 4;
+        x2 = (x1 - (W2 + W6) * x2) >> 3;
+        x3 = (x1 + (W2 - W6) * x3) >> 3;
+        x1 = x4 + x6;
+        x4 -= x6;
+        x6 = x5 + x7;
+        x5 -= x7;
+
+        /* third stage */
+        x7 = x8 + x3;
+        x8 -= x3;
+        x3 = x0 + x2;
+        x0 -= x2;
+        x2 = (181 * (x4 + x5) + 128) >> 8;
+        x4 = (181 * (x4 - x5) + 128) >> 8;
+
+        /* fourth stage */
+        pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+
+        res = (x7 + x1) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x3 + x2) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x0 + x4) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x8 + x6) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+        pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+
+        res = (x8 - x6) >> 14;
+        ADD_AND_CLIP1(res);
+        res2 = (x0 - x4) >> 14;
+        ADD_AND_CLIP2(res2);
+        dst_word = (res2 << 8) | res;
+        res = (x3 - x2) >> 14;
+        ADD_AND_CLIP3(res);
+        dst_word |= (res << 16);
+        res = (x7 - x1) >> 14;
+        ADD_AND_CLIP4(res);
+        dst_word |= (res << 24);
+        *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+    }
+    return;
+}
+
+/*----------------------------------------------------------------------------
+;  End Function: idctcol
+----------------------------------------------------------------------------*/
+/* ======================================================================== */
+/*  Function : BlockIDCTMotionComp                                              */
+/*  Date     : 10/16/2000                                                   */
+/*  Purpose  : fast IDCT routine                                    */
+/*  In/out   :                                                              */
+/*      Int* coeff_in   Dequantized coefficient
+        Int block_out   output IDCT coefficient
+        Int maxval      clip value                                          */
+/*  Modified :   7/31/01, add checking for all-zero and DC-only block.  */
+/*              do 8 columns at a time                                      */
+/*               8/2/01, do column first then row-IDCT.                 */
+/*               8/2/01, remove clipping (included in motion comp).     */
+/*               8/7/01, combine with motion comp.                      */
+/*               8/8/01, use AAN IDCT                                       */
+/*               9/4/05, use Chen's IDCT and 16 bit block                   */
+/* ======================================================================== */
+void BlockIDCTMotionComp(Short *block, UChar *bitmapcol, UChar bitmaprow,
+                         Int dctMode, UChar *rec, UChar *pred, Int lx_intra)
+{
+    Int i;
+    Int tmp, tmp2;
+    ULong tmp4;
+    Int bmap;
+    Short *ptr = block;
+    UChar *endcol;
+    UInt mask = 0xFF;
+    Int lx = lx_intra >> 1;
+    Int intra = (lx_intra & 1);
+
+    /*  all-zero block */
+    if (dctMode == 0 || bitmaprow == 0)
+    {
+        if (intra)
+        {
+            *((ULong*)rec) = *((ULong*)(rec + 4)) = 0;
+            *((ULong*)(rec += lx)) = 0;
+            *((ULong*)(rec + 4)) = 0;
+            *((ULong*)(rec += lx)) = 0;
+            *((ULong*)(rec + 4)) = 0;
+            *((ULong*)(rec += lx)) = 0;
+            *((ULong*)(rec + 4)) = 0;
+            *((ULong*)(rec += lx)) = 0;
+            *((ULong*)(rec + 4)) = 0;
+            *((ULong*)(rec += lx)) = 0;
+            *((ULong*)(rec + 4)) = 0;
+            *((ULong*)(rec += lx)) = 0;
+            *((ULong*)(rec + 4)) = 0;
+            *((ULong*)(rec += lx)) = 0;
+            *((ULong*)(rec + 4)) = 0;
+            return ;
+        }
+        else /* copy from previous frame */
+        {
+            *((ULong*)rec) = *((ULong*)pred);
+            *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+            *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+            *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+            *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+            *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+            *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+            *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+            *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+            *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+            *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+            *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+            *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+            *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+            *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+            *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+            return ;
+        }
+    }
+
+    /* Test for DC only block */
+    if (dctMode == 1 || (bitmaprow == 0x80 && bitmapcol[0] == 0x80))
+    {
+        i = ((block[0] << 3) + 32) >> 6;
+        block[0] = 0;
+        if (intra)
+        {
+            if ((UInt)i > mask) i = mask & (~(i >> 31));
+
+            tmp = i | (i << 8);
+            tmp |= (tmp << 16);
+
+            *((ULong*)rec) = *((ULong*)(rec + 4)) = tmp;
+            *((ULong*)(rec += lx)) = tmp;
+            *((ULong*)(rec + 4)) = tmp;
+            *((ULong*)(rec += lx)) = tmp;
+            *((ULong*)(rec + 4)) = tmp;
+            *((ULong*)(rec += lx)) = tmp;
+            *((ULong*)(rec + 4)) = tmp;
+            *((ULong*)(rec += lx)) = tmp;
+            *((ULong*)(rec + 4)) = tmp;
+            *((ULong*)(rec += lx)) = tmp;
+            *((ULong*)(rec + 4)) = tmp;
+            *((ULong*)(rec += lx)) = tmp;
+            *((ULong*)(rec + 4)) = tmp;
+            *((ULong*)(rec += lx)) = tmp;
+            *((ULong*)(rec + 4)) = tmp;
+
+            return ;
+        }
+        else
+        {
+            endcol = rec + (lx << 3);
+            do
+            {
+                tmp4 = *((ULong*)pred);
+                tmp2 = tmp4 & 0xFF;
+                tmp2 += i;
+                if ((UInt)tmp2 > mask) tmp2 = mask & (~(tmp2 >> 31));
+                tmp = (tmp4 >> 8) & 0xFF;
+                tmp += i;
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                tmp2 |= (tmp << 8);
+                tmp = (tmp4 >> 16) & 0xFF;
+                tmp += i;
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                tmp2 |= (tmp << 16);
+                tmp = (tmp4 >> 24) & 0xFF;
+                tmp += i;
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                tmp2 |= (tmp << 24);
+                *((ULong*)rec) = tmp2;
+
+                tmp4 = *((ULong*)(pred + 4));
+                tmp2 = tmp4 & 0xFF;
+                tmp2 += i;
+                if ((UInt)tmp2 > mask) tmp2 = mask & (~(tmp2 >> 31));
+                tmp = (tmp4 >> 8) & 0xFF;
+                tmp += i;
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                tmp2 |= (tmp << 8);
+                tmp = (tmp4 >> 16) & 0xFF;
+                tmp += i;
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                tmp2 |= (tmp << 16);
+                tmp = (tmp4 >> 24) & 0xFF;
+                tmp += i;
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                tmp2 |= (tmp << 24);
+                *((ULong*)(rec + 4)) = tmp2;
+
+                rec += lx;
+                pred += 16;
+            }
+            while (rec < endcol);
+            return ;
+        }
+    }
+
+    for (i = 0; i < dctMode; i++)
+    {
+        bmap = (Int)bitmapcol[i];
+        if (bmap)
+        {
+            if ((bmap&0xf) == 0)
+                (*(idctcolVCA[bmap>>4]))(ptr);
+            else
+                idct_col(ptr);
+        }
+        ptr++;
+    }
+
+    if ((bitmaprow&0xf) == 0)
+    {
+        if (intra)
+            (*(idctrowVCAIntra[(Int)(bitmaprow>>4)]))(block, rec, lx);
+        else
+            (*(idctrowVCAzmv[(Int)(bitmaprow>>4)]))(block, rec, pred, lx);
+    }
+    else
+    {
+        if (intra)
+            idct_rowIntra(block, rec, lx);
+        else
+            idct_rowzmv(block, rec, pred, lx);
+    }
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp
new file mode 100644
index 0000000..466ce47
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp
@@ -0,0 +1,967 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4enc_lib.h"
+#include "fastquant_inline.h"
+
+#define siz 63
+#define LSL 18
+
+
+const static UChar imask[8] = {128, 64, 32, 16, 8, 4, 2, 1};
+#define SIGN0(a)        ( ((a)<0) ? -1 : (((a)>0) ? 1  : 0) )
+
+/* variable bit precision quantization scale */
+/* used to avoid using 32-bit multiplication */
+const static Short scaleArrayV[32] = {0, 16384, 8192, 5462,  /* 15 */
+                                      4096, 3277, 2731, 2341,
+                                      4096, 3641, 3277, 2979,  /* 16 */
+                                      2731, 2521, 2341, 2185,
+                                      4096, 3856, 3641, 3450,  /* 17 */
+                                      3277, 3121, 2979, 2850,
+                                      5462, 5243, 5042, 4855,  /* 18 */
+                                      4682, 4520, 4370, 4229
+                                     };
+
+/* scale for dc_scaler and qmat, note, no value smaller than 8 */
+const static Short scaleArrayV2[47] = {0, 0, 0, 0, 0, 0, 0, 0, /* 15 */
+                                       4096, 3641, 3277, 2979, 2731, 2521, 2341, 2185,
+                                       4096, 3856, 3641, 3450, 3277, 3121, 2979, 2850,  /* 16 */
+                                       2731, 2622, 2521, 2428, 2341, 2260, 2185, 2115,
+                                       4096, 3972, 3856, 3745, 3641, 3543, 3450, 3361,  /* 17 */
+                                       3277, 3197, 3121, 3049, 2979, 2913, 2850
+                                      };
+
+/* AAN scale and zigzag */
+const static Short AANScale[64] =
+{
+    /* 0 */ 0x1000, 0x0B89, 0x0C3E, 0x0D9B, 0x1000, 0x0A2E, 0x0EC8, 0x0E7F,
+    /* 1 */ 0x0B89, 0x0851, 0x08D4, 0x09CF, 0x0B89, 0x0757, 0x0AA8, 0x0A73,
+    /* 2 */ 0x0C3E, 0x08D4, 0x095F, 0x0A6A, 0x0C3E, 0x07CB, 0x0B50, 0x0B18,
+    /* 3 */ 0x0D9B, 0x09CF, 0x0A6A, 0x0B92, 0x0D9B, 0x08A8, 0x0C92, 0x0C54,
+    /* 4 */ 0x1000, 0x0B89, 0x0C3E, 0x0D9B, 0x1000, 0x0A2E, 0x0EC8, 0x0E7F,
+    /* 5 */ 0x0A2E, 0x0757, 0x07CB, 0x08A8, 0x0A2E, 0x067A, 0x0968, 0x0939,
+    /* 6 */ 0x0EC8, 0x0AA8, 0x0B50, 0x0C92, 0x0EC8, 0x0968, 0x0DA8, 0x0D64,
+    /* 7 */ 0x0E7F, 0x0A73, 0x0B18, 0x0C54, 0x0E7F, 0x0939, 0x0D64, 0x0D23
+};
+
+const static UShort ZZTab[64] =
+{
+    /* 0 */ 0x0, 0x2, 0xA, 0xC, 0x1C, 0x1E, 0x36, 0x38,
+    /* 1 */ 0x4, 0x8, 0xE, 0x1A, 0x20, 0x34, 0x3A, 0x54,
+    /* 2 */ 0x6, 0x10, 0x18, 0x22, 0x32, 0x3C, 0x52, 0x56,
+    /* 3 */ 0x12, 0x16, 0x24, 0x30, 0x3E, 0x50, 0x58, 0x6A,
+    /* 4 */ 0x14, 0x26, 0x2E, 0x40, 0x4E, 0x5A, 0x68, 0x6C,
+    /* 5 */ 0x28, 0x2C, 0x42, 0x4C, 0x5C, 0x66, 0x6E, 0x78,
+    /* 6 */ 0x2A, 0x44, 0x4A, 0x5E, 0x64, 0x70, 0x76, 0x7A,
+    /* 7 */ 0x46, 0x48, 0x60, 0x62, 0x72, 0x74, 0x7C, 0x7E
+};
+
+
+//Tao need to remove, write another version of abs
+//#include <math.h>
+
+/* ======================================================================== */
+/*  Function : cal_dc_scalerENC                                             */
+/*  Date     : 01/25/2000                                                   */
+/*  Purpose  : calculation of DC quantization scale according to the
+               incoming Q and type;                                         */
+/*  In/out   :                                                              */
+/*      Int Qp      Quantizer                                               */
+/*  Return   :                                                              */
+/*          DC Scaler                                                       */
+/*  Modified :                                                              */
+/* ======================================================================== */
+/* ======================================================================== */
+Int cal_dc_scalerENC(Int QP, Int type)
+{
+
+    Int dc_scaler;
+    if (type == 1)
+    {
+        if (QP > 0 && QP < 5)
+            dc_scaler = 8;
+        else if (QP > 4 && QP < 9)
+            dc_scaler = 2 * QP;
+        else if (QP > 8 && QP < 25)
+            dc_scaler = QP + 8;
+        else
+            dc_scaler = 2 * QP - 16;
+    }
+    else
+    {
+        if (QP > 0 && QP < 5)
+            dc_scaler = 8;
+        else if (QP > 4 && QP < 25)
+            dc_scaler = (QP + 13) / 2;
+        else
+            dc_scaler = QP - 6;
+    }
+    return dc_scaler;
+}
+
+
+/***********************************************************************
+ Function: BlckQuantDequantH263
+ Date:     June 15, 1999
+ Purpose:  Combine BlockQuantH263 and BlockDequantH263ENC
+ Input:   coeff=> DCT coefficient
+ Output:  qcoeff=> quantized coefficient
+          rcoeff=> reconstructed coefficient
+          return CBP for this block
+          4/2/01,  correct dc_scaler for short_header mode.
+          5/14/01,
+          changed the division into LUT multiplication/shift and other
+          modifications to speed up fastQuant/DeQuant (check for zero 1st, rowq LUT,
+          fast bitmaprow mask and borrowed Addition method instead of ifs from , ).
+          6/25/01,
+          Further optimization (~100K/QCIF), need more testing/comment before integration.
+
+          7/4/01,  break up Inter / Intra function and merge for different cases.
+          7/22/01,  combine AAN scaling here and reordering.
+          7/24/01, , reorder already done in FDCT, the input here is in the next block and
+            it's the
+            transpose of the raster scan. Output the same order (for proof of concenpt).
+          8/1/01, , change FDCT to do row/column FDCT without reordering, input is still
+            in the next block. The reconstructed DCT output is current block in normal
+            order. The quantized output is in zigzag scan order for INTER, row/column for
+            INTRA. Use bitmapzz for zigzag RunLevel for INTER.  The quantization is done
+            in column/row scanning order.
+          8/2/01, , change IDCT to do column/row, change bitmaprow/col to the opposite.
+          8/3/01, , add clipping to the reconstructed coefficient [-2047,2047]
+          9/4/05, , removed scaling for AAN IDCT, use Chen IDCT instead.
+ ********************************************************************/
+
+Int BlockQuantDequantH263Inter(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+                               UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                               Int dctMode, Int comp, Int dummy, UChar shortHeader)
+{
+    Int i, zz;
+    Int tmp, coeff, q_value;
+    Int QPdiv2 = QuantParam->QPdiv2;
+    Int QPx2 = QuantParam->QPx2;
+    Int Addition = QuantParam->Addition;
+    Int QPx2plus = QuantParam->QPx2plus;
+    Int round = 1 << 15;
+    Int q_scale = scaleArrayV[QuantParam->QP];
+    Int shift = 15 + (QPx2 >> 4);
+    Int *temp;
+    UChar *bcolptr = bitmapcol;
+    Int ac_clip;    /* quantized coeff bound */
+
+    OSCL_UNUSED_ARG(comp);
+    OSCL_UNUSED_ARG(dummy);
+
+
+    if (shortHeader) ac_clip = 126; /* clip between [-127,126] (standard allows 127!) */
+    else ac_clip = 2047;  /* clip between [-2048,2047] */
+
+    /* reset all bitmap to zero */
+    temp = (Int*) bitmapcol;
+    temp[0] = temp[1] = 0;
+    bitmapzz[0] = bitmapzz[1] = 0;
+    *bitmaprow = 0;
+    QPx2plus <<= 4;
+    QPx2plus -= 8;
+
+    rcoeff += 64; /* actual data is 64 item ahead */
+    //end  = rcoeff + dctMode - 1;
+    //rcoeff--;
+    bcolptr--;
+    i = 0;
+
+    do
+    {
+        bcolptr++;
+        //rcoeff++;
+        //i=0;
+        coeff = rcoeff[i];
+        if (coeff == 0x7fff) /* all zero column */
+        {
+            i++;
+            continue;
+        }
+
+        do
+        {
+            if (coeff >= -QPx2plus && coeff < QPx2plus)  /* quantize to zero */
+            {
+                i += 8;
+                if (i < (dctMode << 3))
+                {
+                    coeff = rcoeff[i];
+                    if (coeff > -QPx2plus && coeff < QPx2plus)  /* quantize to zero */
+                    {
+                        i += 8;
+                        coeff = rcoeff[i];
+                        continue;
+                    }
+                    else
+                        goto NONZERO1;
+                }
+            }
+            else
+            {
+NONZERO1:
+                /* scaling */
+                q_value = AANScale[i];  /* load scale AAN */
+                zz = ZZTab[i];  /* zigzag order */
+
+                coeff = aan_scale(q_value, coeff, round, QPdiv2);
+                q_value = coeff_quant(coeff, q_scale, shift);
+
+                /* dequantization  */
+                if (q_value)
+                {
+
+                    //coeff = PV_MIN(ac_clip,PV_MAX(-ac_clip-1, q_value));
+                    q_value = coeff_clip(q_value, ac_clip);
+                    qcoeff[zz>>1] = q_value;
+
+                    // dequant and clip
+                    //coeff = PV_MIN(2047,PV_MAX(-2048, q_value));
+                    tmp = 2047;
+                    coeff = coeff_dequant(q_value, QPx2, Addition, tmp);
+                    rcoeff[i-64] = coeff;
+
+                    (*bcolptr) |= imask[i>>3];
+                    if ((zz >> 1) > 31) bitmapzz[1] |= (1 << (63 - (zz >> 1)));
+                    else        bitmapzz[0] |= (1 << (31 - (zz >> 1)));
+                }
+                i += 8;
+                coeff = rcoeff[i];
+            }
+        }
+        while (i < (dctMode << 3));
+
+        i += (1 - (dctMode << 3));
+    }
+    while (i < dctMode) ;
+
+    i = dctMode;
+    tmp = 1 << (8 - i);
+    while (i--)
+    {
+        if (bitmapcol[i])(*bitmaprow) |= tmp;
+        tmp <<= 1;
+    }
+
+    if (*bitmaprow)
+        return 1;
+    else
+        return 0;
+}
+
+Int BlockQuantDequantH263Intra(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+                               UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                               Int dctMode, Int comp, Int dc_scaler, UChar shortHeader)
+{
+    Int i;
+    Int tmp, coeff, q_value;
+    Int QPx2 = QuantParam->QPx2;
+    Int Addition = QuantParam->Addition;
+    Int QPx2plus = QuantParam->QPx2plus;
+    Int round = 1 << 15;
+    Int q_scale = scaleArrayV[QuantParam->QP];
+    Int shift = 15 + (QPx2 >> 4);
+    UChar *bmcolptr = bitmapcol;
+    Int ac_clip;    /* quantized coeff bound */
+
+    OSCL_UNUSED_ARG(bitmapzz);
+    OSCL_UNUSED_ARG(comp);
+
+
+    if (shortHeader) ac_clip = 126; /* clip between [-127,126] (standard allows 127!) */
+    else ac_clip = 2047;  /* clip between [-2048,2047] */
+
+    *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+    *bitmaprow = 0;
+
+    QPx2plus = QPx2 << 4;
+    QPx2plus -= 8;
+
+    rcoeff += 64; /* actual data is 64 element ahead */
+    i = 0;
+
+    /* DC value */
+    coeff = *rcoeff;
+    /* scaling */
+    if (coeff == 0x7fff && !shortHeader) /* all zero column */
+    {
+        bmcolptr++;
+        i++;
+    }
+    else
+    {
+        if (coeff == 0x7fff) /* shortHeader on */
+        {
+            coeff = 1; /* can't be zero */
+            qcoeff[0] = coeff;
+            coeff = coeff * dc_scaler;
+            coeff = PV_MAX(-2048, PV_MIN(2047, coeff));
+            rcoeff[-64] = coeff;
+            bitmapcol[0] |= 128;
+            bmcolptr++;
+            //qcoeff++;
+            //rcoeff++;
+            //i=0;
+            i++;
+        }
+        else
+        {
+            q_value = round + (coeff << 12);
+            coeff = q_value >> 16;
+            if (coeff >= 0) coeff += (dc_scaler >> 1) ;
+            else            coeff -= (dc_scaler >> 1) ;
+            q_value = scaleArrayV2[dc_scaler];
+            coeff = coeff * q_value;
+            coeff >>= (15 + (dc_scaler >> 4));
+            coeff += ((UInt)coeff >> 31);
+
+            if (shortHeader)
+                coeff = PV_MAX(1, PV_MIN(254, coeff));
+
+            if (coeff)
+            {
+                qcoeff[0] = coeff;
+                coeff = coeff * dc_scaler;
+                coeff = PV_MAX(-2048, PV_MIN(2047, coeff));
+                rcoeff[-64] = coeff;
+                bitmapcol[0] |= 128;
+            }
+            i += 8;
+        }
+    }
+    /* AC values */
+    do
+    {
+        coeff = rcoeff[i];
+        if (coeff == 0x7fff) /* all zero row */
+        {
+            bmcolptr++;
+            i++;
+            continue;
+        }
+        do
+        {
+            if (coeff >= -QPx2plus && coeff < QPx2plus)  /* quantize to zero */
+            {
+                i += 8;
+                if (i < dctMode << 3)
+                {
+                    coeff = rcoeff[i];
+                    if (coeff > -QPx2plus && coeff < QPx2plus)  /* quantize to zero */
+                    {
+                        i += 8;
+                        coeff = rcoeff[i];
+                        continue;
+                    }
+                    else
+                        goto NONZERO2;
+                }
+            }
+            else
+            {
+NONZERO2:   /* scaling */
+                q_value = AANScale[i]; /*  09/02/05 */
+
+                /* scale aan */
+                q_value = smlabb(q_value, coeff, round);
+                coeff = q_value >> 16;
+                /* quant */
+                q_value = smulbb(q_scale, coeff); /*mov     q_value, coeff, lsl #14 */
+                /*smull tmp, coeff, q_value, q_scale*/
+                q_value >>= shift;
+                q_value += ((UInt)q_value >> 31); /* add 1 if negative */
+
+                if (q_value)
+                {
+                    //coeff = PV_MIN(ac_clip,PV_MAX(-ac_clip-1, q_value));
+                    q_value = coeff_clip(q_value, ac_clip);
+                    qcoeff[i] = q_value;
+
+                    // dequant and clip
+                    //coeff = PV_MIN(2047,PV_MAX(-2048, q_value));
+                    tmp = 2047;
+                    coeff = coeff_dequant(q_value, QPx2, Addition, tmp);
+                    rcoeff[i-64] = coeff;
+
+                    (*bmcolptr) |= imask[i>>3];
+                }
+                i += 8;
+                coeff = rcoeff[i];
+            }
+        }
+        while (i < (dctMode << 3)) ;
+
+        //qcoeff++; /* next column */
+        bmcolptr++;
+        //rcoeff++;
+        i += (1 - (dctMode << 3)); //i = 0;
+    }
+    while (i < dctMode);//while(rcoeff < end) ;
+
+    i = dctMode;
+    tmp = 1 << (8 - i);
+    while (i--)
+    {
+        if (bitmapcol[i])(*bitmaprow) |= tmp;
+        tmp <<= 1;
+    }
+
+    if (((*bitmaprow)&127) || (bitmapcol[0]&127)) /* exclude DC */
+        return 1;
+    else
+        return 0;
+}
+
+
+/***********************************************************************
+ Function: BlckQuantDequantH263DC
+ Date:     5/3/2001
+ Purpose:   H.263 quantization mode, only for DC component
+ 6/25/01,
+          Further optimization (~100K/QCIF), need more testing/comment before integration.
+
+ ********************************************************************/
+Int BlockQuantDequantH263DCInter(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+                                 UChar *bitmaprow, UInt *bitmapzz, Int dummy, UChar shortHeader)
+{
+    Int coeff, scale_q;
+    Int CBP = 0;
+    Int QP = QuantParam->QP;
+    Int QPx2plus = QuantParam->QPx2plus;
+    Int Addition = QuantParam->Addition;
+    Int shift = 15 + (QP >> 3);
+    Int ac_clip;    /* quantized coeff bound */
+    Int tmp;
+
+    OSCL_UNUSED_ARG(dummy);
+
+    if (shortHeader) ac_clip = 126; /* clip between [-127,126] (standard allows 127!) */
+    else ac_clip = 2047;  /* clip between [-2048,2047] */
+
+    *bitmaprow = 0;
+    bitmapzz[0] = bitmapzz[1] = 0;
+    coeff = rcoeff[0];
+
+    if (coeff >= -QPx2plus && coeff < QPx2plus)
+    {
+        rcoeff[0] = 0;
+        return CBP;//rcoeff[0] = 0; not needed since CBP will be zero
+    }
+    else
+    {
+        scale_q = scaleArrayV[QP];
+
+        coeff = aan_dc_scale(coeff, QP);
+
+        scale_q = coeff_quant(coeff, scale_q, shift);
+
+        //coeff = PV_MIN(ac_clip,PV_MAX(-ac_clip-1, tmp));
+        scale_q = coeff_clip(scale_q, ac_clip);
+
+        qcoeff[0] = scale_q;
+
+        QP <<= 1;
+        //coeff = PV_MIN(2047,PV_MAX(-2048, tmp));
+        tmp = 2047;
+        coeff = coeff_dequant(scale_q, QP, Addition, tmp);
+
+        rcoeff[0] = coeff;
+
+        (*bitmaprow) = 128;
+        bitmapzz[0] = (ULong)1 << 31;
+        CBP = 1;
+    }
+    return CBP;
+}
+
+
+Int BlockQuantDequantH263DCIntra(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+                                 UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler, UChar shortHeader)
+{
+    Int tmp, coeff;
+
+    OSCL_UNUSED_ARG(QuantParam);
+
+    *bitmaprow = 0;
+    coeff = rcoeff[0];
+
+    if (coeff >= 0) coeff += (dc_scaler >> 1) ;
+    else            coeff -= (dc_scaler >> 1) ;
+    tmp = scaleArrayV2[dc_scaler];
+    tmp = coeff * tmp;
+    tmp >>= (15 + (dc_scaler >> 4));
+    tmp += ((UInt)tmp >> 31);
+
+    if (shortHeader)
+        tmp = PV_MAX(1, PV_MIN(254, tmp));
+
+    if (tmp)
+    {
+        qcoeff[0] = tmp;
+        coeff = tmp * dc_scaler;
+        coeff = PV_MAX(-2048, PV_MIN(2047, coeff));
+        rcoeff[0] = coeff;
+        *bitmaprow = 128;
+        bitmapzz[0] = (ULong)1 << 31;
+    }
+
+    return 0;
+}
+
+#ifndef NO_MPEG_QUANT
+/***********************************************************************
+ Function: BlckQuantDequantMPEG
+ Date:     June 15, 1999
+ Purpose:  Combine BlockQuantMPEG and BlockDequantMPEGENC
+ Input:   coeff=> DCT coefficient
+ Output:  qcoeff=> quantized coefficient
+          rcoeff=> reconstructed coefficient
+ Modified:  7/5/01, break up function for Intra/Inter
+          8/3/01,  update with changes from H263 quant mode.
+          8/3/01,  add clipping to the reconstructed coefficient [-2048,2047]
+          8/6/01,  optimize using multiplicative lookup-table.
+                     can be further optimized using ARM assembly, e.g.,
+                     clipping, 16-bit mult., etc !!!!!!!!!!!!!
+ ********************************************************************/
+
+Int BlockQuantDequantMPEGInter(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+                               UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                               Int dctMode, Int comp, Int dc_scaler)
+{
+    Int i, zz;
+    Int tmp, coeff, q_value = 0;
+    Int sum = 0;
+    Int stepsize, QPx2 = QP << 1;
+    Int CBP = 0;
+    Int round = 1 << 15;
+    Int q_scale = scaleArrayV[QP];
+    Int shift = 15 + (QP >> 3);
+    UChar *bcolptr = bitmapcol;
+
+    OSCL_UNUSED_ARG(dc_scaler);
+    OSCL_UNUSED_ARG(comp);
+
+
+    *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+    bitmapzz[0] = bitmapzz[1] = 0;
+    *bitmaprow = 0;
+
+    rcoeff += 64;
+    i = 0;
+    bcolptr--;
+
+    do
+    {
+        bcolptr++;
+        coeff = rcoeff[i];
+        if (coeff == 0x7fff) /* all zero column */
+        {
+            i++;
+            continue;
+        }
+        do
+        {
+            q_value = AANScale[i];  /*  09/02/05 scaling for AAN*/
+            /* aan scaling */
+            q_value = smlabb(q_value, coeff, round);
+
+            coeff = q_value >> 16;
+
+            stepsize = qmat[i];
+//          if(coeff>0)     coeff = (16*coeff + (stepsize/2)) / stepsize;
+//          else            coeff = (16*coeff - (stepsize/2)) / stepsize;
+            coeff <<= 4;
+            if (coeff >= 0) coeff += (stepsize >> 1) ;
+            else            coeff -= (stepsize >> 1) ;
+            q_value = scaleArrayV2[stepsize];
+            /* mpeg quant table scale */
+            coeff = smulbb(coeff, q_value);
+
+            coeff >>= (15 + (stepsize >> 4));
+            coeff += ((UInt)coeff >> 31);
+
+            /* QP scale */
+            if (coeff >= -QPx2 && coeff < QPx2)  /* quantized to zero*/
+            {
+                i += 8;
+            }
+            else
+            {
+//              q_value = coeff/(QPx2);
+                q_value = coeff_quant(coeff, q_scale, shift);
+
+                if (q_value)                /* dequant */
+                {
+
+                    zz = ZZTab[i];  /* zigzag order */
+
+                    tmp = 2047;
+
+                    q_value = clip_2047(q_value, tmp);
+
+                    qcoeff[zz>>1] = q_value;
+
+                    //q_value=(((coeff*2)+SIGN0(coeff))*stepsize*QP)/16;
+                    /* no need for SIGN0, no zero coming in this {} */
+                    q_value = coeff_dequant_mpeg(q_value, stepsize, QP, tmp);
+
+                    rcoeff[i-64] = q_value;
+
+                    sum += q_value;
+                    (*bcolptr) |= imask[i>>3];
+                    if ((zz >> 1) > 31) bitmapzz[1] |= (1 << (63 - (zz >> 1)));
+                    else        bitmapzz[0] |= (1 << (31 - (zz >> 1)));
+                }
+                i += 8;
+            }
+            coeff = rcoeff[i];
+        }
+        while (i < (dctMode << 3)) ;
+
+        i += (1 - (dctMode << 3));
+    }
+    while (i < dctMode) ;
+
+    i = dctMode;
+    tmp = 1 << (8 - i);
+    while (i--)
+    {
+        if (bitmapcol[i])(*bitmaprow) |= tmp;
+        tmp <<= 1;
+    }
+
+    if (*bitmaprow)
+        CBP = 1;   /* check CBP before mismatch control,  7/5/01 */
+
+    /* Mismatch control,  5/3/01 */
+    if (CBP)
+    {
+        if ((sum&0x1) == 0)
+        {
+            rcoeff--;  /* rcoeff[63] */
+            coeff = *rcoeff;
+            coeff ^= 0x1;
+            *rcoeff = coeff;
+            if (coeff)
+            {
+                bitmapcol[7] |= 1;
+                (*bitmaprow) |= 1;
+            }
+        }
+    }
+
+    return CBP;
+}
+
+Int BlockQuantDequantMPEGIntra(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+                               UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                               Int dctMode, Int comp, Int dc_scaler)
+{
+    Int i;
+    Int tmp, coeff, q_value = 0;
+    Int sum = 0;
+    Int stepsize;
+    Int CBP = 0;
+    Int round = 1 << 15;
+    Int q_scale = scaleArrayV[QP];
+    Int shift = 15 + (QP >> 3);
+    Int round2 = (3 * QP + 2) >> 2;
+    Int QPx2plus = (QP << 1) - round2;
+    UChar *bmcolptr = bitmapcol;
+
+    OSCL_UNUSED_ARG(bitmapzz);
+    OSCL_UNUSED_ARG(comp);
+
+    *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+    *bitmaprow = 0;
+
+    rcoeff += 64;
+    i = 0;
+
+    /* DC value */
+    coeff = *rcoeff;
+
+    if (coeff == 0x7fff) /* all zero column */
+    {
+        bmcolptr++;
+        i++;
+    }
+    else
+    {
+        q_value = round + (coeff << 12);
+        coeff = q_value >> 16;
+        /*if (coeff >= 0)   coeff = (coeff + (dc_scaler/2)) / dc_scaler;
+        else            coeff = (coeff - (dc_scaler/2)) / dc_scaler;*/
+        if (coeff >= 0) coeff += (dc_scaler >> 1) ;
+        else            coeff -= (dc_scaler >> 1) ;
+        q_value = scaleArrayV2[dc_scaler];
+
+        /* mpeg quant table scale */
+        coeff = smulbb(coeff, q_value);
+
+        coeff >>= (15 + (dc_scaler >> 4));
+        coeff += ((UInt)coeff >> 31);
+
+        if (coeff)
+        {
+            coeff = PV_MAX(1, PV_MIN(254, coeff));
+            qcoeff[0] = coeff;
+
+            coeff = smulbb(coeff, dc_scaler);
+
+            q_value = clip_2047(coeff, 2047);
+
+            sum = q_value;
+
+            rcoeff[-64] = q_value;
+
+            bitmapcol[0] |= 128;
+        }
+        i += 8;
+    }
+    /* AC values */
+    do
+    {
+        coeff = rcoeff[i];
+        if (coeff == 0x7fff) /* all zero row */
+        {
+            bmcolptr++;
+            i++;
+            continue;
+        }
+        do
+        {
+            /* scaling */
+            q_value = AANScale[i]; /*  09/02/05 */
+
+            /* q_value = coeff*q_value + round */
+            q_value = smlabb(coeff, q_value, round);
+            coeff = q_value >> 16;
+
+            stepsize = qmat[i];
+            /*if(coeff>0)       coeff = (16*coeff + (stepsize/2)) / stepsize;
+            else            coeff = (16*coeff - (stepsize/2)) / stepsize;*/
+            coeff <<= 4;
+            if (coeff >= 0) coeff += (stepsize >> 1) ;
+            else            coeff -= (stepsize >> 1) ;
+            q_value = scaleArrayV2[stepsize];
+
+            /* scale mpeg quant */
+            coeff = smulbb(coeff, q_value);
+
+            coeff >>= (15 + (stepsize >> 4));
+            coeff += ((UInt)coeff >> 31);
+
+            if (coeff >= -QPx2plus && coeff < QPx2plus)
+            {
+                i += 8;
+            }
+            else
+            {
+                //q_value = ( coeff + SIGN0(coeff)*((3*QP+2)/4))/(2*QP);
+                if (coeff > 0) coeff += round2;
+                else if (coeff < 0) coeff -= round2;
+
+                q_value = smulbb(coeff, q_scale);
+                q_value >>= shift;
+                q_value += ((UInt)q_value >> 31);
+
+                if (q_value)
+                {
+                    tmp = 2047;
+                    q_value = clip_2047(q_value, tmp);
+
+                    qcoeff[i] = q_value;
+
+                    stepsize = smulbb(stepsize, QP);
+                    q_value =  smulbb(q_value, stepsize);
+
+                    q_value = coeff_dequant_mpeg_intra(q_value, tmp);
+                    //q_value = (coeff*stepsize*QP*2)/16;
+
+                    rcoeff[i-64] = q_value;
+
+                    sum += q_value;
+                    (*bmcolptr) |= imask[i>>3];
+                }
+                i += 8;
+            }
+            coeff = rcoeff[i];
+        }
+        while (i < (dctMode << 3)) ;
+
+        bmcolptr++;
+        i += (1 - (dctMode << 3));
+    }
+    while (i < dctMode) ;
+
+    i = dctMode;
+    tmp = 1 << (8 - i);
+    while (i--)
+    {
+        if (bitmapcol[i])(*bitmaprow) |= tmp;
+        tmp <<= 1;
+    }
+
+    if (((*bitmaprow) &127) || (bitmapcol[0]&127))
+        CBP = 1;  /* check CBP before mismatch control,  7/5/01 */
+
+    /* Mismatch control,  5/3/01 */
+    if (CBP || bitmapcol[0])
+    {
+        if ((sum&0x1) == 0)
+        {
+            rcoeff--;  /* rcoeff[63] */
+            coeff = *rcoeff;
+            coeff ^= 0x1;
+            *rcoeff = coeff;
+            if (coeff)
+            {
+                bitmapcol[7] |= 1;
+                (*bitmaprow) |= 1;
+            }
+        }
+    }
+
+    return CBP;
+}
+
+
+/***********************************************************************
+ Function: BlckQuantDequantMPEGDC
+ Date:     5/3/2001
+ Purpose:  MPEG Quant/Dequant for DC only block.
+ ********************************************************************/
+Int BlockQuantDequantMPEGDCInter(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+                                 UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dummy)
+{
+    Int q_value, coeff, stepsize;
+    Int CBP = 0;
+    Int q_scale = scaleArrayV[QP];
+    Int shift = 15 + (QP >> 3);
+    Int QPx2 = QP << 1;
+
+    OSCL_UNUSED_ARG(dummy);
+
+    *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+    *bitmaprow = 0;
+    bitmapzz[0] = bitmapzz[1] = 0;
+    coeff = rcoeff[0];
+    stepsize = qmat[0];
+
+    /*if(coeff>0)       coeff = (16*coeff + (stepsize/2)) / stepsize;
+    else            coeff = (16*coeff - (stepsize/2)) / stepsize;*/
+    coeff <<= 4;
+    if (coeff >= 0) coeff += (stepsize >> 1) ;
+    else            coeff -= (stepsize >> 1) ;
+    q_value = scaleArrayV2[stepsize];
+
+    coeff = smulbb(coeff, q_value);
+
+    coeff >>= (15 + (stepsize >> 4));
+    coeff += ((UInt)coeff >> 31);
+
+    if (coeff >= -QPx2 && coeff < QPx2)
+    {
+        rcoeff[0] = 0;
+        return CBP;
+    }
+    else
+    {
+//      q_value = coeff/(QPx2);
+        q_value = coeff_quant(coeff, q_scale, shift);
+
+        if (q_value)
+        {
+
+            //PV_MIN(2047,PV_MAX(-2048, q_value));
+            q_value = clip_2047(q_value, 2047);
+            qcoeff[0] = q_value;
+            q_value = coeff_dequant_mpeg(q_value, stepsize, QP, 2047);
+            //q_value=(((coeff*2)+SIGN0(coeff))*stepsize*QP)/16;
+            rcoeff[0] = q_value;
+
+            bitmapcol[0] = 128;
+            (*bitmaprow) = 128;
+            bitmapzz[0] = (UInt)1 << 31;
+            CBP = 1;
+
+            /* Mismatch control,  5/3/01 */
+            if ((q_value&0x1) == 0)
+            {
+                rcoeff[63] = 1; /* after scaling it remains the same */
+                bitmapcol[7] |= 1;
+                (*bitmaprow) |= 1;
+            }
+        }
+    }
+    return CBP;
+}
+
+
+Int BlockQuantDequantMPEGDCIntra(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+                                 UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                                 Int dc_scaler)
+{
+    Int tmp, coeff, q_value;
+
+    OSCL_UNUSED_ARG(QP);
+    OSCL_UNUSED_ARG(qmat);
+
+
+    *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+    *bitmaprow = 0;
+    coeff = rcoeff[0];
+
+    /*if (coeff >= 0)   tmp = (coeff + dc_scaler/2) / dc_scaler;
+    else            tmp = (coeff - dc_scaler/2) / dc_scaler;*/
+    if (coeff >= 0) coeff += (dc_scaler >> 1) ;
+    else            coeff -= (dc_scaler >> 1) ;
+    tmp = scaleArrayV2[dc_scaler];
+
+    tmp = smulbb(tmp, coeff);
+    tmp >>= (15 + (dc_scaler >> 4));
+    tmp += ((UInt)tmp >> 31);
+
+    if (tmp)
+    {
+        coeff = PV_MAX(1, PV_MIN(254, tmp));
+        qcoeff[0] = coeff;
+
+        q_value = smulbb(coeff, dc_scaler);
+        q_value = clip_2047(q_value, 2047);
+        rcoeff[0] = q_value;
+        bitmapcol[0] = 128;
+        *bitmaprow = 128;
+        bitmapzz[0] = (UInt)1 << 31;
+
+        /* Mismatch control,  5/3/01 */
+        if ((q_value&0x1) == 0)
+        {
+            rcoeff[63] = 1; /* after scaling it remains the same */
+            bitmapcol[7] |= 1;
+            (*bitmaprow) |= 1;
+        }
+    }
+
+    return 0;
+}
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h
new file mode 100644
index 0000000..79d0ebf
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h
@@ -0,0 +1,625 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/*  Filename: fastquant_inline.h                                                        */
+/*  Description: Implementation for in-line functions used in dct.cpp           */
+/*  Modified:                                                                   */
+/*********************************************************************************/
+#ifndef _FASTQUANT_INLINE_H_
+#define _FASTQUANT_INLINE_H_
+
+#include "mp4def.h"
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) /* ARM GNU COMPILER  */
+
+__inline int32 aan_scale(int32 q_value, int32 coeff, int32 round, int32 QPdiv2)
+{
+    q_value = coeff * q_value + round;
+    coeff = q_value >> 16;
+    if (coeff < 0)  coeff += QPdiv2;
+    else            coeff -= QPdiv2;
+
+    return coeff;
+}
+
+
+__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
+{
+    int32 q_value;
+
+    q_value = coeff * q_scale;      //q_value = -((-(coeff + QPdiv2)*q_scale)>>LSL);
+    q_value >>= shift;                  //q_value = (((coeff - QPdiv2)*q_scale)>>LSL );
+    q_value += ((UInt)q_value >> 31); /* add one if negative */
+
+    return q_value;
+}
+
+__inline int32  coeff_clip(int32 q_value, int32 ac_clip)
+{
+    int32 coeff = q_value + ac_clip;
+
+    if ((UInt)coeff > (UInt)(ac_clip << 1))
+        q_value = ac_clip ^(q_value >> 31);
+
+    return q_value;
+}
+
+__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
+{
+    int32 coeff;
+
+    OSCL_UNUSED_ARG(tmp);
+
+    if (q_value < 0)
+    {
+        coeff = q_value * QPx2 - Addition;
+        if (coeff < -2048)
+            coeff = -2048;
+    }
+    else
+    {
+        coeff = q_value * QPx2 + Addition;
+        if (coeff > 2047)
+            coeff = 2047;
+    }
+    return coeff;
+}
+
+__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
+{
+    q_value = coeff * q_value + round;
+
+    return q_value;
+}
+
+__inline int32 smulbb(int32 q_scale, int32 coeff)
+{
+    int32 q_value;
+
+    q_value = coeff * q_scale;
+
+    return q_value;
+}
+
+__inline int32 aan_dc_scale(int32 coeff, int32 QP)
+{
+
+    if (coeff < 0)  coeff += (QP >> 1);
+    else            coeff -= (QP >> 1);
+
+    return coeff;
+}
+
+__inline int32 clip_2047(int32 q_value, int32 tmp)
+{
+    OSCL_UNUSED_ARG(tmp);
+
+    if (q_value < -2048)
+    {
+        q_value = -2048;
+    }
+    else if (q_value > 2047)
+    {
+        q_value = 2047;
+    }
+
+    return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
+{
+    int32 coeff;
+
+    OSCL_UNUSED_ARG(tmp);
+
+    coeff = q_value << 1;
+    stepsize *= QP;
+    if (coeff > 0)
+    {
+        q_value = (coeff + 1) * stepsize;
+        q_value >>= 4;
+        if (q_value > 2047) q_value = 2047;
+    }
+    else
+    {
+        q_value = (coeff - 1) * stepsize;
+        q_value += 15;
+        q_value >>= 4;
+        if (q_value < -2048)    q_value = -2048;
+    }
+
+    return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
+{
+    OSCL_UNUSED_ARG(tmp);
+
+    q_value <<= 1;
+    if (q_value > 0)
+    {
+        q_value >>= 4;
+        if (q_value > 2047) q_value = 2047;
+    }
+    else
+    {
+        q_value += 15;
+        q_value >>= 4;
+        if (q_value < -2048) q_value = -2048;
+    }
+
+    return q_value;
+}
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+#if defined(__TARGET_ARCH_5TE)
+
+__inline int32 aan_scale(int32 q_value, int32 coeff,
+                         int32 round, int32 QPdiv2)
+{
+    __asm
+    {
+        smlabb q_value, coeff, q_value, round
+        movs       coeff, q_value, asr #16
+        addle   coeff, coeff, QPdiv2
+        subgt   coeff, coeff, QPdiv2
+    }
+
+    return coeff;
+}
+
+__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
+{
+    int32 q_value;
+
+    __asm
+    {
+        smulbb  q_value, q_scale, coeff    /*mov    coeff, coeff, lsl #14*/
+        mov     coeff, q_value, asr shift   /*smull tmp, coeff, q_scale, coeff*/
+        add q_value, coeff, coeff, lsr #31
+    }
+
+
+    return q_value;
+}
+
+__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
+{
+    int32 coeff;
+
+    __asm
+    {
+        cmp     q_value, #0
+        smulbb  coeff, q_value, QPx2
+        sublt   coeff, coeff, Addition
+        addge   coeff, coeff, Addition
+        add     q_value, coeff, tmp
+        subs    q_value, q_value, #3840
+        subcss  q_value, q_value, #254
+        eorhi   coeff, tmp, coeff, asr #31
+    }
+
+    return coeff;
+}
+
+__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
+{
+    __asm
+    {
+        smlabb q_value, coeff, q_value, round
+    }
+
+    return q_value;
+}
+
+__inline int32 smulbb(int32 q_scale, int32 coeff)
+{
+    int32 q_value;
+
+    __asm
+    {
+        smulbb  q_value, q_scale, coeff
+    }
+
+    return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
+{
+    /* tmp must have value of 2047 */
+    int32 coeff;
+    __asm
+    {
+        movs    coeff, q_value, lsl #1
+        smulbb  stepsize, stepsize, QP
+        addgt   coeff, coeff, #1
+        sublt   coeff, coeff, #1
+        smulbb  q_value, coeff, stepsize
+        addlt   q_value, q_value, #15
+        mov     q_value, q_value, asr #4
+        add     coeff, q_value, tmp
+        subs    coeff, coeff, #0xf00
+        subcss  coeff, coeff, #0xfe
+        eorhi   q_value, tmp, q_value, asr #31
+    }
+
+    return q_value;
+}
+
+
+#else // not ARMV5TE
+
+__inline int32 aan_scale(int32 q_value, int32 coeff,
+                         int32 round, int32 QPdiv2)
+{
+    __asm
+    {
+        mla q_value, coeff, q_value, round
+        movs       coeff, q_value, asr #16
+        addle   coeff, coeff, QPdiv2
+        subgt   coeff, coeff, QPdiv2
+    }
+
+    return coeff;
+}
+
+__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
+{
+    int32 q_value;
+
+    __asm
+    {
+        mul q_value, q_scale, coeff    /*mov    coeff, coeff, lsl #14*/
+        mov     coeff, q_value, asr shift   /*smull tmp, coeff, q_scale, coeff*/
+        add q_value, coeff, coeff, lsr #31
+    }
+
+
+    return q_value;
+}
+
+
+__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
+{
+    int32 coeff;
+
+    __asm
+    {
+        cmp     q_value, #0
+        mul coeff, q_value, QPx2
+        sublt   coeff, coeff, Addition
+        addge   coeff, coeff, Addition
+        add     q_value, coeff, tmp
+        subs    q_value, q_value, #3840
+        subcss  q_value, q_value, #254
+        eorhi   coeff, tmp, coeff, asr #31
+    }
+
+    return coeff;
+}
+
+__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
+{
+    __asm
+    {
+        mla q_value, coeff, q_value, round
+    }
+
+    return q_value;
+}
+
+__inline int32 smulbb(int32 q_scale, int32 coeff)
+{
+    int32 q_value;
+
+    __asm
+    {
+        mul q_value, q_scale, coeff
+    }
+
+    return q_value;
+}
+
+
+__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
+{
+    /* tmp must have value of 2047 */
+    int32 coeff;
+    __asm
+    {
+        movs    coeff, q_value, lsl #1
+        mul  stepsize, stepsize, QP
+        addgt   coeff, coeff, #1
+        sublt   coeff, coeff, #1
+        mul q_value, coeff, stepsize
+        addlt   q_value, q_value, #15
+        mov     q_value, q_value, asr #4
+        add     coeff, q_value, tmp
+        subs    coeff, coeff, #0xf00
+        subcss  coeff, coeff, #0xfe
+        eorhi   q_value, tmp, q_value, asr #31
+    }
+
+    return q_value;
+}
+
+
+#endif
+
+__inline int32  coeff_clip(int32 q_value, int32 ac_clip)
+{
+    int32 coeff;
+
+    __asm
+    {
+        add     coeff, q_value, ac_clip
+        subs    coeff, coeff, ac_clip, lsl #1
+        eorhi   q_value, ac_clip, q_value, asr #31
+    }
+
+    return q_value;
+}
+
+__inline int32 aan_dc_scale(int32 coeff, int32 QP)
+{
+
+    __asm
+    {
+        cmp   coeff, #0
+        addle   coeff, coeff, QP, asr #1
+        subgt   coeff, coeff, QP, asr #1
+    }
+
+    return coeff;
+}
+
+__inline int32 clip_2047(int32 q_value, int32 tmp)
+{
+    /* tmp must have value of 2047 */
+    int32 coeff;
+
+    __asm
+    {
+        add     coeff, q_value, tmp
+        subs    coeff, coeff, #0xf00
+        subcss  coeff, coeff, #0xfe
+        eorhi   q_value, tmp, q_value, asr #31
+    }
+
+    return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
+{
+    int32 coeff;
+
+    __asm
+    {
+        movs    q_value, q_value, lsl #1
+        addlt   q_value, q_value, #15
+        mov     q_value, q_value, asr #4
+        add     coeff, q_value, tmp
+        subs    coeff, coeff, #0xf00
+        subcss  coeff, coeff, #0xfe
+        eorhi   q_value, tmp, q_value, asr #31
+    }
+
+    return q_value;
+}
+
+#elif ( defined(PV_ARM_GCC_V4) || defined(PV_ARM_GCC_V5) ) /* ARM GNU COMPILER  */
+
+__inline int32 aan_scale(int32 q_value, int32 coeff,
+                         int32 round, int32 QPdiv2)
+{
+    register int32 out;
+    register int32 qv = q_value;
+    register int32 cf = coeff;
+    register int32 rr = round;
+    register int32 qp = QPdiv2;
+
+    asm volatile("smlabb %0, %2, %1, %3\n\t"
+                 "movs %0, %0, asr #16\n\t"
+                 "addle %0, %0, %4\n\t"
+                 "subgt %0, %0, %4"
+             : "=&r"(out)
+                         : "r"(qv),
+                         "r"(cf),
+                         "r"(rr),
+                         "r"(qp));
+    return out;
+}
+
+__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
+{
+    register int32 out;
+    register int32 temp1;
+    register int32 cc = coeff;
+    register int32 qs = q_scale;
+    register int32 ss = shift;
+
+    asm volatile("smulbb %0, %3, %2\n\t"
+                 "mov %1, %0, asr %4\n\t"
+                 "add %0, %1, %1, lsr #31"
+             : "=&r"(out),
+                 "=&r"(temp1)
+                         : "r"(cc),
+                         "r"(qs),
+                         "r"(ss));
+
+    return out;
+}
+
+__inline int32 coeff_clip(int32 q_value, int32 ac_clip)
+{
+    register int32 coeff;
+
+    asm volatile("add   %1, %0, %2\n\t"
+                 "subs  %1, %1, %2, lsl #1\n\t"
+                 "eorhi %0, %2, %0, asr #31"
+             : "+r"(q_value),
+                 "=&r"(coeff)
+                         : "r"(ac_clip));
+
+    return q_value;
+}
+
+__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
+{
+    register int32 out;
+    register int32 temp1;
+    register int32 qv = q_value;
+    register int32 qp = QPx2;
+    register int32 aa = Addition;
+    register int32 tt = tmp;
+
+    asm volatile("cmp    %2, #0\n\t"
+                 "mul    %0, %2, %3\n\t"
+                 "sublt  %0, %0, %4\n\t"
+                 "addge  %0, %0, %4\n\t"
+                 "add    %1, %0, %5\n\t"
+                 "subs   %1, %1, #3840\n\t"
+                 "subcss %1, %1, #254\n\t"
+                 "eorhi  %0, %5, %0, asr #31"
+             : "=&r"(out),
+                 "=&r"(temp1)
+                         : "r"(qv),
+                         "r"(qp),
+                         "r"(aa),
+                         "r"(tt));
+
+    return out;
+}
+
+__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
+{
+    register int32 out;
+    register int32 aa = (int32)q_value;
+    register int32 bb = (int32)coeff;
+    register int32 cc = (int32)round;
+
+    asm volatile("smlabb %0, %1, %2, %3"
+             : "=&r"(out)
+                         : "r"(aa),
+                         "r"(bb),
+                         "r"(cc));
+    return out;
+}
+
+__inline int32 smulbb(int32 q_scale, int32 coeff)
+{
+    register int32 out;
+    register int32 aa = (int32)q_scale;
+    register int32 bb = (int32)coeff;
+
+    asm volatile("smulbb %0, %1, %2"
+             : "=&r"(out)
+                         : "r"(aa),
+                         "r"(bb));
+    return out;
+}
+
+__inline int32 aan_dc_scale(int32 coeff, int32 QP)
+{
+    register int32 out;
+    register int32 cc = coeff;
+    register int32 qp = QP;
+
+    asm volatile("cmp %1, #0\n\t"
+                 "addle %0, %1, %2, asr #1\n\t"
+                 "subgt %0, %1, %2, asr #1"
+             : "=&r"(out)
+                         : "r"(cc),
+                         "r"(qp));
+    return out;
+}
+
+__inline int32 clip_2047(int32 q_value, int32 tmp)
+{
+    register int32 coeff;
+    asm volatile("add    %1, %0, %2\n\t"
+                 "subs   %1, %1, #0xF00\n\t"
+                 "subcss %1, %1, #0xFE\n\t"
+                 "eorhi  %0, %2, %0, asr #31"
+             : "+r"(q_value),
+                 "=&r"(coeff)
+                         : "r"(tmp));
+
+    return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
+{
+    register int32 out;
+    register int32 temp1;
+    register int32 qv = q_value;
+    register int32 ss = stepsize;
+    register int32 qp = QP;
+    register int32 tt = tmp;
+
+    asm volatile("movs    %1, %2, lsl #1\n\t"
+                 "mul     %0, %3, %4\n\t"
+                 "addgt   %1, %1, #1\n\t"
+                 "sublt   %1, %1, #1\n\t"
+                 "mul     %0, %1, %0\n\t"
+                 "addlt   %0, %0, #15\n\t"
+                 "mov     %0, %0, asr #4\n\t"
+                 "add     %1, %0, %5\n\t"
+                 "subs    %1, %1, #0xF00\n\t"
+                 "subcss  %1, %1, #0xFE\n\t"
+                 "eorhi   %0, %5, %0, asr #31"
+             : "=&r"(out),
+                 "=&r"(temp1)
+                         : "r"(qv),
+                         "r"(ss),
+                         "r"(qp),
+                         "r"(tt));
+
+    return out;
+
+}
+
+__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
+{
+    register int32 out;
+    register int32 temp1;
+    register int32 qv = q_value;
+    register int32 tt = tmp;
+
+    asm volatile("movs    %1, %2, lsl #1\n\t"
+                 "addlt   %1, %1, #15\n\t"
+                 "mov     %0, %1, asr #4\n\t"
+                 "add     %1, %0, %3\n\t"
+                 "subs    %1, %1, #0xF00\n\t"
+                 "subcss  %1, %1, #0xFE\n\t"
+                 "eorhi   %0, %3, %0, asr #31"
+             : "=&r"(out),
+                 "=&r"(temp1)
+                         : "r"(qv),
+                         "r"(tt));
+    return out;
+}
+
+
+#endif // Platform
+
+
+#endif //_FASTQUANT_INLINE_H_
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp
new file mode 100644
index 0000000..319c76f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp
@@ -0,0 +1,287 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "m4venc_oscl.h"
+
+/* 3/29/01 fast half-pel search based on neighboring guess */
+/* value ranging from 0 to 4, high complexity (more accurate) to
+   low complexity (less accurate) */
+#define HP_DISTANCE_TH      2  /* half-pel distance threshold */
+
+#define PREF_16_VEC 129     /* 1MV bias versus 4MVs*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    void GenerateSearchRegion(UChar *searchPadding, UChar *ref, Int width, Int height,
+    Int ilow, Int ihigh, Int jlow, Int jhigh);
+
+    void InterpDiag(UChar *prev, Int lx, UChar *pred_block);
+    void InterpHorz(UChar *prev, Int lx, UChar *pred_block);
+    void InterpVert(UChar *prev, Int lx, UChar *pred_block);
+#ifdef __cplusplus
+}
+#endif
+
+
+const static Int distance_tab[9][9] =   /* [hp_guess][k] */
+{
+    {0, 1, 1, 1, 1, 1, 1, 1, 1},
+    {1, 0, 1, 2, 3, 4, 3, 2, 1},
+    {1, 0, 0, 0, 1, 2, 3, 2, 1},
+    {1, 2, 1, 0, 1, 2, 3, 4, 3},
+    {1, 2, 1, 0, 0, 0, 1, 2, 3},
+    {1, 4, 3, 2, 1, 0, 1, 2, 3},
+    {1, 2, 3, 2, 1, 0, 0, 0, 1},
+    {1, 2, 3, 4, 3, 2, 1, 0, 1},
+    {1, 0, 1, 2, 3, 2, 1, 0, 0}
+};
+
+
+/*=====================================================================
+    Function:   FindHalfPelMB
+    Date:       10/7/2000
+    Purpose:    Find half pel resolution MV surrounding the full-pel MV
+=====================================================================*/
+
+void FindHalfPelMB(VideoEncData *video, UChar *cur, MOT *mot, UChar *ncand,
+                   Int xpos, Int ypos, Int *xhmin, Int *yhmin, Int hp_guess)
+{
+//  hp_mem = ULong *vertArray; /* 20x17 */
+//           ULong *horzArray; /* 20x16 */
+//           ULong *diagArray; /* 20x17 */
+    Int dmin, d;
+
+    Int xh, yh;
+    Int k, kmin = 0;
+    Int imin, jmin, ilow, jlow;
+    Int h263_mode = video->encParams->H263_Enabled; /*  3/29/01 */
+    Int in_range[9] = {0, 1, 1, 1, 1, 1, 1, 1, 1}; /*  3/29/01 */
+    Int range = video->encParams->SearchRange;
+    Int lx = video->currVop->pitch;
+    Int width = video->currVop->width; /*  padding */
+    Int height = video->vol[video->currLayer]->height;
+    Int(**SAD_MB_HalfPel)(UChar*, UChar*, Int, void*) =
+        video->functionPointer->SAD_MB_HalfPel;
+    void *extra_info = video->sad_extra_info;
+
+    Int next_hp_pos[9][2] = {{0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}, {0, -1}};
+    Int next_ncand[9] = {0, 1 , lx, lx, 0, -1, -1, -lx, -lx};
+
+    cur = video->currYMB;
+
+    /**************** check range ***************************/
+    /*  3/29/01 */
+    imin = xpos + (mot[0].x >> 1);
+    jmin = ypos + (mot[0].y >> 1);
+    ilow = xpos - range;
+    jlow = ypos - range;
+
+    if (!h263_mode)
+    {
+        if (imin <= -15 || imin == ilow)
+            in_range[1] = in_range[7] = in_range[8] = 0;
+        else if (imin >= width - 1)
+            in_range[3] = in_range[4] = in_range[5] = 0;
+        if (jmin <= -15 || jmin == jlow)
+            in_range[1] = in_range[2] = in_range[3] = 0;
+        else if (jmin >= height - 1)
+            in_range[5] = in_range[6] = in_range[7] = 0;
+    }
+    else
+    {
+        if (imin <= 0 || imin == ilow)
+            in_range[1] = in_range[7] = in_range[8] = 0;
+        else if (imin >= width - 16)
+            in_range[3] = in_range[4] = in_range[5] = 0;
+        if (jmin <= 0 || jmin == jlow)
+            in_range[1] = in_range[2] = in_range[3] = 0;
+        else if (jmin >= height - 16)
+            in_range[5] = in_range[6] = in_range[7] = 0;
+    }
+
+    xhmin[0] = 0;
+    yhmin[0] = 0;
+    dmin = mot[0].sad;
+
+    xh = 0;
+    yh = -1;
+    ncand -= lx; /* initial position */
+
+    for (k = 2; k <= 8; k += 2)
+    {
+        if (distance_tab[hp_guess][k] < HP_DISTANCE_TH)
+        {
+            if (in_range[k])
+            {
+                d = (*(SAD_MB_HalfPel[((yh&1)<<1)+(xh&1)]))(ncand, cur, (dmin << 16) | lx, extra_info);
+
+                if (d < dmin)
+                {
+                    dmin = d;
+                    xhmin[0] = xh;
+                    yhmin[0] = yh;
+                    kmin = k;
+                }
+                else if (d == dmin &&
+                         PV_ABS(mot[0].x + xh) + PV_ABS(mot[0].y + yh) < PV_ABS(mot[0].x + xhmin[0]) + PV_ABS(mot[0].y + yhmin[0]))
+                {
+                    xhmin[0] = xh;
+                    yhmin[0] = yh;
+                    kmin = k;
+                }
+
+            }
+        }
+        xh += next_hp_pos[k][0];
+        yh += next_hp_pos[k][1];
+        ncand += next_ncand[k];
+
+        if (k == 8)
+        {
+            if (xhmin[0] != 0 || yhmin[0] != 0)
+            {
+                k = -1;
+                hp_guess = kmin;
+            }
+        }
+    }
+
+    mot[0].sad = dmin;
+    mot[0].x += xhmin[0];
+    mot[0].y += yhmin[0];
+
+    return ;
+}
+
+#ifndef NO_INTER4V
+/*=====================================================================
+    Function:   FindHalfPelBlk
+    Date:       10/7/2000
+    Purpose:    Find half pel resolution MV surrounding the full-pel MV
+                And decide between 1MV or 4MV mode
+=====================================================================*/
+///// THIS FUNCTION IS NOT WORKING!!! NEED TO BE RIVISITED
+
+Int FindHalfPelBlk(VideoEncData *video, UChar *cur, MOT *mot, Int sad16, UChar *ncand8[],
+                   UChar *mode, Int xpos, Int ypos, Int *xhmin, Int *yhmin, UChar *hp_mem)
+{
+    Int k, comp;
+    Int xh, yh;//, xhmin, yhmin;
+    Int imin, jmin, ilow, jlow;
+    Int height;
+    UChar *cand, *cur8;
+    UChar *hmem;//[17*17]; /* half-pel memory */
+    Int d, dmin, sad8;
+    Int lx = video->currVop->pitch;
+    Int width = video->currVop->width; /* , padding */
+    Int(*SAD_Blk_HalfPel)(UChar*, UChar*, Int, Int, Int, Int, Int, void*) = video->functionPointer->SAD_Blk_HalfPel;
+    void *extra_info = video->sad_extra_info;
+    Int in_range[8]; /*  3/29/01 */
+    Int range = video->encParams->SearchRange;
+    Int swidth;
+    Int next_hp_pos[8][2] = {{1, 0}, {1, 0}, {0, 1}, {0, 1}, { -1, 0}, { -1, 0}, {0, -1}, {0, -1}};
+
+    height = video->vol[video->currLayer]->height;
+
+    hmem = hp_mem;
+    sad8 = 0;
+    for (comp = 0; comp < 4; comp++)
+    {
+#ifdef _SAD_STAT
+        num_HP_Blk++;
+#endif
+        /**************** check range ***************************/
+        /*  3/29/01 */
+        M4VENC_MEMSET(in_range, 1, sizeof(Int) << 3);
+        imin = xpos + ((comp & 1) << 3) + (mot[comp+1].x >> 1);
+        jmin = ypos + ((comp & 2) << 2) + (mot[comp+1].y >> 1);
+        ilow = xpos + ((comp & 1) << 3) - range;
+        jlow = ypos + ((comp & 2) << 2) - range;
+
+        if (imin <= -15 || imin == ilow)
+            in_range[0] = in_range[6] = in_range[7] = 0;
+        else if (imin >= width - 1)
+            in_range[2] = in_range[3] = in_range[4] = 0;
+
+        if (jmin <= -15 || jmin == jlow)
+            in_range[0] = in_range[1] = in_range[2] = 0;
+        else if (jmin >= height - 1)
+            in_range[4] = in_range[5] = in_range[6] = 0;
+
+        /**************** half-pel search ***********************/
+        cur8 = cur + ((comp & 1) << 3) + ((comp & 2) << 2) * width ;
+
+        /* generate half-pel search region */
+        {
+            cand = ncand8[comp+1];
+            swidth = lx;
+        }
+
+        xhmin[comp+1] = 0;
+        yhmin[comp+1] = 0;
+        dmin = mot[comp+1].sad;
+
+        xh = -1;
+        yh = -1;
+        for (k = 0; k < 8; k++)
+        {
+            if (in_range[k])
+            {
+                d = (*SAD_Blk_HalfPel)(cand, cur8, dmin, lx, swidth, xh, yh, extra_info);
+
+                if (d < dmin)
+                {
+                    dmin = d;
+                    xhmin[comp+1] = xh;
+                    yhmin[comp+1] = yh;
+                }
+            }
+            xh += next_hp_pos[k][0];
+            yh += next_hp_pos[k][1];
+        }
+        /********************************************/
+        mot[comp+1].x += xhmin[comp+1];
+        mot[comp+1].y += yhmin[comp+1];
+        mot[comp+1].sad = dmin;
+        sad8 += dmin;
+
+        if (sad8 >= sad16 - PREF_16_VEC)
+        {
+            *mode = MODE_INTER;
+            for (k = 1; k <= 4; k++)
+            {
+                mot[k].sad = (mot[0].sad + 2) >> 2;
+                mot[k].x = mot[0].x;
+                mot[k].y = mot[0].y;
+            }
+            return sad8;
+        }
+
+        hmem += (10 * 10);
+    }
+
+    *mode = MODE_INTER4V;
+
+    return sad8;
+}
+#endif /* NO_INTER4V */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h b/media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h
new file mode 100644
index 0000000..c9e18d5
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h
@@ -0,0 +1,43 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/* Revision History                                                             */
+/* Date: 11/04/05                                                               */
+/* Description: Created for abstracting out OSCL such that the code can be used */
+/*          by both V3 and V4 OSCL library. This file is for V4.                */
+/*********************************************************************************/
+
+#ifndef _M4VENC_OSCL_H_
+#define _M4VENC_OSCL_H_
+
+#include <stdlib.h>
+#include <math.h>
+
+#define M4VENC_MALLOC(size)             malloc(size)
+#define M4VENC_FREE(ptr)                free(ptr)
+
+#define M4VENC_MEMSET(ptr,val,size)     memset(ptr,val,size)
+#define M4VENC_MEMCPY(dst,src,size)     memcpy(dst,src,size)
+
+#define M4VENC_LOG(x)                   log(x)
+#define M4VENC_SQRT(x)                  sqrt(x)
+#define M4VENC_POW(x,y)                 pow(x,y)
+
+#define M4VENC_HAS_SYMBIAN_SUPPORT  OSCL_HAS_SYMBIAN_SUPPORT
+
+#endif //_M4VENC_OSCL_H_
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp
new file mode 100644
index 0000000..6dab31a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp
@@ -0,0 +1,386 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "m4venc_oscl.h"
+
+#define VOP_OFFSET  ((lx<<4)+16)  /* for offset to image area */
+#define CVOP_OFFSET ((lx<<2)+8)
+
+#define PREF_INTRA  512     /* bias for INTRA coding */
+
+/*===============================================================
+    Function:   ChooseMode
+    Date:       09/21/2000
+    Purpose:    Choosing between INTRA or INTER
+    Input/Output: Pointer to the starting point of the macroblock.
+    Note:
+===============================================================*/
+void ChooseMode_C(UChar *Mode, UChar *cur, Int lx, Int min_SAD)
+{
+    Int i, j;
+    Int MB_mean, A, tmp, Th;
+    Int offset = (lx >> 2) - 4;
+    UChar *p = cur;
+    Int *pint = (Int *) cur, temp = 0;
+    MB_mean = 0;
+    A = 0;
+    Th = (min_SAD - PREF_INTRA) >> 1;
+
+    for (j = 0; j < 8; j++)
+    {
+
+        /* Odd Rows */
+        temp += (*pint++) & 0x00FF00FF;
+        temp += (*pint++) & 0x00FF00FF;
+        temp += (*pint++) & 0x00FF00FF;
+        temp += (*pint++) & 0x00FF00FF;
+        pint += offset;
+
+        /* Even Rows */
+        temp += (*pint++ >> 8) & 0x00FF00FF;
+        temp += (*pint++ >> 8) & 0x00FF00FF;
+        temp += (*pint++ >> 8) & 0x00FF00FF;
+        temp += (*pint++ >> 8) & 0x00FF00FF;
+        pint += offset;
+
+    }
+
+    MB_mean = (((temp & 0x0000FFFF)) + ((temp & 0xFFFF0000) >> 16)) >> 7;
+
+    p = cur;
+    offset = lx - 16;
+    for (j = 0; j < 16; j++)
+    {
+        temp = (j & 1);
+        p += temp;
+        i = 8;
+        while (i--)
+        {
+            tmp = *p - MB_mean;
+            p += 2;
+            if (tmp > 0) A += tmp;
+            else    A -= tmp;
+        }
+
+        if (A >= Th)
+        {
+            *Mode = MODE_INTER;
+            return ;
+        }
+        p += (offset - temp);
+    }
+
+    if (A < Th)
+        *Mode = MODE_INTRA;
+    else
+        *Mode = MODE_INTER;
+
+    return ;
+}
+
+
+/*===============================================================
+    Function:   GetHalfPelMBRegion
+    Date:       09/17/2000
+    Purpose:    Interpolate the search region for half-pel search
+    Input/Output:   Center of the search, Half-pel memory, width
+    Note:       rounding type should be parameterized.
+                Now fixed it to zero!!!!!!
+
+===============================================================*/
+
+
+void GetHalfPelMBRegion_C(UChar *cand, UChar *hmem, Int lx)
+{
+    Int i, j;
+    UChar *p1, *p2, *p3, *p4;
+    UChar *hmem1 = hmem;
+    UChar *hmem2 = hmem1 + 33;
+    Int offset = lx - 17;
+
+    p1 = cand - lx - 1;
+    p2 = cand - lx;
+    p3 = cand - 1;
+    p4 = cand;
+
+    for (j = 0; j < 16; j++)
+    {
+        for (i = 0; i < 16; i++)
+        {
+            *hmem1++ = ((*p1++) + *p2 + *p3 + *p4 + 2) >> 2;
+            *hmem1++ = ((*p2++) + *p4 + 1) >> 1;
+            *hmem2++ = ((*p3++) + *p4 + 1) >> 1;
+            *hmem2++ = *p4++;
+        }
+        /*  last pixel */
+        *hmem1++ = ((*p1++) + (*p2++) + *p3 + *p4 + 2) >> 2;
+        *hmem2++ = ((*p3++) + (*p4++) + 1) >> 1;
+        hmem1 += 33;
+        hmem2 += 33;
+        p1 += offset;
+        p2 += offset;
+        p3 += offset;
+        p4 += offset;
+    }
+    /* last row */
+    for (i = 0; i < 16; i++)
+    {
+        *hmem1++ = ((*p1++) + *p2 + (*p3++) + *p4 + 2) >> 2;
+        *hmem1++ = ((*p2++) + (*p4++) + 1) >> 1;
+
+    }
+    *hmem1 = (*p1 + *p2 + *p3 + *p4 + 2) >> 2;
+
+    return ;
+}
+
+/*===============================================================
+   Function:    GetHalfPelBlkRegion
+   Date:        09/20/2000
+   Purpose: Interpolate the search region for half-pel search
+            in 4MV mode.
+   Input/Output:    Center of the search, Half-pel memory, width
+   Note:        rounding type should be parameterized.
+            Now fixed it to zero!!!!!!
+
+===============================================================*/
+
+
+void GetHalfPelBlkRegion(UChar *cand, UChar *hmem, Int lx)
+{
+    Int i, j;
+    UChar *p1, *p2, *p3, *p4;
+    UChar *hmem1 = hmem;
+    UChar *hmem2 = hmem1 + 17;
+    Int offset = lx - 9;
+
+    p1 = cand - lx - 1;
+    p2 = cand - lx;
+    p3 = cand - 1;
+    p4 = cand;
+
+    for (j = 0; j < 8; j++)
+    {
+        for (i = 0; i < 8; i++)
+        {
+            *hmem1++ = ((*p1++) + *p2 + *p3 + *p4 + 2) >> 2;
+            *hmem1++ = ((*p2++) + *p4 + 1) >> 1;
+            *hmem2++ = ((*p3++) + *p4 + 1) >> 1;
+            *hmem2++ = *p4++;
+        }
+        /*  last pixel */
+        *hmem1++ = ((*p1++) + (*p2++) + *p3 + *p4 + 2) >> 2;
+        *hmem2++ = ((*p3++) + (*p4++) + 1) >> 1;
+        hmem1 += 17;
+        hmem2 += 17;
+        p1 += offset;
+        p2 += offset;
+        p3 += offset;
+        p4 += offset;
+    }
+    /* last row */
+    for (i = 0; i < 8; i++)
+    {
+        *hmem1++ = ((*p1++) + *p2 + (*p3++) + *p4 + 2) >> 2;
+        *hmem1++ = ((*p2++) + (*p4++) + 1) >> 1;
+
+    }
+    *hmem1 = (*p1 + *p2 + *p3 + *p4 + 2) >> 2;
+
+    return ;
+}
+
+
+/*=====================================================================
+    Function:   PaddingEdge
+    Date:       09/16/2000
+    Purpose:    Pad edge of a Vop
+    Modification: 09/20/05.
+=====================================================================*/
+
+void  PaddingEdge(Vop *refVop)
+{
+    UChar *src, *dst;
+    Int i;
+    Int pitch, width, height;
+    ULong temp1, temp2;
+
+    width = refVop->width;
+    height = refVop->height;
+    pitch = refVop->pitch;
+
+    /* pad top */
+    src = refVop->yChan;
+
+    temp1 = *src; /* top-left corner */
+    temp2 = src[width-1]; /* top-right corner */
+    temp1 |= (temp1 << 8);
+    temp1 |= (temp1 << 16);
+    temp2 |= (temp2 << 8);
+    temp2 |= (temp2 << 16);
+
+    dst = src - (pitch << 4);
+
+    *((ULong*)(dst - 16)) = temp1;
+    *((ULong*)(dst - 12)) = temp1;
+    *((ULong*)(dst - 8)) = temp1;
+    *((ULong*)(dst - 4)) = temp1;
+
+    M4VENC_MEMCPY(dst, src, width);
+
+    *((ULong*)(dst += width)) = temp2;
+    *((ULong*)(dst + 4)) = temp2;
+    *((ULong*)(dst + 8)) = temp2;
+    *((ULong*)(dst + 12)) = temp2;
+
+    dst = dst - width - 16;
+
+    i = 15;
+    while (i--)
+    {
+        M4VENC_MEMCPY(dst + pitch, dst, pitch);
+        dst += pitch;
+    }
+
+    /* pad sides */
+    dst += (pitch + 16);
+    src = dst;
+    i = height;
+    while (i--)
+    {
+        temp1 = *src;
+        temp2 = src[width-1];
+        temp1 |= (temp1 << 8);
+        temp1 |= (temp1 << 16);
+        temp2 |= (temp2 << 8);
+        temp2 |= (temp2 << 16);
+
+        *((ULong*)(dst - 16)) = temp1;
+        *((ULong*)(dst - 12)) = temp1;
+        *((ULong*)(dst - 8)) = temp1;
+        *((ULong*)(dst - 4)) = temp1;
+
+        *((ULong*)(dst += width)) = temp2;
+        *((ULong*)(dst + 4)) = temp2;
+        *((ULong*)(dst + 8)) = temp2;
+        *((ULong*)(dst + 12)) = temp2;
+
+        src += pitch;
+        dst = src;
+    }
+
+    /* pad bottom */
+    dst -= 16;
+    i = 16;
+    while (i--)
+    {
+        M4VENC_MEMCPY(dst, dst - pitch, pitch);
+        dst += pitch;
+    }
+
+
+    return ;
+}
+
+/*===================================================================
+    Function:   ComputeMBSum
+    Date:       10/28/2000
+    Purpose:    Compute sum of absolute value (SAV) of blocks in a macroblock
+                in INTRA mode needed for rate control. Thus, instead of
+                computing the SAV, we can compute first order moment or
+                variance .
+
+    11/28/00:    add MMX
+    9/3/01:      do parallel comp for C function.
+===================================================================*/
+void ComputeMBSum_C(UChar *cur, Int lx, MOT *mot_mb)
+{
+    Int j;
+    Int *cInt, *cInt2;
+    Int sad1 = 0, sad2 = 0, sad3 = 0, sad4 = 0;
+    Int tmp, tmp2, mask = 0x00FF00FF;
+
+    cInt = (Int*)cur;   /* make sure this is word-align */
+    cInt2 = (Int*)(cur + (lx << 3));
+    j = 8;
+    while (j--)
+    {
+        tmp = cInt[3];  /* load 4 pixels at a time */
+        tmp2 = tmp & mask;
+        tmp = (tmp >> 8) & mask;
+        tmp += tmp2;
+        sad2 += tmp;
+        tmp = cInt[2];
+        tmp2 = tmp & mask;
+        tmp = (tmp >> 8) & mask;
+        tmp += tmp2;
+        sad2 += tmp;
+        tmp = cInt[1];
+        tmp2 = tmp & mask;
+        tmp = (tmp >> 8) & mask;
+        tmp += tmp2;
+        sad1 += tmp;
+        tmp = *cInt;
+        cInt += (lx >> 2);
+        tmp2 = tmp & mask;
+        tmp = (tmp >> 8) & mask;
+        tmp += tmp2;
+        sad1 += tmp;
+
+        tmp = cInt2[3];
+        tmp2 = tmp & mask;
+        tmp = (tmp >> 8) & mask;
+        tmp += tmp2;
+        sad4 += tmp;
+        tmp = cInt2[2];
+        tmp2 = tmp & mask;
+        tmp = (tmp >> 8) & mask;
+        tmp += tmp2;
+        sad4 += tmp;
+        tmp = cInt2[1];
+        tmp2 = tmp & mask;
+        tmp = (tmp >> 8) & mask;
+        tmp += tmp2;
+        sad3 += tmp;
+        tmp = *cInt2;
+        cInt2 += (lx >> 2);
+        tmp2 = tmp & mask;
+        tmp = (tmp >> 8) & mask;
+        tmp += tmp2;
+        sad3 += tmp;
+    }
+    sad1 += (sad1 << 16);
+    sad2 += (sad2 << 16);
+    sad3 += (sad3 << 16);
+    sad4 += (sad4 << 16);
+    sad1 >>= 16;
+    sad2 >>= 16;
+    sad3 >>= 16;
+    sad4 >>= 16;
+
+    mot_mb[1].sad = sad1;
+    mot_mb[2].sad = sad2;
+    mot_mb[3].sad = sad3;
+    mot_mb[4].sad = sad4;
+    mot_mb[0].sad = sad1 + sad2 + sad3 + sad4;
+
+    return ;
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp
new file mode 100644
index 0000000..b81d278
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp
@@ -0,0 +1,1965 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4lib_int.h"
+#include "mp4enc_lib.h"
+
+//const static Int roundtab4[] = {0,1,1,1};
+//const static Int roundtab8[] = {0,0,1,1,1,1,1,2};
+//const static Int roundtab12[] = {0,0,0,1,1,1,1,1,1,1,2,2};
+const static Int roundtab16[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
+
+#define FORWARD_MODE    1
+#define BACKWARD_MODE   2
+#define BIDIRECTION_MODE    3
+#define DIRECT_MODE         4
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    /*Function Prototype */
+    /* no-edge padding */
+    Int EncGetPredOutside(Int xpos, Int ypos, UChar *c_prev, UChar *rec,
+    Int width, Int height, Int rnd1);
+
+    void Copy_MB_from_Vop(UChar *comp, Int yChan[][NCOEFF_BLOCK], Int width);
+    void Copy_B_from_Vop(UChar *comp, Int cChan[], Int width);
+    void Copy_MB_into_Vop(UChar *comp, Int yChan[][NCOEFF_BLOCK], Int width);
+    void Copy_B_into_Vop(UChar *comp, Int cChan[], Int width);
+    void get_MB(UChar *c_prev, UChar *c_prev_u  , UChar *c_prev_v,
+                Short mb[6][64], Int lx, Int lx_uv);
+
+    Int GetPredAdvBy0x0(
+        UChar *c_prev,      /* i */
+        UChar *pred_block,      /* i */
+        Int lx,     /* i */
+        Int rnd1 /* i */
+    );
+
+    Int GetPredAdvBy0x1(
+        UChar *c_prev,      /* i */
+        UChar *pred_block,      /* i */
+        Int lx,     /* i */
+        Int rnd1 /* i */
+    );
+
+    Int GetPredAdvBy1x0(
+        UChar *c_prev,      /* i */
+        UChar *pred_block,      /* i */
+        Int lx,     /* i */
+        Int rnd1 /* i */
+    );
+
+    Int GetPredAdvBy1x1(
+        UChar *c_prev,      /* i */
+        UChar *pred_block,      /* i */
+        Int lx,     /* i */
+        Int rnd1 /* i */
+    );
+
+    static Int(*const GetPredAdvBTable[2][2])(UChar*, UChar*, Int, Int) =
+    {
+        {&GetPredAdvBy0x0, &GetPredAdvBy0x1},
+        {&GetPredAdvBy1x0, &GetPredAdvBy1x1}
+    };
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ======================================================================== */
+/*  Function : getMotionCompensatedMB( )                                    */
+/*  Date     : 4/17/2001                                                    */
+/*  Purpose  : Get the motion compensate block into video->predictionMB     */
+/*              and generate video->predictionErrorMB                       */
+/*              modified from MBMotionComp() function in the decoder        */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+void getMotionCompensatedMB(VideoEncData *video, Int ind_x, Int ind_y, Int offset)
+{
+    Vop *prevVop = video->forwardRefVop; //reference frame
+    Vop *currVop = video->currVop;
+    Int mbnum = video->mbnum;       //mb index
+    MOT *mot = video->mot[mbnum];
+    Int ypos, xpos;
+    UChar *c_prev, *cu_prev, *cv_prev;
+    UChar *c_rec, *cu_rec, *cv_rec;
+    Int height, pitch, pitch_uv, height_uv;
+    Int mode = video->headerInfo.Mode[mbnum];  /* get mode */
+    Int dx, dy;
+    Int xpred, ypred;
+    Int xsum, ysum;
+    Int round1;
+
+    OSCL_UNUSED_ARG(offset);
+
+    round1 = (Int)(1 - video->currVop->roundingType);
+
+    pitch  = currVop->pitch;
+    height = currVop->height;
+    pitch_uv  = pitch >> 1;
+    height_uv = height >> 1;
+
+    ypos = ind_y << 4 ;
+    xpos = ind_x << 4 ;
+
+    c_rec = video->predictedMB;
+    cu_rec = video->predictedMB + 256;
+    cv_rec = video->predictedMB + 264;
+
+    if (mode == MODE_INTER || mode == MODE_INTER_Q)
+    {
+        /* Motion vector in x direction       */
+        dx = mot[0].x;
+        dy = mot[0].y;
+
+        c_prev  = prevVop->yChan;
+
+        xpred = (xpos << 1) + dx ;
+        ypred = (ypos << 1) + dy ;
+
+        /* Call function that performs luminance prediction */
+        EncPrediction_INTER(xpred, ypred, c_prev, c_rec,
+                            pitch, round1);
+
+        if ((dx & 3) == 0)  dx = dx >> 1;
+        else        dx = (dx >> 1) | 1;
+
+        if ((dy & 3) == 0)      dy = dy >> 1;
+        else        dy = (dy >> 1) | 1;
+
+        xpred = xpos + dx;
+        ypred = ypos + dy;
+
+        cu_prev = prevVop->uChan;
+        cv_prev = prevVop->vChan;
+
+        EncPrediction_Chrom(xpred, ypred, cu_prev, cv_prev, cu_rec, cv_rec,
+                            pitch_uv, (currVop->width) >> 1, height_uv, round1);
+    }
+#ifndef NO_INTER4V
+    else if (mode == MODE_INTER4V)
+    {
+        c_prev  = prevVop->yChan;
+        cu_prev = prevVop->uChan;
+        cv_prev = prevVop->vChan;
+
+        EncPrediction_INTER4V(xpos, ypos, mot, c_prev, c_rec,
+                              pitch, round1);
+
+        xsum = mot[1].x + mot[2].x + mot[3].x + mot[4].x;
+        ysum = mot[1].y + mot[2].y + mot[3].y + mot[4].y;
+
+        dx = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] +
+                              (((PV_ABS(xsum)) >> 4) << 1));
+        dy = PV_SIGN(ysum) * (roundtab16[(PV_ABS(ysum)) & 0xF] +
+                              (((PV_ABS(ysum)) >> 4) << 1));
+
+        ypred = ypos + dy;
+        xpred = xpos + dx;
+
+        EncPrediction_Chrom(xpred, ypred, cu_prev, cv_prev, cu_rec, cv_rec,
+                            pitch_uv, (currVop->width) >> 1, height_uv, round1);
+    }
+#endif
+    else
+    {
+        ;//printf("Error, MODE_SKIPPED is not decided yet!\n");
+    }
+
+    return ;
+}
+
+/***************************************************************************
+    Function:   EncPrediction_INTER
+    Date:       04/17/2001
+    Purpose:    Get predicted area for luminance and compensate with the residue.
+                Modified from luminance_pred_mode_inter() in decoder.
+***************************************************************************/
+
+void EncPrediction_INTER(
+    Int xpred,          /* i */
+    Int ypred,          /* i */
+    UChar *c_prev,          /* i */
+    UChar *c_rec,       /* i */
+    Int lx,         /* i */
+    Int round1          /* i */
+)
+{
+    c_prev += (xpred >> 1) + ((ypred >> 1) * lx);
+
+    GetPredAdvBTable[ypred&1][xpred&1](c_prev, c_rec, lx, round1);
+
+    c_prev += B_SIZE;
+    c_rec += B_SIZE;
+
+    GetPredAdvBTable[ypred&1][xpred&1](c_prev, c_rec, lx, round1);
+
+    c_prev += (lx << 3) - B_SIZE;
+    c_rec += (16 << 3) - B_SIZE; /* padding */
+
+    GetPredAdvBTable[ypred&1][xpred&1](c_prev, c_rec, lx, round1);
+
+    c_prev += B_SIZE;
+    c_rec += B_SIZE;
+
+    GetPredAdvBTable[ypred&1][xpred&1](c_prev, c_rec, lx, round1);
+
+    return;
+}
+
+#ifndef NO_INTER4V
+/***************************************************************************
+    Function:   EncPrediction_INTER4V
+    Date:       04/17/2001
+    Purpose:    Get predicted area for luminance and compensate with the residue.
+                Modified from luminance_pred_mode_inter4v() in decoder.
+***************************************************************************/
+
+void EncPrediction_INTER4V(
+    Int xpos,           /* i */
+    Int ypos,           /* i */
+    MOT *mot,           /* i */
+    UChar *c_prev,          /* i */
+    UChar *c_rec,           /* i */
+    Int lx,         /* i */
+    Int round1          /* i */
+)
+{
+    Int ypred, xpred;
+
+    xpred = (Int)((xpos << 1) + mot[1].x);
+    ypred = (Int)((ypos << 1) + mot[1].y);
+
+    GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+                                       c_rec, lx, round1);
+
+    c_rec += B_SIZE;
+
+    xpred = (Int)(((xpos + B_SIZE) << 1) + mot[2].x);
+    ypred = (Int)((ypos << 1) + mot[2].y);
+
+    GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+                                       c_rec, lx, round1);
+
+    c_rec += (16 << 3) - B_SIZE; /* padding */
+
+    xpred = (Int)((xpos << 1) + mot[3].x);
+    ypred = (Int)(((ypos + B_SIZE) << 1) + mot[3].y);
+
+    GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+                                       c_rec, lx, round1);
+
+    c_rec += B_SIZE;
+
+    xpred = (Int)(((xpos + B_SIZE) << 1) + mot[4].x);
+    ypred = (Int)(((ypos + B_SIZE) << 1) + mot[4].y);
+
+    GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+                                       c_rec, lx, round1);
+
+    return;
+}
+#endif /* NO_INTER4V */
+
+/***************************************************************************
+    Function:   EncPrediction_Chrom
+    Date:       04/17/2001
+    Purpose:    Get predicted area for chrominance and compensate with the residue.
+                Modified from chrominance_pred() in decoder.
+***************************************************************************/
+
+void EncPrediction_Chrom(
+    Int xpred,          /* i */
+    Int ypred,          /* i */
+    UChar *cu_prev,         /* i */
+    UChar *cv_prev,         /* i */
+    UChar *cu_rec,
+    UChar *cv_rec,
+    Int lx,
+    Int width_uv,           /* i */
+    Int height_uv,          /* i */
+    Int round1          /* i */
+)
+{
+    /* check whether the MV points outside the frame */
+    /* Compute prediction for Chrominance b block (block[4]) */
+    if (xpred >= 0 && xpred <= ((width_uv << 1) - (2*B_SIZE)) && ypred >= 0 &&
+            ypred <= ((height_uv << 1) - (2*B_SIZE)))
+    {
+        /*****************************/
+        /* (x,y) is inside the frame */
+        /*****************************/
+
+        /* Compute prediction for Chrominance b (block[4]) */
+        GetPredAdvBTable[ypred&1][xpred&1](cu_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+                                           cu_rec, lx, round1);
+
+        /* Compute prediction for Chrominance r (block[5]) */
+        GetPredAdvBTable[ypred&1][xpred&1](cv_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+                                           cv_rec,  lx, round1);
+    }
+    else
+    {
+        /******************************/
+        /* (x,y) is outside the frame */
+        /******************************/
+
+        /* Compute prediction for Chrominance b (block[4]) */
+        EncGetPredOutside(xpred, ypred,
+                          cu_prev, cu_rec,
+                          width_uv, height_uv, round1);
+
+        /* Compute prediction for Chrominance r (block[5]) */
+        EncGetPredOutside(xpred, ypred,
+                          cv_prev, cv_rec,
+                          width_uv, height_uv, round1);
+    }
+
+    return;
+}
+/***************************************************************************
+    Function:   GetPredAdvancedB
+    Date:       04/17/2001
+    Purpose:    Get predicted area (block) and compensate with the residue.
+                - modified from GetPredAdvancedBAdd in decoder.
+    Intput/Output:
+    Modified:
+***************************************************************************/
+
+Int GetPredAdvBy0x0(
+    UChar *prev,        /* i */
+    UChar *rec,     /* i */
+    Int lx,     /* i */
+    Int rnd /* i */
+)
+{
+    Int i;      /* loop variable */
+    ULong  pred_word, word1, word2;
+    Int tmp;
+
+    OSCL_UNUSED_ARG(rnd);
+
+    /* initialize offset to adjust pixel counter */
+    /*    the next row; full-pel resolution      */
+
+    tmp = (ULong)prev & 0x3;
+
+    if (tmp == 0)  /* word-aligned */
+    {
+        rec -= 16; /* preset */
+        prev -= lx;
+
+        for (i = 8; i > 0; i--)
+        {
+            *((ULong*)(rec += 16)) = *((ULong*)(prev += lx));
+            *((ULong*)(rec + 4)) = *((ULong*)(prev + 4));
+        }
+        return 1;
+    }
+    else if (tmp == 1) /* first position */
+    {
+        prev--; /* word-aligned */
+        rec -= 16; /* preset */
+        prev -= lx;
+
+        for (i = 8; i > 0; i--)
+        {
+            word1 = *((ULong*)(prev += lx)); /* read 4 bytes, b4 b3 b2 b1 */
+            word2 = *((ULong*)(prev + 4));  /* read 4 bytes, b8 b7 b6 b5 */
+            word1 >>= 8; /* 0 b4 b3 b2 */
+            pred_word = word1 | (word2 << 24);  /* b5 b4 b3 b2 */
+            *((ULong*)(rec += 16)) = pred_word;
+
+            word1 = *((ULong*)(prev + 8)); /* b12 b11 b10 b9 */
+            word2 >>= 8; /* 0 b8 b7 b6 */
+            pred_word = word2 | (word1 << 24); /* b9 b8 b7 b6 */
+            *((ULong*)(rec + 4)) = pred_word;
+        }
+
+        return 1;
+    }
+    else if (tmp == 2) /* second position */
+    {
+        prev -= 2; /* word1-aligned */
+        rec -= 16; /* preset */
+        prev -= lx;
+
+        for (i = 8; i > 0; i--)
+        {
+            word1 = *((ULong*)(prev += lx)); /* read 4 bytes, b4 b3 b2 b1 */
+            word2 = *((ULong*)(prev + 4));  /* read 4 bytes, b8 b7 b6 b5 */
+            word1 >>= 16; /* 0 0 b4 b3 */
+            pred_word = word1 | (word2 << 16);  /* b6 b5 b4 b3 */
+            *((ULong*)(rec += 16)) = pred_word;
+
+            word1 = *((ULong*)(prev + 8)); /* b12 b11 b10 b9 */
+            word2 >>= 16; /* 0 0 b8 b7 */
+            pred_word = word2 | (word1 << 16); /* b10 b9 b8 b7 */
+            *((ULong*)(rec + 4)) = pred_word;
+        }
+
+        return 1;
+    }
+    else /* third position */
+    {
+        prev -= 3; /* word1-aligned */
+        rec -= 16; /* preset */
+        prev -= lx;
+
+        for (i = 8; i > 0; i--)
+        {
+            word1 = *((ULong*)(prev += lx)); /* read 4 bytes, b4 b3 b2 b1 */
+            word2 = *((ULong*)(prev + 4));  /* read 4 bytes, b8 b7 b6 b5 */
+            word1 >>= 24; /* 0 0 0 b4 */
+            pred_word = word1 | (word2 << 8);   /* b7 b6 b5 b4 */
+            *((ULong*)(rec += 16)) = pred_word;
+
+            word1 = *((ULong*)(prev + 8)); /* b12 b11 b10 b9 */
+            word2 >>= 24; /* 0 0 0 b8 */
+            pred_word = word2 | (word1 << 8); /* b11 b10 b9 b8 */
+            *((ULong*)(rec + 4)) = pred_word;
+
+        }
+
+        return 1;
+    }
+}
+/**************************************************************************/
+Int GetPredAdvBy0x1(
+    UChar *prev,        /* i */
+    UChar *rec,     /* i */
+    Int lx,     /* i */
+    Int rnd1 /* i */
+)
+{
+    Int i;      /* loop variable */
+    Int offset;
+    ULong word1, word2, word3, word12;
+    Int tmp;
+    ULong mask;
+
+    /* initialize offset to adjust pixel counter */
+    /*    the next row; full-pel resolution      */
+    offset = lx - B_SIZE; /* offset for prev */
+
+    /* Branch based on pixel location (half-pel or full-pel) for x and y */
+    rec -= 12; /* preset */
+
+    tmp = (ULong)prev & 3;
+    mask = 254;
+    mask |= (mask << 8);
+    mask |= (mask << 16); /* 0xFEFEFEFE */
+
+    if (tmp == 0) /* word-aligned */
+    {
+        if (rnd1 == 1)
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)prev); /* b4 b3 b2 b1 */
+                word2 = *((ULong*)(prev += 4)); /* b8 b7 b6 b5 */
+                word12 = (word1 >> 8); /* 0 b4 b3 b2 */
+                word12 |= (word2 << 24); /* b5 b4 b3 b2 */
+                word3 = word1 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word12 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+                word1 = *((ULong*)(prev += 4)); /* b12 b11 b10 b9 */
+                word12 = (word2 >> 8); /* 0 b8 b7 b6 */
+                word12 |= (word1 << 24); /* b9 b8 b7 b6 */
+                word3 = word2 | word12;
+                word2 &= mask;
+                word3 &= (~mask);  /* 0x1010101, check last bit */
+                word12 &= mask;
+                word2 >>= 1;
+                word2 = word2 + (word12 >> 1);
+                word2 += word3;
+                *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+
+                prev += offset;
+            }
+            return 1;
+        }
+        else /* rnd1 == 0 */
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)prev); /* b4 b3 b2 b1 */
+
+                word2 = *((ULong*)(prev += 4)); /* b8 b7 b6 b5 */
+                word12 = (word1 >> 8); /* 0 b4 b3 b2 */
+                word12 |= (word2 << 24); /* b5 b4 b3 b2 */
+                word3 = word1 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word12 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+                word1 = *((ULong*)(prev += 4)); /* b12 b11 b10 b9 */
+                word12 = (word2 >> 8); /* 0 b8 b7 b6 */
+                word12 |= (word1 << 24); /* b9 b8 b7 b6 */
+                word3 = word2 & word12;
+                word2 &= mask;
+                word3 &= (~mask);  /* 0x1010101, check last bit */
+                word12 &= mask;
+                word2 >>= 1;
+                word2 = word2 + (word12 >> 1);
+                word2 += word3;
+                *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+
+                prev += offset;
+            }
+            return 1;
+        } /* rnd1 */
+    }
+    else if (tmp == 1)
+    {
+        prev--; /* word-aligned */
+        if (rnd1 == 1)
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)prev); /* b3 b2 b1 b0 */
+                word2 = *((ULong*)(prev += 4)); /* b7 b6 b5 b4 */
+                word12 = (word1 >> 8); /* 0 b3 b2 b1 */
+                word1 >>= 16; /* 0 0 b3 b2 */
+                word12 |= (word2 << 24); /* b4 b3 b2 b1 */
+                word1 |= (word2 << 16); /* b5 b4 b3 b2 */
+                word3 = word1 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word12 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+                word1 = *((ULong*)(prev += 4)); /* b11 b10 b9 b8 */
+                word12 = (word2 >> 8); /* 0 b7 b6 b5 */
+                word2 >>= 16; /* 0 0 b7 b6 */
+                word12 |= (word1 << 24); /* b8 b7 b6 b5 */
+                word2 |= (word1 << 16); /* b9 b8 b7 b6 */
+                word3 = word2 | word12; // rnd1 = 1; otherwise word3 = word2&word12
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word2 >>= 1;
+                word2 = word2 + (word12 >> 1);
+                word2 += word3;
+                *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+
+                prev += offset;
+            }
+            return 1;
+        }
+        else /* rnd1 = 0 */
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)prev); /* b3 b2 b1 b0 */
+
+                word2 = *((ULong*)(prev += 4)); /* b7 b6 b5 b4 */
+                word12 = (word1 >> 8); /* 0 b3 b2 b1 */
+                word1 >>= 16; /* 0 0 b3 b2 */
+                word12 |= (word2 << 24); /* b4 b3 b2 b1 */
+                word1 |= (word2 << 16); /* b5 b4 b3 b2 */
+                word3 = word1 & word12;
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word12 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+                word1 = *((ULong*)(prev += 4)); /* b11 b10 b9 b8 */
+                word12 = (word2 >> 8); /* 0 b7 b6 b5 */
+                word2 >>= 16; /* 0 0 b7 b6 */
+                word12 |= (word1 << 24); /* b8 b7 b6 b5 */
+                word2 |= (word1 << 16); /* b9 b8 b7 b6 */
+                word3 = word2 & word12;
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word2 >>= 1;
+                word2 = word2 + (word12 >> 1);
+                word2 += word3;
+                *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+
+                prev += offset;
+            }
+            return 1;
+        } /* rnd1 */
+    }
+    else if (tmp == 2)
+    {
+        prev -= 2; /* word-aligned */
+        if (rnd1 == 1)
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)prev); /* b2 b1 b0 bN1 */
+                word2 = *((ULong*)(prev += 4)); /* b6 b5 b4 b3 */
+                word12 = (word1 >> 16); /* 0 0 b2 b1 */
+                word1 >>= 24; /* 0 0 0 b2 */
+                word12 |= (word2 << 16); /* b4 b3 b2 b1 */
+                word1 |= (word2 << 8); /* b5 b4 b3 b2 */
+                word3 = word1 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word12 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+                word1 = *((ULong*)(prev += 4)); /* b10 b9 b8 b7 */
+                word12 = (word2 >> 16); /* 0 0 b6 b5 */
+                word2 >>= 24; /* 0 0 0 b6 */
+                word12 |= (word1 << 16); /* b8 b7 b6 b5 */
+                word2 |= (word1 << 8); /* b9 b8 b7 b6 */
+                word3 = word2 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word2 >>= 1;
+                word2 = word2 + (word12 >> 1);
+                word2 += word3;
+                *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+                prev += offset;
+            }
+            return 1;
+        }
+        else /* rnd1 == 0 */
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)prev); /* b2 b1 b0 bN1 */
+                word2 = *((ULong*)(prev += 4)); /* b6 b5 b4 b3 */
+                word12 = (word1 >> 16); /* 0 0 b2 b1 */
+                word1 >>= 24; /* 0 0 0 b2 */
+                word12 |= (word2 << 16); /* b4 b3 b2 b1 */
+                word1 |= (word2 << 8); /* b5 b4 b3 b2 */
+                word3 = word1 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word12 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+                word1 = *((ULong*)(prev += 4)); /* b10 b9 b8 b7 */
+                word12 = (word2 >> 16); /* 0 0 b6 b5 */
+                word2 >>= 24; /* 0 0 0 b6 */
+                word12 |= (word1 << 16); /* b8 b7 b6 b5 */
+                word2 |= (word1 << 8); /* b9 b8 b7 b6 */
+                word3 = word2 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word2 >>= 1;
+                word2 = word2 + (word12 >> 1);
+                word2 += word3;
+                *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+                prev += offset;
+            }
+            return 1;
+        }
+    }
+    else /* tmp = 3 */
+    {
+        prev -= 3; /* word-aligned */
+        if (rnd1 == 1)
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)prev); /* b1 b0 bN1 bN2 */
+                word2 = *((ULong*)(prev += 4)); /* b5 b4 b3 b2 */
+                word12 = (word1 >> 24); /* 0 0 0 b1 */
+                word12 |= (word2 << 8); /* b4 b3 b2 b1 */
+                word1 = word2;
+                word3 = word1 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word12 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+                word1 = *((ULong*)(prev += 4)); /* b9 b8 b7 b6 */
+                word12 = (word2 >> 24); /* 0 0 0 b5 */
+                word12 |= (word1 << 8); /* b8 b7 b6 b5 */
+                word2 = word1; /* b9 b8 b7 b6 */
+                word3 = word2 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word2 >>= 1;
+                word2 = word2 + (word12 >> 1);
+                word2 += word3;
+                *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+                prev += offset;
+            }
+            return 1;
+        }
+        else
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)prev); /* b1 b0 bN1 bN2 */
+                word2 = *((ULong*)(prev += 4)); /* b5 b4 b3 b2 */
+                word12 = (word1 >> 24); /* 0 0 0 b1 */
+                word12 |= (word2 << 8); /* b4 b3 b2 b1 */
+                word1 = word2;
+                word3 = word1 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word12 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+                word1 = *((ULong*)(prev += 4)); /* b9 b8 b7 b6 */
+                word12 = (word2 >> 24); /* 0 0 0 b5 */
+                word12 |= (word1 << 8); /* b8 b7 b6 b5 */
+                word2 = word1; /* b9 b8 b7 b6 */
+                word3 = word2 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 &= mask;
+                word2 >>= 1;
+                word2 = word2 + (word12 >> 1);
+                word2 += word3;
+                *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+                prev += offset;
+            }
+            return 1;
+        }
+    }
+}
+
+/**************************************************************************/
+Int GetPredAdvBy1x0(
+    UChar *prev,        /* i */
+    UChar *rec,     /* i */
+    Int lx,     /* i */
+    Int rnd1 /* i */
+)
+{
+    Int i;      /* loop variable */
+    Int offset;
+    ULong  word1, word2, word3, word12, word22;
+    Int tmp;
+    ULong mask;
+
+    /* initialize offset to adjust pixel counter */
+    /*    the next row; full-pel resolution      */
+    offset = lx - B_SIZE; /* offset for prev */
+
+    /* Branch based on pixel location (half-pel or full-pel) for x and y */
+    rec -= 12; /* preset */
+
+    tmp = (ULong)prev & 3;
+    mask = 254;
+    mask |= (mask << 8);
+    mask |= (mask << 16); /* 0xFEFEFEFE */
+
+    if (tmp == 0) /* word-aligned */
+    {
+        prev -= 4;
+        if (rnd1 == 1)
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)(prev += 4));
+                word2 = *((ULong*)(prev + lx));
+                word3 = word1 | word2; // rnd1 = 1; otherwise word3 = word1&word2
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word2 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1;
+                word1 = *((ULong*)(prev += 4));
+                word2 = *((ULong*)(prev + lx));
+                word3 = word1 | word2; // rnd1 = 1; otherwise word3 = word1&word2
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word2 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 4)) = word1;
+
+                prev += offset;
+            }
+            return 1;
+        }
+        else   /* rnd1 = 0 */
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word1 = *((ULong*)(prev += 4));
+                word2 = *((ULong*)(prev + lx));
+                word3 = word1 & word2;  /* rnd1 = 0; */
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word2 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 12)) = word1;
+                word1 = *((ULong*)(prev += 4));
+                word2 = *((ULong*)(prev + lx));
+                word3 = word1 & word2;  /* rnd1 = 0; */
+                word1 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word2 &= mask;
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 4)) = word1;
+
+                prev += offset;
+            }
+            return 1;
+        }
+    }
+    else if (tmp == 1)
+    {
+        prev--; /* word-aligned */
+        if (rnd1 == 1)
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+                word22 = *((ULong*)(prev + lx));
+
+                word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+                word2 = *((ULong*)(prev + lx));
+                word12 >>= 8; /* 0 b4 b3 b2 */
+                word22 >>= 8;
+                word12 = word12 | (word1 << 24); /* b5 b4 b3 b2 */
+                word22 = word22 | (word2 << 24);
+                word3 = word12 | word22;
+                word12 &= mask;
+                word22 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 >>= 1;
+                word12 = word12 + (word22 >> 1);
+                word12 += word3;
+                *((ULong*)(rec += 12)) = word12;
+
+                word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+                word22 = *((ULong*)(prev + lx));
+                word1 >>= 8; /* 0 b8 b7 b6 */
+                word2 >>= 8;
+                word1 = word1 | (word12 << 24); /* b9 b8 b7 b6 */
+                word2 = word2 | (word22 << 24);
+                word3 = word1 | word2;
+                word1 &= mask;
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 4)) = word1;
+                prev += offset;
+            }
+            return 1;
+        }
+        else /* rnd1 = 0 */
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+                word22 = *((ULong*)(prev + lx));
+
+                word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+                word2 = *((ULong*)(prev + lx));
+                word12 >>= 8; /* 0 b4 b3 b2 */
+                word22 >>= 8;
+                word12 = word12 | (word1 << 24); /* b5 b4 b3 b2 */
+                word22 = word22 | (word2 << 24);
+                word3 = word12 & word22;
+                word12 &= mask;
+                word22 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 >>= 1;
+                word12 = word12 + (word22 >> 1);
+                word12 += word3;
+                *((ULong*)(rec += 12)) = word12;
+
+                word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+                word22 = *((ULong*)(prev + lx));
+                word1 >>= 8; /* 0 b8 b7 b6 */
+                word2 >>= 8;
+                word1 = word1 | (word12 << 24); /* b9 b8 b7 b6 */
+                word2 = word2 | (word22 << 24);
+                word3 = word1 & word2;
+                word1 &= mask;
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 4)) = word1;
+                prev += offset;
+            }
+            return 1;
+        }
+    }
+    else if (tmp == 2)
+    {
+        prev -= 2; /* word-aligned */
+        if (rnd1 == 1)
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+                word22 = *((ULong*)(prev + lx));
+
+                word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+                word2 = *((ULong*)(prev + lx));
+                word12 >>= 16; /* 0 0 b4 b3 */
+                word22 >>= 16;
+                word12 = word12 | (word1 << 16); /* b6 b5 b4 b3 */
+                word22 = word22 | (word2 << 16);
+                word3 = word12 | word22;
+                word12 &= mask;
+                word22 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 >>= 1;
+                word12 = word12 + (word22 >> 1);
+                word12 += word3;
+                *((ULong*)(rec += 12)) = word12;
+
+                word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+                word22 = *((ULong*)(prev + lx));
+                word1 >>= 16; /* 0 0 b8 b7 */
+                word2 >>= 16;
+                word1 = word1 | (word12 << 16); /* b10 b9 b8 b7 */
+                word2 = word2 | (word22 << 16);
+                word3 = word1 | word2;
+                word1 &= mask;
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 4)) = word1;
+                prev += offset;
+            }
+            return 1;
+        }
+        else /* rnd1 = 0 */
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+                word22 = *((ULong*)(prev + lx));
+
+                word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+                word2 = *((ULong*)(prev + lx));
+                word12 >>= 16; /* 0 0 b4 b3 */
+                word22 >>= 16;
+                word12 = word12 | (word1 << 16); /* b6 b5 b4 b3 */
+                word22 = word22 | (word2 << 16);
+                word3 = word12 & word22;
+                word12 &= mask;
+                word22 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 >>= 1;
+                word12 = word12 + (word22 >> 1);
+                word12 += word3;
+                *((ULong*)(rec += 12)) = word12;
+
+                word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+                word22 = *((ULong*)(prev + lx));
+                word1 >>= 16; /* 0 0 b8 b7 */
+                word2 >>= 16;
+                word1 = word1 | (word12 << 16); /* b10 b9 b8 b7 */
+                word2 = word2 | (word22 << 16);
+                word3 = word1 & word2;
+                word1 &= mask;
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 4)) = word1;
+                prev += offset;
+            }
+
+            return 1;
+        }
+    }
+    else /* tmp == 3 */
+    {
+        prev -= 3; /* word-aligned */
+        if (rnd1 == 1)
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+                word22 = *((ULong*)(prev + lx));
+
+                word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+                word2 = *((ULong*)(prev + lx));
+                word12 >>= 24; /* 0 0 0 b4 */
+                word22 >>= 24;
+                word12 = word12 | (word1 << 8); /* b7 b6 b5 b4 */
+                word22 = word22 | (word2 << 8);
+                word3 = word12 | word22;
+                word12 &= mask;
+                word22 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 >>= 1;
+                word12 = word12 + (word22 >> 1);
+                word12 += word3;
+                *((ULong*)(rec += 12)) = word12;
+
+                word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+                word22 = *((ULong*)(prev + lx));
+                word1 >>= 24; /* 0 0 0 b8 */
+                word2 >>= 24;
+                word1 = word1 | (word12 << 8); /* b11 b10 b9 b8 */
+                word2 = word2 | (word22 << 8);
+                word3 = word1 | word2;
+                word1 &= mask;
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 4)) = word1;
+                prev += offset;
+            }
+            return 1;
+        }
+        else /* rnd1 = 0 */
+        {
+            for (i = B_SIZE; i > 0; i--)
+            {
+                word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+                word22 = *((ULong*)(prev + lx));
+
+                word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+                word2 = *((ULong*)(prev + lx));
+                word12 >>= 24; /* 0 0 0 b4 */
+                word22 >>= 24;
+                word12 = word12 | (word1 << 8); /* b7 b6 b5 b4 */
+                word22 = word22 | (word2 << 8);
+                word3 = word12 & word22;
+                word12 &= mask;
+                word22 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word12 >>= 1;
+                word12 = word12 + (word22 >> 1);
+                word12 += word3;
+                *((ULong*)(rec += 12)) = word12;
+
+                word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+                word22 = *((ULong*)(prev + lx));
+                word1 >>= 24; /* 0 0 0 b8 */
+                word2 >>= 24;
+                word1 = word1 | (word12 << 8); /* b11 b10 b9 b8 */
+                word2 = word2 | (word22 << 8);
+                word3 = word1 & word2;
+                word1 &= mask;
+                word2 &= mask;
+                word3 &= (~mask); /* 0x1010101, check last bit */
+                word1 >>= 1;
+                word1 = word1 + (word2 >> 1);
+                word1 += word3;
+                *((ULong*)(rec += 4)) = word1;
+                prev += offset;
+            }
+            return 1;
+        } /* rnd */
+    } /* tmp */
+}
+
+/**********************************************************************************/
+Int GetPredAdvBy1x1(
+    UChar *prev,        /* i */
+    UChar *rec,     /* i */
+    Int lx,     /* i */
+    Int rnd1 /* i */
+)
+{
+    Int i;      /* loop variable */
+    Int offset;
+    ULong  x1, x2, x1m, x2m, y1, y2, y1m, y2m; /* new way */
+    Int tmp;
+    Int rnd2;
+    ULong mask;
+
+    /* initialize offset to adjust pixel counter */
+    /*    the next row; full-pel resolution      */
+    offset = lx - B_SIZE; /* offset for prev */
+
+    rnd2 = rnd1 + 1;
+    rnd2 |= (rnd2 << 8);
+    rnd2 |= (rnd2 << 16);
+
+    mask = 0x3F;
+    mask |= (mask << 8);
+    mask |= (mask << 16); /* 0x3f3f3f3f */
+
+    tmp = (ULong)prev & 3;
+
+    rec -= 4; /* preset */
+
+    if (tmp == 0) /* word-aligned */
+    {
+        for (i = B_SIZE; i > 0; i--)
+        {
+            x1 = *((ULong*)prev); /* load a3 a2 a1 a0 */
+            x2 = *((ULong*)(prev + lx)); /* load b3 b2 b1 b0, another line */
+            y1 = *((ULong*)(prev += 4)); /* a7 a6 a5 a4 */
+            y2 = *((ULong*)(prev + lx)); /* b7 b6 b5 b4 */
+
+            x1m = (x1 >> 2) & mask; /* zero out last 2 bits */
+            x2m = (x2 >> 2) & mask;
+            x1 = x1 ^(x1m << 2);
+            x2 = x2 ^(x2m << 2);
+            x1m += x2m;
+            x1 += x2;
+
+            /* x2m, x2 free */
+            y1m = (y1 >> 2) & mask; /* zero out last 2 bits */
+            y2m = (y2 >> 2) & mask;
+            y1 = y1 ^(y1m << 2);
+            y2 = y2 ^(y2m << 2);
+            y1m += y2m;
+            y1 += y2;
+
+            /* y2m, y2 free */
+            /* x2m, x2 free */
+            x2 = *((ULong*)(prev += 4)); /* a11 a10 a9 a8 */
+            y2 = *((ULong*)(prev + lx)); /* b11 b10 b9 b8 */
+            x2m = (x2 >> 2) & mask;
+            y2m = (y2 >> 2) & mask;
+            x2 = x2 ^(x2m << 2);
+            y2 = y2 ^(y2m << 2);
+            x2m += y2m;
+            x2 += y2;
+            /* y2m, y2 free */
+
+            /* now operate on x1m, x1, y1m, y1, x2m, x2 */
+            /* x1m = a3+b3, a2+b2, a1+b1, a0+b0 */
+            /* y1m = a7+b7, a6+b6, a5+b5, a4+b4 */
+            /* x2m = a11+b11, a10+b10, a9+b9, a8+b8 */
+            /* x1, y1, x2 */
+
+            y2m = x1m >> 8;
+            y2 = x1 >> 8;
+            y2m |= (y1m << 24);  /* a4+b4, a3+b3, a2+b2, a1+b1 */
+            y2 |= (y1 << 24);
+            x1m += y2m;  /* a3+b3+a4+b4, ....., a0+b0+a1+b1 */
+            x1 += y2;
+            x1 += rnd2;
+            x1 &= (mask << 2);
+            x1m += (x1 >> 2);
+            *((ULong*)(rec += 4)) = x1m; /* save x1m */
+
+            y2m = y1m >> 8;
+            y2 = y1 >> 8;
+            y2m |= (x2m << 24); /* a8+b8, a7+b7, a6+b6, a5+b5 */
+            y2 |= (x2 << 24);
+            y1m += y2m;  /* a7+b7+a8+b8, ....., a4+b4+a5+b5 */
+            y1 += y2;
+            y1 += rnd2;
+            y1 &= (mask << 2);
+            y1m += (y1 >> 2);
+            *((ULong*)(rec += 4)) = y1m; /* save y1m */
+
+            rec += 8;
+            prev += offset;
+        }
+
+        return 1;
+    }
+    else if (tmp == 1)
+    {
+        prev--; /* to word-aligned */
+        for (i = B_SIZE; i > 0; i--)
+        {
+            x1 = *((ULong*)prev); /* load a3 a2 a1 a0 */
+            x2 = *((ULong*)(prev + lx)); /* load b3 b2 b1 b0, another line */
+            y1 = *((ULong*)(prev += 4)); /* a7 a6 a5 a4 */
+            y2 = *((ULong*)(prev + lx)); /* b7 b6 b5 b4 */
+
+            x1m = (x1 >> 2) & mask; /* zero out last 2 bits */
+            x2m = (x2 >> 2) & mask;
+            x1 = x1 ^(x1m << 2);
+            x2 = x2 ^(x2m << 2);
+            x1m += x2m;
+            x1 += x2;
+
+            /* x2m, x2 free */
+            y1m = (y1 >> 2) & mask; /* zero out last 2 bits */
+            y2m = (y2 >> 2) & mask;
+            y1 = y1 ^(y1m << 2);
+            y2 = y2 ^(y2m << 2);
+            y1m += y2m;
+            y1 += y2;
+
+            /* y2m, y2 free */
+            /* x2m, x2 free */
+            x2 = *((ULong*)(prev += 4)); /* a11 a10 a9 a8 */
+            y2 = *((ULong*)(prev + lx)); /* b11 b10 b9 b8 */
+            x2m = (x2 >> 2) & mask;
+            y2m = (y2 >> 2) & mask;
+            x2 = x2 ^(x2m << 2);
+            y2 = y2 ^(y2m << 2);
+            x2m += y2m;
+            x2 += y2;
+            /* y2m, y2 free */
+
+            /* now operate on x1m, x1, y1m, y1, x2m, x2 */
+            /* x1m = a3+b3, a2+b2, a1+b1, a0+b0 */
+            /* y1m = a7+b7, a6+b6, a5+b5, a4+b4 */
+            /* x2m = a11+b11, a10+b10, a9+b9, a8+b8 */
+            /* x1, y1, x2 */
+
+            x1m >>= 8 ;
+            x1 >>= 8;
+            x1m |= (y1m << 24);  /* a4+b4, a3+b3, a2+b2, a1+b1 */
+            x1 |= (y1 << 24);
+            y2m = (y1m << 16);
+            y2 = (y1 << 16);
+            y2m |= (x1m >> 8); /* a5+b5, a4+b4, a3+b3, a2+b2 */
+            y2 |= (x1 >> 8);
+            x1 += rnd2;
+            x1m += y2m;  /* a4+b4+a5+b5, ....., a1+b1+a2+b2 */
+            x1 += y2;
+            x1 &= (mask << 2);
+            x1m += (x1 >> 2);
+            *((ULong*)(rec += 4)) = x1m; /* save x1m */
+
+            y1m >>= 8;
+            y1 >>= 8;
+            y1m |= (x2m << 24); /* a8+b8, a7+b7, a6+b6, a5+b5 */
+            y1 |= (x2 << 24);
+            y2m = (x2m << 16);
+            y2 = (x2 << 16);
+            y2m |= (y1m >> 8); /*  a9+b9, a8+b8, a7+b7, a6+b6,*/
+            y2 |= (y1 >> 8);
+            y1 += rnd2;
+            y1m += y2m;  /* a8+b8+a9+b9, ....., a5+b5+a6+b6 */
+            y1 += y2;
+            y1 &= (mask << 2);
+            y1m += (y1 >> 2);
+            *((ULong*)(rec += 4)) = y1m; /* save y1m */
+
+            rec += 8;
+            prev += offset;
+        }
+        return 1;
+    }
+    else if (tmp == 2)
+    {
+        prev -= 2; /* to word-aligned */
+        for (i = B_SIZE; i > 0; i--)
+        {
+            x1 = *((ULong*)prev); /* load a3 a2 a1 a0 */
+            x2 = *((ULong*)(prev + lx)); /* load b3 b2 b1 b0, another line */
+            y1 = *((ULong*)(prev += 4)); /* a7 a6 a5 a4 */
+            y2 = *((ULong*)(prev + lx)); /* b7 b6 b5 b4 */
+
+            x1m = (x1 >> 2) & mask; /* zero out last 2 bits */
+            x2m = (x2 >> 2) & mask;
+            x1 = x1 ^(x1m << 2);
+            x2 = x2 ^(x2m << 2);
+            x1m += x2m;
+            x1 += x2;
+
+            /* x2m, x2 free */
+            y1m = (y1 >> 2) & mask; /* zero out last 2 bits */
+            y2m = (y2 >> 2) & mask;
+            y1 = y1 ^(y1m << 2);
+            y2 = y2 ^(y2m << 2);
+            y1m += y2m;
+            y1 += y2;
+
+            /* y2m, y2 free */
+            /* x2m, x2 free */
+            x2 = *((ULong*)(prev += 4)); /* a11 a10 a9 a8 */
+            y2 = *((ULong*)(prev + lx)); /* b11 b10 b9 b8 */
+            x2m = (x2 >> 2) & mask;
+            y2m = (y2 >> 2) & mask;
+            x2 = x2 ^(x2m << 2);
+            y2 = y2 ^(y2m << 2);
+            x2m += y2m;
+            x2 += y2;
+            /* y2m, y2 free */
+
+            /* now operate on x1m, x1, y1m, y1, x2m, x2 */
+            /* x1m = a3+b3, a2+b2, a1+b1, a0+b0 */
+            /* y1m = a7+b7, a6+b6, a5+b5, a4+b4 */
+            /* x2m = a11+b11, a10+b10, a9+b9, a8+b8 */
+            /* x1, y1, x2 */
+
+            x1m >>= 16 ;
+            x1 >>= 16;
+            x1m |= (y1m << 16);  /* a5+b5, a4+b4, a3+b3, a2+b2 */
+            x1 |= (y1 << 16);
+            y2m = (y1m << 8);
+            y2 = (y1 << 8);
+            y2m |= (x1m >> 8); /* a6+b6, a5+b5, a4+b4, a3+b3 */
+            y2 |= (x1 >> 8);
+            x1 += rnd2;
+            x1m += y2m;  /* a5+b5+a6+b6, ....., a2+b2+a3+b3 */
+            x1 += y2;
+            x1 &= (mask << 2);
+            x1m += (x1 >> 2);
+            *((ULong*)(rec += 4)) = x1m; /* save x1m */
+
+            y1m >>= 16;
+            y1 >>= 16;
+            y1m |= (x2m << 16); /* a9+b9, a8+b8, a7+b7, a6+b6 */
+            y1 |= (x2 << 16);
+            y2m = (x2m << 8);
+            y2 = (x2 << 8);
+            y2m |= (y1m >> 8); /*  a10+b10, a9+b9, a8+b8, a7+b7,*/
+            y2 |= (y1 >> 8);
+            y1 += rnd2;
+            y1m += y2m;  /* a9+b9+a10+b10, ....., a6+b6+a7+b7 */
+            y1 += y2;
+            y1 &= (mask << 2);
+            y1m += (y1 >> 2);
+            *((ULong*)(rec += 4)) = y1m; /* save y1m */
+
+            rec += 8;
+            prev += offset;
+        }
+        return 1;
+    }
+    else /* tmp == 3 */
+    {
+        prev -= 3; /* to word-aligned */
+        for (i = B_SIZE; i > 0; i--)
+        {
+            x1 = *((ULong*)prev); /* load a3 a2 a1 a0 */
+            x2 = *((ULong*)(prev + lx)); /* load b3 b2 b1 b0, another line */
+            y1 = *((ULong*)(prev += 4)); /* a7 a6 a5 a4 */
+            y2 = *((ULong*)(prev + lx)); /* b7 b6 b5 b4 */
+
+            x1m = (x1 >> 2) & mask; /* zero out last 2 bits */
+            x2m = (x2 >> 2) & mask;
+            x1 = x1 ^(x1m << 2);
+            x2 = x2 ^(x2m << 2);
+            x1m += x2m;
+            x1 += x2;
+
+            /* x2m, x2 free */
+            y1m = (y1 >> 2) & mask; /* zero out last 2 bits */
+            y2m = (y2 >> 2) & mask;
+            y1 = y1 ^(y1m << 2);
+            y2 = y2 ^(y2m << 2);
+            y1m += y2m;
+            y1 += y2;
+
+            /* y2m, y2 free */
+            /* x2m, x2 free */
+            x2 = *((ULong*)(prev += 4)); /* a11 a10 a9 a8 */
+            y2 = *((ULong*)(prev + lx)); /* b11 b10 b9 b8 */
+            x2m = (x2 >> 2) & mask;
+            y2m = (y2 >> 2) & mask;
+            x2 = x2 ^(x2m << 2);
+            y2 = y2 ^(y2m << 2);
+            x2m += y2m;
+            x2 += y2;
+            /* y2m, y2 free */
+
+            /* now operate on x1m, x1, y1m, y1, x2m, x2 */
+            /* x1m = a3+b3, a2+b2, a1+b1, a0+b0 */
+            /* y1m = a7+b7, a6+b6, a5+b5, a4+b4 */
+            /* x2m = a11+b11, a10+b10, a9+b9, a8+b8 */
+            /* x1, y1, x2 */
+
+            x1m >>= 24 ;
+            x1 >>= 24;
+            x1m |= (y1m << 8);  /* a6+b6, a5+b5, a4+b4, a3+b3 */
+            x1 |= (y1 << 8);
+
+            x1m += y1m;  /* a6+b6+a7+b7, ....., a3+b3+a4+b4 */
+            x1 += y1;
+            x1 += rnd2;
+            x1 &= (mask << 2);
+            x1m += (x1 >> 2);
+            *((ULong*)(rec += 4)) = x1m; /* save x1m */
+
+            y1m >>= 24;
+            y1 >>= 24;
+            y1m |= (x2m << 8); /* a10+b10, a9+b9, a8+b8, a7+b7 */
+            y1 |= (x2 << 8);
+            y1m += x2m;  /* a10+b10+a11+b11, ....., a7+b7+a8+b8 */
+            y1 += x2;
+            y1 += rnd2;
+            y1 &= (mask << 2);
+            y1m += (y1 >> 2);
+            *((ULong*)(rec += 4)) = y1m; /* save y1m */
+
+            rec += 8;
+            prev += offset;
+        }
+        return 1;
+    }
+}
+
+
+/*=============================================================================
+    Function:   EncGetPredOutside
+    Date:       04/17/2001
+    Purpose:    - modified from GetPredOutside in the decoder.
+    Modified:    09/24/05
+                use the existing non-initialized padded region
+=============================================================================*/
+// not really needed since padding is included
+#define PAD_CORNER  { temp = *src; \
+                     temp |= (temp<<8); \
+                     temp |= (temp<<16); \
+                     *((ULong*)dst) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                     *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                     *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                     *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                     *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                     *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                     *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                     *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; }
+
+#define PAD_ROW     { temp = *((ULong*)src); \
+                      temp2 = *((ULong*)(src+4)); \
+                      *((ULong*)dst) = temp; \
+                      *((ULong*)(dst+4)) = temp2; \
+                      *((ULong*)(dst+=lx)) = temp; \
+                      *((ULong*)(dst+4)) = temp2; \
+                      *((ULong*)(dst+=lx)) = temp; \
+                      *((ULong*)(dst+4)) = temp2; \
+                      *((ULong*)(dst+=lx)) = temp; \
+                      *((ULong*)(dst+4)) = temp2; \
+                      *((ULong*)(dst+=lx)) = temp; \
+                      *((ULong*)(dst+4)) = temp2; \
+                      *((ULong*)(dst+=lx)) = temp; \
+                      *((ULong*)(dst+4)) = temp2; \
+                      *((ULong*)(dst+=lx)) = temp; \
+                      *((ULong*)(dst+4)) = temp2; \
+                      *((ULong*)(dst+=lx)) = temp; \
+                      *((ULong*)(dst+4)) = temp2; }
+
+#define PAD_COL     { temp = *src;   temp |= (temp<<8);  temp |= (temp<<16); \
+                      *((ULong*)dst) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                      temp = *(src+=lx);     temp |= (temp<<8);  temp |= (temp<<16); \
+                      *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                      temp = *(src+=lx);     temp |= (temp<<8);  temp |= (temp<<16); \
+                      *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                      temp = *(src+=lx);     temp |= (temp<<8);  temp |= (temp<<16); \
+                      *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                      temp = *(src+=lx);     temp |= (temp<<8);  temp |= (temp<<16); \
+                      *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                      temp = *(src+=lx);     temp |= (temp<<8);  temp |= (temp<<16); \
+                      *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                      temp = *(src+=lx);     temp |= (temp<<8);  temp |= (temp<<16); \
+                      *((ULong*)(dst+=lx)) = temp; \
+                     *((ULong*)(dst+4)) = temp; \
+                      temp = *(src+=lx);     temp |= (temp<<8);  temp |= (temp<<16); \
+                      *((ULong*)(dst+=lx)) = temp; \
+                      *((ULong*)(dst+4)) = temp; }
+
+
+Int EncGetPredOutside(Int xpos, Int ypos, UChar *c_prev, UChar *rec,
+                      Int width, Int height, Int rnd1)
+{
+    Int lx;
+    UChar *src, *dst;
+    ULong temp, temp2;
+    Int xoffset;
+
+    lx = width + 16; /* only works for chroma */
+
+    if (xpos < 0)
+    {
+        if (ypos < 0) /* pad top-left */
+        {
+            /* pad corner */
+            src = c_prev;
+            dst = c_prev - (lx << 3) - 8;
+            PAD_CORNER
+
+            /* pad top */
+            dst = c_prev - (lx << 3);
+            PAD_ROW
+
+            /* pad left */
+            dst = c_prev - 8;
+            PAD_COL
+
+            GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+                                             rec, lx, rnd1);
+
+            return 1;
+        }
+        else if ((ypos >> 1) < (height - 8)) /* pad left of frame */
+        {
+            /* pad left */
+            src = c_prev + (ypos >> 1) * lx;
+            dst = src - 8;
+            PAD_COL
+            /* pad extra row */
+            temp = *(src += lx);
+            temp |= (temp << 8);
+            temp |= (temp << 16);
+            *((ULong*)(dst += lx)) = temp;
+            *((ULong*)(dst + 4)) = temp;
+
+            GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+                                             rec, lx, rnd1);
+
+            return 1;
+        }
+        else /* pad bottom-left */
+        {
+            /* pad corner */
+            src = c_prev + (height - 1) * lx;
+            dst = src + lx - 8;
+            PAD_CORNER
+
+            /* pad bottom */
+            dst = src + lx;
+            PAD_ROW
+
+            /* pad left */
+            src -= (lx << 3);
+            src += lx;
+            dst = src - 8;
+            PAD_COL
+
+            GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+                                             rec, lx, rnd1);
+
+            return 1;
+        }
+    }
+    else if ((xpos >> 1) < (width - 8))
+    {
+        if (ypos < 0) /* pad top of frame */
+        {
+            xoffset = (xpos >> 1) & 0x3;
+            src = c_prev + (xpos >> 1) - xoffset;
+            dst = src - (lx << 3);
+            PAD_ROW
+            if (xoffset || (xpos&1))
+            {
+                temp = *((ULong*)(src + 8));
+                dst = src - (lx << 3) + 8;
+                *((ULong*)dst) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+            }
+
+            GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+                                             rec, lx, rnd1);
+
+            return 1;
+        }
+        else /* pad bottom of frame */
+        {
+            xoffset = (xpos >> 1) & 0x3;
+            src = c_prev + (xpos >> 1) - xoffset + (height - 1) * lx;
+            dst = src + lx;
+            PAD_ROW
+            if (xoffset || (xpos&1))
+            {
+                temp = *((ULong*)(src + 8));
+                dst = src + lx + 8;
+                *((ULong*)dst) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+                *((ULong*)(dst += lx)) = temp;
+            }
+
+            GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+                                             rec, lx, rnd1);
+
+            return 1;
+        }
+    }
+    else
+    {
+        if (ypos < 0) /* pad top-right */
+        {
+            /* pad corner */
+            src = c_prev + width - 1;
+            dst = src - (lx << 3) + 1;
+            PAD_CORNER
+
+            /* pad top */
+            src -= 7;
+            dst = src - (lx << 3);
+            PAD_ROW
+
+            /* pad left */
+            src += 7;
+            dst = src + 1;
+            PAD_COL
+
+            GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+                                             rec, lx, rnd1);
+
+            return 1;
+        }
+        else if ((ypos >> 1) < (height - B_SIZE)) /* pad right of frame */
+        {
+            /* pad left */
+            src = c_prev + (ypos >> 1) * lx + width - 1;
+            dst = src + 1;
+            PAD_COL
+            /* pad extra row */
+            temp = *(src += lx);
+            temp |= (temp << 8);
+            temp |= (temp << 16);
+            *((ULong*)(dst += lx)) = temp;
+            *((ULong*)(dst + 4)) = temp;
+
+            GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+                                             rec, lx, rnd1);
+
+            return 1;
+        }
+        else /* pad bottom-right */
+        {
+            /* pad left */
+            src = c_prev + (height - 8) * lx + width - 1;
+            dst = src + 1;
+            PAD_COL
+
+            /* pad corner */
+            dst = src + lx + 1;
+            PAD_CORNER
+
+            /* pad bottom */
+            src -= 7;
+            dst = src + lx;
+            PAD_ROW
+
+            GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+                                             rec, lx, rnd1);
+
+            return 1;
+        }
+    }
+}
+
+/* ====================================================================== /
+    Function : Copy_MB_from_Vop()
+    Date     : 04/17/2001
+ ====================================================================== */
+
+void Copy_MB_from_Vop(UChar *comp, Int yChan[][NCOEFF_BLOCK], Int pitch)
+{
+    Int row, col, i;
+    Int *src1, *src2;
+    Int offset = pitch - MB_SIZE;
+    ULong temp;
+
+    for (i = 0; i < 4; i += 2)
+    {
+        src1 = yChan[i];
+        src2 = yChan[i+1];
+
+        row = B_SIZE;
+        while (row--)
+        {
+            col = B_SIZE;
+            while (col)
+            {
+                temp = *((ULong*)comp);
+                *src1++ = (Int)(temp & 0xFF);
+                *src1++ = (Int)((temp >> 8) & 0xFF);
+                *src1++ = (Int)((temp >> 16) & 0xFF);
+                *src1++ = (Int)((temp >> 24) & 0xFF);
+                comp += 4;
+                col -= 4;
+            }
+            col = B_SIZE;
+            while (col)
+            {
+                temp = *((ULong*)comp);
+                *src2++ = (Int)(temp & 0xFF);
+                *src2++ = (Int)((temp >> 8) & 0xFF);
+                *src2++ = (Int)((temp >> 16) & 0xFF);
+                *src2++ = (Int)((temp >> 24) & 0xFF);
+                comp += 4;
+                col -= 4;
+            }
+            comp += offset;
+        }
+    }
+    return ;
+}
+
+/* ====================================================================== /
+    Function : Copy_B_from_Vop()
+    Date     : 04/17/2001
+/ ====================================================================== */
+
+void Copy_B_from_Vop(UChar *comp, Int cChan[], Int pitch)
+{
+    Int row, col;
+    Int offset = pitch - B_SIZE;
+    ULong temp;
+
+    row = B_SIZE;
+    while (row--)
+    {
+        col = B_SIZE;
+        while (col)
+        {
+            temp = *((ULong*)comp);
+            *cChan++ = (Int)(temp & 0xFF);
+            *cChan++ = (Int)((temp >> 8) & 0xFF);
+            *cChan++ = (Int)((temp >> 16) & 0xFF);
+            *cChan++ = (Int)((temp >> 24) & 0xFF);
+            comp += 4;
+            col -= 4;
+        }
+        comp += offset;
+    }
+}
+
+/* ====================================================================== /
+    Function : Copy_MB_into_Vop()
+    Date     : 04/17/2001
+    History  : From decoder
+/ ====================================================================== */
+
+void Copy_MB_into_Vop(UChar *comp, Int yChan[][NCOEFF_BLOCK], Int pitch)
+{
+    Int row, col, i;
+    Int *src1, *src2;
+    Int offset = pitch - MB_SIZE;
+    UChar mask = 0xFF;
+    Int tmp;
+    ULong temp;
+
+    for (i = 0; i < 4; i += 2)
+    {
+        src1 = yChan[i];
+        src2 = yChan[i+1];
+
+        row = B_SIZE;
+        while (row--)
+        {
+            col = B_SIZE;
+            while (col)
+            {
+                tmp = (*src1++);
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                temp = tmp << 24;
+                tmp = (*src1++);
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                temp |= (tmp << 16);
+                tmp = (*src1++);
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                temp |= (tmp << 8);
+                tmp = (*src1++);
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                temp |= tmp;
+                *((ULong*)comp) = temp;
+                comp += 4;
+                col -= 4;
+            }
+            col = B_SIZE;
+            while (col)
+            {
+                tmp = (*src2++);
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                temp = tmp << 24;
+                tmp = (*src2++);
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                temp |= (tmp << 16);
+                tmp = (*src2++);
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                temp |= (tmp << 8);
+                tmp = (*src2++);
+                if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+                temp |= tmp;
+                *((ULong*)comp) = temp;
+                comp += 4;
+                col -= 4;
+            }
+            comp += offset;
+        }
+    }
+    return ;
+}
+
+
+/* ====================================================================== /
+    Function : Copy_B_into_Vop()
+    Date     : 04/17/2001
+    History  : From decoder
+/ ====================================================================== */
+
+void Copy_B_into_Vop(UChar *comp, Int cChan[], Int pitch)
+{
+    Int row, col;
+    Int offset = pitch - B_SIZE;
+    Int tmp;
+    UChar mask = 0xFF;
+    ULong temp;
+
+    row = B_SIZE;
+    while (row--)
+    {
+        col = B_SIZE;
+        while (col)
+        {
+            tmp = (*cChan++);
+            if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+            temp = tmp << 24;
+            tmp = (*cChan++);
+            if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+            temp |= (tmp << 16);
+            tmp = (*cChan++);
+            if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+            temp |= (tmp << 8);
+            tmp = (*cChan++);
+            if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+            temp |= tmp;
+            *((ULong*)comp) = temp;
+            comp += 4;
+            col -= 4;
+        }
+        comp += offset;
+    }
+}
+
+/* ======================================================================== */
+/*  Function : get_MB( )                                                    */
+/*  Date     : 10/03/2000                                                   */
+/*  Purpose  : Copy 4 Y to reference frame                                  */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+void get_MB(UChar *c_prev, UChar *c_prev_u  , UChar *c_prev_v,
+            Short mb[6][64], Int lx, Int lx_uv)
+
+{
+    Int i, j, count = 0, count1 = 0;
+    Int k1 = lx - MB_SIZE, k2 = lx_uv - B_SIZE;
+
+    for (i = 0; i < B_SIZE; i++)
+    {
+        for (j = 0; j < B_SIZE; j++)
+        {
+            mb[0][count] = (Int)(*c_prev++);
+            mb[4][count] = (Int)(*c_prev_u++);
+            mb[5][count++] = (Int)(*c_prev_v++);
+        }
+
+        for (j = 0; j < B_SIZE; j++)
+            mb[1][count1++] = (Int)(*c_prev++);
+
+        c_prev += k1;
+        c_prev_u += k2;
+        c_prev_v += k2;
+
+
+    }
+
+    count = count1 = 0;
+    for (i = 0; i < B_SIZE; i++)
+    {
+        for (j = 0; j < B_SIZE; j++)
+            mb[2][count++] = (Int)(*c_prev++);
+
+        for (j = 0; j < B_SIZE; j++)
+            mb[3][count1++] = (Int)(*c_prev++);
+
+        c_prev += k1;
+    }
+}
+
+void PutSkippedBlock(UChar *rec, UChar *prev, Int lx)
+{
+    UChar *end;
+    Int offset = (lx - 8) >> 2;
+    Int *src, *dst;
+
+    dst = (Int*)rec;
+    src = (Int*)prev;
+
+    end = prev + (lx << 3);
+
+    do
+    {
+        *dst++ = *src++;
+        *dst++ = *src++;
+        dst += offset;
+        src += offset;
+    }
+    while ((UInt)src < (UInt)end);
+
+    return ;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
new file mode 100644
index 0000000..997b78d
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
@@ -0,0 +1,1741 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "m4venc_oscl.h"
+
+//#define PRINT_MV
+#define MIN_GOP 1   /* minimum size of GOP,  1/23/01, need to be tested */
+
+#define CANDIDATE_DISTANCE  0 /* distance candidate from one another to consider as a distinct one */
+/* shouldn't be more than 3 */
+
+#define ZERO_MV_PREF    0 /* 0: bias (0,0)MV before full-pel search, lowest complexity*/
+/* 1: bias (0,0)MV after full-pel search, before half-pel, highest comp */
+/* 2: bias (0,0)MV after half-pel, high comp, better PSNR */
+
+#define RASTER_REFRESH  /* instead of random INTRA refresh, do raster scan,  2/26/01 */
+
+#ifdef RASTER_REFRESH
+#define TARGET_REFRESH_PER_REGION 4 /* , no. MB per frame to be INTRA refreshed */
+#else
+#define TARGET_REFRESH_PER_REGION 1 /* , no. MB per region to be INTRA refreshed */
+#endif
+
+#define ALL_CAND_EQUAL  10  /*  any number greater than 5 will work */
+
+#define NumPixelMB  256     /*  number of pixels used in SAD calculation */
+
+#define DEF_8X8_WIN 3   /* search region for 8x8 MVs around the 16x16 MV */
+#define MB_Nb  256
+
+#define PREF_NULL_VEC 129   /* for zero vector bias */
+#define PREF_16_VEC 129     /* 1MV bias versus 4MVs*/
+#define PREF_INTRA  512     /* bias for INTRA coding */
+
+const static Int tab_exclude[9][9] =  // [last_loc][curr_loc]
+{
+    {0, 0, 0, 0, 0, 0, 0, 0, 0},
+    {0, 0, 0, 0, 1, 1, 1, 0, 0},
+    {0, 0, 0, 0, 1, 1, 1, 1, 1},
+    {0, 0, 0, 0, 0, 0, 1, 1, 1},
+    {0, 1, 1, 0, 0, 0, 1, 1, 1},
+    {0, 1, 1, 0, 0, 0, 0, 0, 1},
+    {0, 1, 1, 1, 1, 0, 0, 0, 1},
+    {0, 0, 1, 1, 1, 0, 0, 0, 0},
+    {0, 0, 1, 1, 1, 1, 1, 0, 0}
+}; //to decide whether to continue or compute
+
+const static Int refine_next[8][2] =    /* [curr_k][increment] */
+{
+    {0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    void MBMotionSearch(VideoEncData *video, UChar *cur, UChar *best_cand[],
+    Int i0, Int j0, Int type_pred, Int fullsearch, Int *hp_guess);
+
+    Int  fullsearch(VideoEncData *video, Vol *currVol, UChar *ref, UChar *cur,
+                    Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh);
+    Int fullsearchBlk(VideoEncData *video, Vol *currVol, UChar *cent, UChar *cur,
+                      Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh, Int range);
+    void CandidateSelection(Int *mvx, Int *mvy, Int *num_can, Int imb, Int jmb,
+                            VideoEncData *video, Int type_pred);
+    void RasterIntraUpdate(UChar *intraArray, UChar *Mode, Int totalMB, Int numRefresh);
+    void ResetIntraUpdate(UChar *intraArray, Int totalMB);
+    void ResetIntraUpdateRegion(UChar *intraArray, Int start_i, Int rwidth,
+                                Int start_j, Int rheight, Int mbwidth, Int mbheight);
+
+    void MoveNeighborSAD(Int dn[], Int new_loc);
+    Int FindMin(Int dn[]);
+    void PrepareCurMB(VideoEncData *video, UChar *cur);
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************/
+/*  2/28/01, for HYPOTHESIS TESTING */
+#ifdef HTFM     /* defined in mp4def.h */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    void CalcThreshold(double pf, double exp_lamda[], Int nrmlz_th[]);
+    void    HTFMPrepareCurMB(VideoEncData *video, HTFM_Stat *htfm_stat, UChar *cur);
+#ifdef __cplusplus
+}
+#endif
+
+
+#define HTFM_Pf  0.25   /* 3/2/1, probability of false alarm, can be varied from 0 to 0.5 */
+/***************************************/
+#endif
+
+#ifdef _SAD_STAT
+ULong num_MB = 0;
+ULong num_HP_MB = 0;
+ULong num_Blk = 0;
+ULong num_HP_Blk = 0;
+ULong num_cand = 0;
+ULong num_better_hp = 0;
+ULong i_dist_from_guess = 0;
+ULong j_dist_from_guess = 0;
+ULong num_hp_not_zero = 0;
+#endif
+
+
+
+/*==================================================================
+    Function:   MotionEstimation
+    Date:       10/3/2000
+    Purpose:    Go through all macroblock for motion search and
+                determine scene change detection.
+====================================================================*/
+
+void MotionEstimation(VideoEncData *video)
+{
+    UChar use_4mv = video->encParams->MV8x8_Enabled;
+    Vol *currVol = video->vol[video->currLayer];
+    Vop *currVop = video->currVop;
+    VideoEncFrameIO *currFrame = video->input;
+    Int i, j, comp;
+    Int mbwidth = currVol->nMBPerRow;
+    Int mbheight = currVol->nMBPerCol;
+    Int totalMB = currVol->nTotalMB;
+    Int width = currFrame->pitch;
+    UChar *mode_mb, *Mode = video->headerInfo.Mode;
+    MOT *mot_mb, **mot = video->mot;
+    UChar *intraArray = video->intraArray;
+    Int FS_en = video->encParams->FullSearch_Enabled;
+    void (*ComputeMBSum)(UChar *, Int, MOT *) = video->functionPointer->ComputeMBSum;
+    void (*ChooseMode)(UChar*, UChar*, Int, Int) = video->functionPointer->ChooseMode;
+
+    Int numIntra, start_i, numLoop, incr_i;
+    Int mbnum, offset;
+    UChar *cur, *best_cand[5];
+    Int sad8 = 0, sad16 = 0;
+    Int totalSAD = 0;   /* average SAD for rate control */
+    Int skip_halfpel_4mv;
+    Int f_code_p, f_code_n, max_mag = 0, min_mag = 0;
+    Int type_pred;
+    Int xh[5] = {0, 0, 0, 0, 0};
+    Int yh[5] = {0, 0, 0, 0, 0}; /* half-pel */
+    UChar hp_mem4MV[17*17*4];
+
+#ifdef HTFM
+    /***** HYPOTHESIS TESTING ********/  /* 2/28/01 */
+    Int collect = 0;
+    HTFM_Stat htfm_stat;
+    double newvar[16];
+    double exp_lamda[15];
+    /*********************************/
+#endif
+    Int hp_guess = 0;
+#ifdef PRINT_MV
+    FILE *fp_debug;
+#endif
+
+//  FILE *fstat;
+//  static int frame_num = 0;
+
+    offset = 0;
+
+    if (video->currVop->predictionType == I_VOP)
+    {   /* compute the SAV */
+        mbnum = 0;
+        cur = currFrame->yChan;
+
+        for (j = 0; j < mbheight; j++)
+        {
+            for (i = 0; i < mbwidth; i++)
+            {
+                video->mbnum = mbnum;
+                mot_mb = mot[mbnum];
+
+                (*ComputeMBSum)(cur + (i << 4), width, mot_mb);
+
+                totalSAD += mot_mb[0].sad;
+
+                mbnum++;
+            }
+            cur += (width << 4);
+        }
+
+        video->sumMAD = (float)totalSAD / (float)NumPixelMB;
+
+        ResetIntraUpdate(intraArray, totalMB);
+
+        return  ;
+    }
+
+    /* 09/20/05 */
+    if (video->prevBaseVop->padded == 0 && !video->encParams->H263_Enabled)
+    {
+        PaddingEdge(video->prevBaseVop);
+        video->prevBaseVop->padded = 1;
+    }
+
+    /* Random INTRA update */
+    /*  suggest to do it in CodeMB */
+    /*  2/21/2001 */
+    //if(video->encParams->RC_Type == CBR_1 || video->encParams->RC_Type == CBR_2)
+    if (video->currLayer == 0 && video->encParams->Refresh)
+    {
+        RasterIntraUpdate(intraArray, Mode, totalMB, video->encParams->Refresh);
+    }
+
+    video->sad_extra_info = NULL;
+
+#ifdef HTFM
+    /***** HYPOTHESIS TESTING ********/  /* 2/28/01 */
+    InitHTFM(video, &htfm_stat, newvar, &collect);
+    /*********************************/
+#endif
+
+    if ((video->encParams->SceneChange_Det == 1) /*&& video->currLayer==0 */
+            && ((video->encParams->LayerFrameRate[0] < 5.0) || (video->numVopsInGOP > MIN_GOP)))
+        /* do not try to detect a new scene if low frame rate and too close to previous I-frame */
+    {
+        incr_i = 2;
+        numLoop = 2;
+        start_i = 1;
+        type_pred = 0; /* for initial candidate selection */
+    }
+    else
+    {
+        incr_i = 1;
+        numLoop = 1;
+        start_i = 0;
+        type_pred = 2;
+    }
+
+    /* First pass, loop thru half the macroblock */
+    /* determine scene change */
+    /* Second pass, for the rest of macroblocks */
+    numIntra = 0;
+    while (numLoop--)
+    {
+        for (j = 0; j < mbheight; j++)
+        {
+            if (incr_i > 1)
+                start_i = (start_i == 0 ? 1 : 0) ; /* toggle 0 and 1 */
+
+            offset = width * (j << 4) + (start_i << 4);
+
+            mbnum = j * mbwidth + start_i;
+
+            for (i = start_i; i < mbwidth; i += incr_i)
+            {
+                video->mbnum = mbnum;
+                mot_mb = mot[mbnum];
+                mode_mb = Mode + mbnum;
+
+                cur = currFrame->yChan + offset;
+
+
+                if (*mode_mb != MODE_INTRA)
+                {
+#if defined(HTFM)
+                    HTFMPrepareCurMB(video, &htfm_stat, cur);
+#else
+                    PrepareCurMB(video, cur);
+#endif
+                    /************************************************************/
+                    /******** full-pel 1MV and 4MVs search **********************/
+
+#ifdef _SAD_STAT
+                    num_MB++;
+#endif
+                    MBMotionSearch(video, cur, best_cand, i << 4, j << 4, type_pred,
+                                   FS_en, &hp_guess);
+
+#ifdef PRINT_MV
+                    fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+                    fprintf(fp_debug, "#%d (%d,%d,%d) : ", mbnum, mot_mb[0].x, mot_mb[0].y, mot_mb[0].sad);
+                    fprintf(fp_debug, "(%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : ==>\n",
+                            mot_mb[1].x, mot_mb[1].y, mot_mb[1].sad,
+                            mot_mb[2].x, mot_mb[2].y, mot_mb[2].sad,
+                            mot_mb[3].x, mot_mb[3].y, mot_mb[3].sad,
+                            mot_mb[4].x, mot_mb[4].y, mot_mb[4].sad);
+                    fclose(fp_debug);
+#endif
+                    sad16 = mot_mb[0].sad;
+#ifdef NO_INTER4V
+                    sad8 = sad16;
+#else
+                    sad8 = mot_mb[1].sad + mot_mb[2].sad + mot_mb[3].sad + mot_mb[4].sad;
+#endif
+
+                    /* choose between INTRA or INTER */
+                    (*ChooseMode)(mode_mb, cur, width, ((sad8 < sad16) ? sad8 : sad16));
+                }
+                else    /* INTRA update, use for prediction 3/23/01 */
+                {
+                    mot_mb[0].x = mot_mb[0].y = 0;
+                }
+
+                if (*mode_mb == MODE_INTRA)
+                {
+                    numIntra++ ;
+
+                    /* compute SAV for rate control and fast DCT, 11/28/00 */
+                    (*ComputeMBSum)(cur, width, mot_mb);
+
+                    /* leave mot_mb[0] as it is for fast motion search */
+                    /* set the 4 MVs to zeros */
+                    for (comp = 1; comp <= 4; comp++)
+                    {
+                        mot_mb[comp].x = 0;
+                        mot_mb[comp].y = 0;
+                    }
+#ifdef PRINT_MV
+                    fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+                    fprintf(fp_debug, "\n");
+                    fclose(fp_debug);
+#endif
+                }
+                else /* *mode_mb = MODE_INTER;*/
+                {
+                    if (video->encParams->HalfPel_Enabled)
+                    {
+#ifdef _SAD_STAT
+                        num_HP_MB++;
+#endif
+                        /* find half-pel resolution motion vector */
+                        FindHalfPelMB(video, cur, mot_mb, best_cand[0],
+                                      i << 4, j << 4, xh, yh, hp_guess);
+#ifdef PRINT_MV
+                        fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+                        fprintf(fp_debug, "(%d,%d), %d\n", mot_mb[0].x, mot_mb[0].y, mot_mb[0].sad);
+                        fclose(fp_debug);
+#endif
+                        skip_halfpel_4mv = ((sad16 - mot_mb[0].sad) <= (MB_Nb >> 1) + 1);
+                        sad16 = mot_mb[0].sad;
+
+#ifndef NO_INTER4V
+                        if (use_4mv && !skip_halfpel_4mv)
+                        {
+                            /* Also decide 1MV or 4MV !!!!!!!!*/
+                            sad8 = FindHalfPelBlk(video, cur, mot_mb, sad16,
+                                                  best_cand, mode_mb, i << 4, j << 4, xh, yh, hp_mem4MV);
+
+#ifdef PRINT_MV
+                            fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+                            fprintf(fp_debug, " (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) \n",
+                                    mot_mb[1].x, mot_mb[1].y, mot_mb[1].sad,
+                                    mot_mb[2].x, mot_mb[2].y, mot_mb[2].sad,
+                                    mot_mb[3].x, mot_mb[3].y, mot_mb[3].sad,
+                                    mot_mb[4].x, mot_mb[4].y, mot_mb[4].sad);
+                            fclose(fp_debug);
+#endif
+                        }
+#endif /* NO_INTER4V */
+                    }
+                    else    /* HalfPel_Enabled ==0  */
+                    {
+#ifndef NO_INTER4V
+                        //if(sad16 < sad8-PREF_16_VEC)
+                        if (sad16 - PREF_16_VEC > sad8)
+                        {
+                            *mode_mb = MODE_INTER4V;
+                        }
+#endif
+                    }
+#if (ZERO_MV_PREF==2)   /* use mot_mb[7].sad as d0 computed in MBMotionSearch*/
+                    /******************************************************/
+                    if (mot_mb[7].sad - PREF_NULL_VEC < sad16 && mot_mb[7].sad - PREF_NULL_VEC < sad8)
+                    {
+                        mot_mb[0].sad = mot_mb[7].sad - PREF_NULL_VEC;
+                        mot_mb[0].x = mot_mb[0].y = 0;
+                        *mode_mb = MODE_INTER;
+                    }
+                    /******************************************************/
+#endif
+                    if (*mode_mb == MODE_INTER)
+                    {
+                        if (mot_mb[0].x == 0 && mot_mb[0].y == 0)   /* use zero vector */
+                            mot_mb[0].sad += PREF_NULL_VEC; /* add back the bias */
+
+                        mot_mb[1].sad = mot_mb[2].sad = mot_mb[3].sad = mot_mb[4].sad = (mot_mb[0].sad + 2) >> 2;
+                        mot_mb[1].x = mot_mb[2].x = mot_mb[3].x = mot_mb[4].x = mot_mb[0].x;
+                        mot_mb[1].y = mot_mb[2].y = mot_mb[3].y = mot_mb[4].y = mot_mb[0].y;
+
+                    }
+                }
+
+                /* find maximum magnitude */
+                /* compute average SAD for rate control, 11/28/00 */
+                if (*mode_mb == MODE_INTER)
+                {
+#ifdef PRINT_MV
+                    fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+                    fprintf(fp_debug, "%d MODE_INTER\n", mbnum);
+                    fclose(fp_debug);
+#endif
+                    totalSAD += mot_mb[0].sad;
+                    if (mot_mb[0].x > max_mag)
+                        max_mag = mot_mb[0].x;
+                    if (mot_mb[0].y > max_mag)
+                        max_mag = mot_mb[0].y;
+                    if (mot_mb[0].x < min_mag)
+                        min_mag = mot_mb[0].x;
+                    if (mot_mb[0].y < min_mag)
+                        min_mag = mot_mb[0].y;
+                }
+                else if (*mode_mb == MODE_INTER4V)
+                {
+#ifdef PRINT_MV
+                    fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+                    fprintf(fp_debug, "%d MODE_INTER4V\n", mbnum);
+                    fclose(fp_debug);
+#endif
+                    totalSAD += sad8;
+                    for (comp = 1; comp <= 4; comp++)
+                    {
+                        if (mot_mb[comp].x > max_mag)
+                            max_mag = mot_mb[comp].x;
+                        if (mot_mb[comp].y > max_mag)
+                            max_mag = mot_mb[comp].y;
+                        if (mot_mb[comp].x < min_mag)
+                            min_mag = mot_mb[comp].x;
+                        if (mot_mb[comp].y < min_mag)
+                            min_mag = mot_mb[comp].y;
+                    }
+                }
+                else    /* MODE_INTRA */
+                {
+#ifdef PRINT_MV
+                    fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+                    fprintf(fp_debug, "%d MODE_INTRA\n", mbnum);
+                    fclose(fp_debug);
+#endif
+                    totalSAD += mot_mb[0].sad;
+                }
+                mbnum += incr_i;
+                offset += (incr_i << 4);
+
+            }
+        }
+
+        if (incr_i > 1 && numLoop) /* scene change on and first loop */
+        {
+            //if(numIntra > ((totalMB>>3)<<1) + (totalMB>>3)) /* 75% of 50%MBs */
+            if (numIntra > (0.30*(totalMB / 2.0))) /* 15% of 50%MBs */
+            {
+                /******** scene change detected *******************/
+                currVop->predictionType = I_VOP;
+                M4VENC_MEMSET(Mode, MODE_INTRA, sizeof(UChar)*totalMB); /* set this for MB level coding*/
+                currVop->quantizer = video->encParams->InitQuantIvop[video->currLayer];
+
+                /* compute the SAV for rate control & fast DCT */
+                totalSAD = 0;
+                offset = 0;
+                mbnum = 0;
+                cur = currFrame->yChan;
+
+                for (j = 0; j < mbheight; j++)
+                {
+                    for (i = 0; i < mbwidth; i++)
+                    {
+                        video->mbnum = mbnum;
+                        mot_mb = mot[mbnum];
+
+
+                        (*ComputeMBSum)(cur + (i << 4), width, mot_mb);
+                        totalSAD += mot_mb[0].sad;
+
+                        mbnum++;
+                    }
+                    cur += (width << 4);
+                }
+
+                video->sumMAD = (float)totalSAD / (float)NumPixelMB;
+                ResetIntraUpdate(intraArray, totalMB);
+                /* video->numVopsInGOP=0; 3/13/01 move it to vop.c*/
+
+                return ;
+            }
+        }
+        /******** no scene change, continue motion search **********************/
+        start_i = 0;
+        type_pred++; /* second pass */
+    }
+
+    video->sumMAD = (float)totalSAD / (float)NumPixelMB;    /* avg SAD */
+
+    /* find f_code , 10/27/2000 */
+    f_code_p = 1;
+    while ((max_mag >> (4 + f_code_p)) > 0)
+        f_code_p++;
+
+    f_code_n = 1;
+    min_mag *= -1;
+    while ((min_mag - 1) >> (4 + f_code_n) > 0)
+        f_code_n++;
+
+    currVop->fcodeForward = (f_code_p > f_code_n ? f_code_p : f_code_n);
+
+#ifdef HTFM
+    /***** HYPOTHESIS TESTING ********/  /* 2/28/01 */
+    if (collect)
+    {
+        collect = 0;
+        UpdateHTFM(video, newvar, exp_lamda, &htfm_stat);
+    }
+    /*********************************/
+#endif
+
+    return ;
+}
+
+
+#ifdef HTFM
+void InitHTFM(VideoEncData *video, HTFM_Stat *htfm_stat, double *newvar, Int *collect)
+{
+    Int i;
+    Int lx = video->currVop->width; //  padding
+    Int lx2 = lx << 1;
+    Int lx3 = lx2 + lx;
+    Int rx = video->currVop->pitch;
+    Int rx2 = rx << 1;
+    Int rx3 = rx2 + rx;
+
+    Int *offset, *offset2;
+
+    /* 4/11/01, collect data every 30 frames, doesn't have to be base layer */
+    if (((Int)video->numVopsInGOP) % 30 == 1)
+    {
+
+        *collect = 1;
+
+        htfm_stat->countbreak = 0;
+        htfm_stat->abs_dif_mad_avg = 0;
+
+        for (i = 0; i < 16; i++)
+        {
+            newvar[i] = 0.0;
+        }
+//      video->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM_Collect;
+        video->functionPointer->SAD_Macroblock = &SAD_MB_HTFM_Collect;
+        video->functionPointer->SAD_MB_HalfPel[0] = NULL;
+        video->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFM_Collectxh;
+        video->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFM_Collectyh;
+        video->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFM_Collectxhyh;
+        video->sad_extra_info = (void*)(htfm_stat);
+        offset = htfm_stat->offsetArray;
+        offset2 = htfm_stat->offsetRef;
+    }
+    else
+    {
+//      video->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM;
+        video->functionPointer->SAD_Macroblock = &SAD_MB_HTFM;
+        video->functionPointer->SAD_MB_HalfPel[0] = NULL;
+        video->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFMxh;
+        video->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFMyh;
+        video->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFMxhyh;
+        video->sad_extra_info = (void*)(video->nrmlz_th);
+        offset = video->nrmlz_th + 16;
+        offset2 = video->nrmlz_th + 32;
+    }
+
+    offset[0] = 0;
+    offset[1] = lx2 + 2;
+    offset[2] = 2;
+    offset[3] = lx2;
+    offset[4] = lx + 1;
+    offset[5] = lx3 + 3;
+    offset[6] = lx + 3;
+    offset[7] = lx3 + 1;
+    offset[8] = lx;
+    offset[9] = lx3 + 2;
+    offset[10] = lx3 ;
+    offset[11] = lx + 2 ;
+    offset[12] = 1;
+    offset[13] = lx2 + 3;
+    offset[14] = lx2 + 1;
+    offset[15] = 3;
+
+    offset2[0] = 0;
+    offset2[1] = rx2 + 2;
+    offset2[2] = 2;
+    offset2[3] = rx2;
+    offset2[4] = rx + 1;
+    offset2[5] = rx3 + 3;
+    offset2[6] = rx + 3;
+    offset2[7] = rx3 + 1;
+    offset2[8] = rx;
+    offset2[9] = rx3 + 2;
+    offset2[10] = rx3 ;
+    offset2[11] = rx + 2 ;
+    offset2[12] = 1;
+    offset2[13] = rx2 + 3;
+    offset2[14] = rx2 + 1;
+    offset2[15] = 3;
+
+    return ;
+}
+
+void UpdateHTFM(VideoEncData *video, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat)
+{
+    if (htfm_stat->countbreak == 0)
+        htfm_stat->countbreak = 1;
+
+    newvar[0] = (double)(htfm_stat->abs_dif_mad_avg) / (htfm_stat->countbreak * 16.);
+
+    if (newvar[0] < 0.001)
+    {
+        newvar[0] = 0.001; /* to prevent floating overflow */
+    }
+    exp_lamda[0] =  1 / (newvar[0] * 1.4142136);
+    exp_lamda[1] = exp_lamda[0] * 1.5825;
+    exp_lamda[2] = exp_lamda[0] * 2.1750;
+    exp_lamda[3] = exp_lamda[0] * 3.5065;
+    exp_lamda[4] = exp_lamda[0] * 3.1436;
+    exp_lamda[5] = exp_lamda[0] * 3.5315;
+    exp_lamda[6] = exp_lamda[0] * 3.7449;
+    exp_lamda[7] = exp_lamda[0] * 4.5854;
+    exp_lamda[8] = exp_lamda[0] * 4.6191;
+    exp_lamda[9] = exp_lamda[0] * 5.4041;
+    exp_lamda[10] = exp_lamda[0] * 6.5974;
+    exp_lamda[11] = exp_lamda[0] * 10.5341;
+    exp_lamda[12] = exp_lamda[0] * 10.0719;
+    exp_lamda[13] = exp_lamda[0] * 12.0516;
+    exp_lamda[14] = exp_lamda[0] * 15.4552;
+
+    CalcThreshold(HTFM_Pf, exp_lamda, video->nrmlz_th);
+    return ;
+}
+
+
+void CalcThreshold(double pf, double exp_lamda[], Int nrmlz_th[])
+{
+    Int i;
+    double temp[15];
+    //  printf("\nLamda: ");
+
+    /* parametric PREMODELling */
+    for (i = 0; i < 15; i++)
+    {
+        //    printf("%g ",exp_lamda[i]);
+        if (pf < 0.5)
+            temp[i] = 1 / exp_lamda[i] * M4VENC_LOG(2 * pf);
+        else
+            temp[i] = -1 / exp_lamda[i] * M4VENC_LOG(2 * (1 - pf));
+    }
+
+    nrmlz_th[15] = 0;
+    for (i = 0; i < 15; i++)        /* scale upto no.pixels */
+        nrmlz_th[i] = (Int)(temp[i] * ((i + 1) << 4) + 0.5);
+
+    return ;
+}
+
+void    HTFMPrepareCurMB(VideoEncData *video, HTFM_Stat *htfm_stat, UChar *cur)
+{
+    void* tmp = (void*)(video->currYMB);
+    ULong *htfmMB = (ULong*)tmp;
+    UChar *ptr, byte;
+    Int *offset;
+    Int i;
+    ULong word;
+    Int width = video->currVop->width;
+
+    if (((Int)video->numVopsInGOP) % 30 == 1)
+    {
+        offset = htfm_stat->offsetArray;
+    }
+    else
+    {
+        offset = video->nrmlz_th + 16;
+    }
+
+    for (i = 0; i < 16; i++)
+    {
+        ptr = cur + offset[i];
+        word = ptr[0];
+        byte = ptr[4];
+        word |= (byte << 8);
+        byte = ptr[8];
+        word |= (byte << 16);
+        byte = ptr[12];
+        word |= (byte << 24);
+        *htfmMB++ = word;
+
+        word = *(ptr += (width << 2));
+        byte = ptr[4];
+        word |= (byte << 8);
+        byte = ptr[8];
+        word |= (byte << 16);
+        byte = ptr[12];
+        word |= (byte << 24);
+        *htfmMB++ = word;
+
+        word = *(ptr += (width << 2));
+        byte = ptr[4];
+        word |= (byte << 8);
+        byte = ptr[8];
+        word |= (byte << 16);
+        byte = ptr[12];
+        word |= (byte << 24);
+        *htfmMB++ = word;
+
+        word = *(ptr += (width << 2));
+        byte = ptr[4];
+        word |= (byte << 8);
+        byte = ptr[8];
+        word |= (byte << 16);
+        byte = ptr[12];
+        word |= (byte << 24);
+        *htfmMB++ = word;
+    }
+
+    return ;
+}
+
+
+#endif
+
+void    PrepareCurMB(VideoEncData *video, UChar *cur)
+{
+    void* tmp = (void*)(video->currYMB);
+    ULong *currYMB = (ULong*)tmp;
+    Int i;
+    Int width = video->currVop->width;
+
+    cur -= width;
+
+    for (i = 0; i < 16; i++)
+    {
+        *currYMB++ = *((ULong*)(cur += width));
+        *currYMB++ = *((ULong*)(cur + 4));
+        *currYMB++ = *((ULong*)(cur + 8));
+        *currYMB++ = *((ULong*)(cur + 12));
+    }
+
+    return ;
+}
+
+
+/*==================================================================
+    Function:   MBMotionSearch
+    Date:       09/06/2000
+    Purpose:    Perform motion estimation for a macroblock.
+                Find 1MV and 4MVs in half-pels resolutions.
+                Using ST1 algorithm provided by Chalidabhongse and Kuo
+                CSVT March'98.
+
+==================================================================*/
+
+void MBMotionSearch(VideoEncData *video, UChar *cur, UChar *best_cand[],
+                    Int i0, Int j0, Int type_pred, Int FS_en, Int *hp_guess)
+{
+    Vol *currVol = video->vol[video->currLayer];
+    UChar *ref, *cand, *ncand = NULL, *cur8;
+    void *extra_info = video->sad_extra_info;
+    Int mbnum = video->mbnum;
+    Int width = video->currVop->width; /* 6/12/01, must be multiple of 16 */
+    Int height = video->currVop->height;
+    MOT **mot = video->mot;
+    UChar use_4mv = video->encParams->MV8x8_Enabled;
+    UChar h263_mode = video->encParams->H263_Enabled;
+    Int(*SAD_Macroblock)(UChar*, UChar*, Int, void*) = video->functionPointer->SAD_Macroblock;
+    Int(*SAD_Block)(UChar*, UChar*, Int, Int, void*) = video->functionPointer->SAD_Block;
+    VideoEncParams *encParams = video->encParams;
+    Int range = encParams->SearchRange;
+
+    Int lx = video->currVop->pitch; /* padding */
+    Int comp;
+    Int i, j, imin, jmin, ilow, ihigh, jlow, jhigh, iorg, jorg;
+    Int d, dmin, dn[9];
+#if (ZERO_MV_PREF==1)   /* compute (0,0) MV at the end */
+    Int d0;
+#endif
+    Int k;
+    Int mvx[5], mvy[5], imin0, jmin0;
+    Int num_can, center_again;
+    Int last_loc, new_loc = 0;
+    Int step, max_step = range >> 1;
+    Int next;
+
+    ref = video->forwardRefVop->yChan; /* origin of actual frame */
+
+    cur = video->currYMB; /* use smaller memory space for current MB */
+
+    /*  find limit of the search (adjusting search range)*/
+
+    if (!h263_mode)
+    {
+        ilow = i0 - range;
+        if (ilow < -15)
+            ilow = -15;
+        ihigh = i0 + range - 1;
+        if (ihigh > width - 1)
+            ihigh = width - 1;
+        jlow = j0 - range;
+        if (jlow < -15)
+            jlow = -15;
+        jhigh = j0 + range - 1;
+        if (jhigh > height - 1)
+            jhigh = height - 1;
+    }
+    else
+    {
+        ilow = i0 - range;
+        if (ilow < 0)
+            ilow = 0;
+        ihigh = i0 + range - 1;
+        if (ihigh > width - 16)
+            ihigh = width - 16;
+        jlow = j0 - range;
+        if (jlow < 0)
+            jlow = 0;
+        jhigh = j0 + range - 1;
+        if (jhigh > height - 16)
+            jhigh = height - 16;
+    }
+
+    imin = i0;
+    jmin = j0; /* needed for fullsearch */
+    ncand = ref + imin + jmin * lx;
+
+    /* for first row of MB, fullsearch can be used */
+    if (FS_en)
+    {
+        *hp_guess = 0; /* no guess for fast half-pel */
+
+        dmin =  fullsearch(video, currVol, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh);
+
+        ncand = ref + imin + jmin * lx;
+
+        mot[mbnum][0].sad = dmin;
+        mot[mbnum][0].x = (imin - i0) << 1;
+        mot[mbnum][0].y = (jmin - j0) << 1;
+        imin0 = imin << 1;  /* 16x16 MV in half-pel resolution */
+        jmin0 = jmin << 1;
+        best_cand[0] = ncand;
+    }
+    else
+    {   /* 4/7/01, modified this testing for fullsearch the top row to only upto (0,3) MB */
+        /*            upto 30% complexity saving with the same complexity */
+        if (video->forwardRefVop->predictionType == I_VOP && j0 == 0 && i0 <= 64 && type_pred != 1)
+        {
+            *hp_guess = 0; /* no guess for fast half-pel */
+            dmin =  fullsearch(video, currVol, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh);
+            ncand = ref + imin + jmin * lx;
+        }
+        else
+        {
+            /************** initialize candidate **************************/
+            /* find initial motion vector */
+            CandidateSelection(mvx, mvy, &num_can, i0 >> 4, j0 >> 4, video, type_pred);
+
+            dmin = 65535;
+
+            /* check if all are equal */
+            if (num_can == ALL_CAND_EQUAL)
+            {
+                i = i0 + mvx[0];
+                j = j0 + mvy[0];
+
+                if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+                {
+                    cand = ref + i + j * lx;
+
+                    d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+
+                    if (d < dmin)
+                    {
+                        dmin = d;
+                        imin = i;
+                        jmin = j;
+                        ncand = cand;
+                    }
+                }
+            }
+            else
+            {
+                /************** evaluate unique candidates **********************/
+                for (k = 0; k < num_can; k++)
+                {
+                    i = i0 + mvx[k];
+                    j = j0 + mvy[k];
+
+                    if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+                    {
+                        cand = ref + i + j * lx;
+                        d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+
+                        if (d < dmin)
+                        {
+                            dmin = d;
+                            imin = i;
+                            jmin = j;
+                            ncand = cand;
+                        }
+                        else if ((d == dmin) && PV_ABS(mvx[k]) + PV_ABS(mvy[k]) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
+                        {
+                            dmin = d;
+                            imin = i;
+                            jmin = j;
+                            ncand = cand;
+                        }
+                    }
+                }
+            }
+            if (num_can == 0 || dmin == 65535) /* no candidate selected */
+            {
+                ncand = ref + i0 + j0 * lx; /* use (0,0) MV as initial value */
+                mot[mbnum][7].sad = dmin = (*SAD_Macroblock)(ncand, cur, (65535 << 16) | lx, extra_info);
+#if (ZERO_MV_PREF==1)   /* compute (0,0) MV at the end */
+                d0 = dmin;
+#endif
+                imin = i0;
+                jmin = j0;
+            }
+
+#if (ZERO_MV_PREF==0)  /*  COMPUTE ZERO VECTOR FIRST !!!!!*/
+            dmin -= PREF_NULL_VEC;
+#endif
+
+            /******************* local refinement ***************************/
+            center_again = 0;
+            last_loc = new_loc = 0;
+            //          ncand = ref + jmin*lx + imin;  /* center of the search */
+            step = 0;
+            dn[0] = dmin;
+            while (!center_again && step <= max_step)
+            {
+
+                MoveNeighborSAD(dn, last_loc);
+
+                center_again = 1;
+                i = imin;
+                j = jmin - 1;
+                cand = ref + i + j * lx;
+
+                /*  starting from [0,-1] */
+                /* spiral check one step at a time*/
+                for (k = 2; k <= 8; k += 2)
+                {
+                    if (!tab_exclude[last_loc][k]) /* exclude last step computation */
+                    {       /* not already computed */
+                        if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+                        {
+                            d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+                            dn[k] = d; /* keep it for half pel use */
+
+                            if (d < dmin)
+                            {
+                                ncand = cand;
+                                dmin = d;
+                                imin = i;
+                                jmin = j;
+                                center_again = 0;
+                                new_loc = k;
+                            }
+                            else if ((d == dmin) && PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
+                            {
+                                ncand = cand;
+                                imin = i;
+                                jmin = j;
+                                center_again = 0;
+                                new_loc = k;
+                            }
+                        }
+                    }
+                    if (k == 8)  /* end side search*/
+                    {
+                        if (!center_again)
+                        {
+                            k = -1; /* start diagonal search */
+                            cand -= lx;
+                            j--;
+                        }
+                    }
+                    else
+                    {
+                        next = refine_next[k][0];
+                        i += next;
+                        cand += next;
+                        next = refine_next[k][1];
+                        j += next;
+                        cand += lx * next;
+                    }
+                }
+                last_loc = new_loc;
+                step ++;
+            }
+            if (!center_again)
+                MoveNeighborSAD(dn, last_loc);
+
+            *hp_guess = FindMin(dn);
+
+        }
+
+#if (ZERO_MV_PREF==1)   /* compute (0,0) MV at the end */
+        if (d0 - PREF_NULL_VEC < dmin)
+        {
+            ncand = ref + i0 + j0 * lx;
+            dmin = d0;
+            imin = i0;
+            jmin = j0;
+        }
+#endif
+        mot[mbnum][0].sad = dmin;
+        mot[mbnum][0].x = (imin - i0) << 1;
+        mot[mbnum][0].y = (jmin - j0) << 1;
+        imin0 = imin << 1;  /* 16x16 MV in half-pel resolution */
+        jmin0 = jmin << 1;
+        best_cand[0] = ncand;
+    }
+    /* imin and jmin is the best 1 MV */
+#ifndef NO_INTER4V
+    /*******************  Find 4 motion vectors ****************************/
+    if (use_4mv && !h263_mode)
+    {
+#ifdef _SAD_STAT
+        num_Blk += 4;
+#endif
+        /* starting from the best 1MV */
+        //offset = imin + jmin*lx;
+        iorg = i0;
+        jorg = j0;
+
+        for (comp = 0; comp < 4; comp++)
+        {
+            i0 = iorg + ((comp & 1) << 3);
+            j0 = jorg + ((comp & 2) << 2);
+
+            imin = (imin0 >> 1) + ((comp & 1) << 3);    /* starting point from 16x16 MV */
+            jmin = (jmin0 >> 1) + ((comp & 2) << 2);
+            ncand = ref + imin + jmin * lx;
+
+            cur8 = cur + ((comp & 1) << 3) + (((comp & 2) << 2) << 4) ; /* 11/30/05, smaller cache */
+
+            /*  find limit of the search (adjusting search range)*/
+            ilow = i0 - range;
+            ihigh = i0 + range - 1 ;/* 4/9/01 */
+            if (ilow < -15)
+                ilow = -15;
+            if (ihigh > width - 1)
+                ihigh = width - 1;
+            jlow = j0 - range;
+            jhigh = j0 + range - 1 ;/* 4/9/01 */
+            if (jlow < -15)
+                jlow = -15;
+            if (jhigh > height - 1)
+                jhigh = height - 1;
+
+            SAD_Block = video->functionPointer->SAD_Block;
+
+            if (FS_en)  /* fullsearch enable, center around 16x16 MV */
+            {
+                dmin =  fullsearchBlk(video, currVol, ncand, cur8, &imin, &jmin, ilow, ihigh, jlow, jhigh, range);
+                ncand = ref + imin + jmin * lx;
+
+                mot[mbnum][comp+1].sad = dmin;
+                mot[mbnum][comp+1].x = (imin - i0) << 1;
+                mot[mbnum][comp+1].y = (jmin - j0) << 1;
+                best_cand[comp+1] = ncand;
+            }
+            else    /* no fullsearch, do local search */
+            {
+                /* starting point from 16x16 */
+                dmin = (*SAD_Block)(ncand, cur8, 65536, lx, extra_info);
+
+                /******************* local refinement ***************************/
+                center_again = 0;
+                last_loc = 0;
+
+                while (!center_again)
+                {
+                    center_again = 1;
+                    i = imin;
+                    j = jmin - 1;
+                    cand = ref + i + j * lx;
+
+                    /*  starting from [0,-1] */
+                    /* spiral check one step at a time*/
+                    for (k = 2; k <= 8; k += 2)
+                    {
+                        if (!tab_exclude[last_loc][k]) /* exclude last step computation */
+                        {       /* not already computed */
+                            if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+                            {
+                                d = (*SAD_Block)(cand, cur8, dmin, lx, extra_info);
+
+                                if (d < dmin)
+                                {
+                                    ncand = cand;
+                                    dmin = d;
+                                    imin = i;
+                                    jmin = j;
+                                    center_again = 0;
+                                    new_loc = k;
+                                }
+                                else if ((d == dmin) &&
+                                         PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
+                                {
+                                    ncand = cand;
+                                    imin = i;
+                                    jmin = j;
+                                    center_again = 0;
+                                    new_loc = k;
+                                }
+                            }
+                        }
+                        if (k == 8)  /* end side search*/
+                        {
+                            if (!center_again)
+                            {
+                                k = -1; /* start diagonal search */
+                                if (j <= height - 1 && j > 0)   cand -= lx;
+                                j--;
+                            }
+                        }
+                        else
+                        {
+                            next = refine_next[k][0];
+                            cand += next;
+                            i += next;
+                            next = refine_next[k][1];
+                            cand += lx * next;
+                            j += next;
+                        }
+                    }
+                    last_loc = new_loc;
+                }
+                mot[mbnum][comp+1].sad = dmin;
+                mot[mbnum][comp+1].x = (imin - i0) << 1;
+                mot[mbnum][comp+1].y = (jmin - j0) << 1;
+                best_cand[comp+1] = ncand;
+            }
+            /********************************************/
+        }
+    }
+    else
+#endif  /* NO_INTER4V */
+    {
+        mot[mbnum][1].sad = mot[mbnum][2].sad = mot[mbnum][3].sad = mot[mbnum][4].sad = (dmin + 2) >> 2;
+        mot[mbnum][1].x = mot[mbnum][2].x = mot[mbnum][3].x = mot[mbnum][4].x = mot[mbnum][0].x;
+        mot[mbnum][1].y = mot[mbnum][2].y = mot[mbnum][3].y = mot[mbnum][4].y = mot[mbnum][0].y;
+        best_cand[1] = best_cand[2] = best_cand[3] = best_cand[4] = ncand;
+
+    }
+    return ;
+}
+
+
+/*===============================================================================
+    Function:   fullsearch
+    Date:       09/16/2000
+    Purpose:    Perform full-search motion estimation over the range of search
+                region in a spiral-outward manner.
+    Input/Output:   VideoEncData, current Vol, previou Vop, pointer to the left corner of
+                current VOP, current coord (also output), boundaries.
+===============================================================================*/
+
+Int fullsearch(VideoEncData *video, Vol *currVol, UChar *prev, UChar *cur,
+               Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh)
+{
+    Int range = video->encParams->SearchRange;
+    UChar *cand;
+    Int i, j, k, l;
+    Int d, dmin;
+    Int i0 = *imin; /* current position */
+    Int j0 = *jmin;
+    Int(*SAD_Macroblock)(UChar*, UChar*, Int, void*) = video->functionPointer->SAD_Macroblock;
+    void *extra_info = video->sad_extra_info;
+//  UChar h263_mode = video->encParams->H263_Enabled;
+    Int lx = video->currVop->pitch; /* with padding */
+
+    Int offset = i0 + j0 * lx;
+
+    OSCL_UNUSED_ARG(currVol);
+
+    cand = prev + offset;
+
+    dmin  = (*SAD_Macroblock)(cand, cur, (65535 << 16) | lx, (void*)extra_info) - PREF_NULL_VEC;
+
+    /* perform spiral search */
+    for (k = 1; k <= range; k++)
+    {
+
+        i = i0 - k;
+        j = j0 - k;
+
+        cand = prev + i + j * lx;
+
+        for (l = 0; l < 8*k; l++)
+        {
+            /* no need for boundary checking again */
+            if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+            {
+                d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, (void*)extra_info);
+
+                if (d < dmin)
+                {
+                    dmin = d;
+                    *imin = i;
+                    *jmin = j;
+                }
+                else if ((d == dmin) && PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - *imin) + PV_ABS(j0 - *jmin))
+                {
+                    dmin = d;
+                    *imin = i;
+                    *jmin = j;
+                }
+            }
+
+            if (l < (k << 1))
+            {
+                i++;
+                cand++;
+            }
+            else if (l < (k << 2))
+            {
+                j++;
+                cand += lx;
+            }
+            else if (l < ((k << 2) + (k << 1)))
+            {
+                i--;
+                cand--;
+            }
+            else
+            {
+                j--;
+                cand -= lx;
+            }
+        }
+    }
+
+    return dmin;
+}
+
+#ifndef NO_INTER4V
+/*===============================================================================
+    Function:   fullsearchBlk
+    Date:       01/9/2001
+    Purpose:    Perform full-search motion estimation of an 8x8 block over the range
+                of search region in a spiral-outward manner centered at the 16x16 MV.
+    Input/Output:   VideoEncData, MB coordinate, pointer to the initial MV on the
+                reference, pointer to coor of current block, search range.
+===============================================================================*/
+Int fullsearchBlk(VideoEncData *video, Vol *currVol, UChar *cent, UChar *cur,
+                  Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh, Int range)
+{
+    UChar *cand, *ref;
+    Int i, j, k, l, istart, jstart;
+    Int d, dmin;
+    Int lx = video->currVop->pitch; /* with padding */
+    Int(*SAD_Block)(UChar*, UChar*, Int, Int, void*) = video->functionPointer->SAD_Block;
+    void *extra_info = video->sad_extra_info;
+
+    OSCL_UNUSED_ARG(currVol);
+
+    /* starting point centered at 16x16 MV */
+    ref = cent;
+    istart = *imin;
+    jstart = *jmin;
+
+    dmin = (*SAD_Block)(ref, cur, 65536, lx, (void*)extra_info);
+
+    cand = ref;
+    /* perform spiral search */
+    for (k = 1; k <= range; k++)
+    {
+
+        i = istart - k;
+        j = jstart - k;
+        cand -= (lx + 1);  /* candidate region */
+
+        for (l = 0; l < 8*k; l++)
+        {
+            /* no need for boundary checking again */
+            if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+            {
+                d = (*SAD_Block)(cand, cur, dmin, lx, (void*)extra_info);
+
+                if (d < dmin)
+                {
+                    dmin = d;
+                    *imin = i;
+                    *jmin = j;
+                }
+                else if ((d == dmin) &&
+                         PV_ABS(istart - i) + PV_ABS(jstart - j) < PV_ABS(istart - *imin) + PV_ABS(jstart - *jmin))
+                {
+                    dmin = d;
+                    *imin = i;
+                    *jmin = j;
+                }
+            }
+
+            if (l < (k << 1))
+            {
+                i++;
+                cand++;
+            }
+            else if (l < (k << 2))
+            {
+                j++;
+                cand += lx;
+            }
+            else if (l < ((k << 2) + (k << 1)))
+            {
+                i--;
+                cand--;
+            }
+            else
+            {
+                j--;
+                cand -= lx;
+            }
+        }
+    }
+
+    return dmin;
+}
+#endif /* NO_INTER4V */
+
+/*===============================================================================
+    Function:   CandidateSelection
+    Date:       09/16/2000
+    Purpose:    Fill up the list of candidate using spatio-temporal correlation
+                among neighboring blocks.
+    Input/Output:   type_pred = 0: first pass, 1: second pass, or no SCD
+    Modified:    09/23/01, get rid of redundant candidates before passing back.
+===============================================================================*/
+
+void CandidateSelection(Int *mvx, Int *mvy, Int *num_can, Int imb, Int jmb,
+                        VideoEncData *video, Int type_pred)
+{
+    MOT **mot = video->mot;
+    MOT *pmot;
+    Int mbnum = video->mbnum;
+    Vol *currVol = video->vol[video->currLayer];
+    Int mbwidth = currVol->nMBPerRow;
+    Int mbheight = currVol->nMBPerCol;
+    Int i, j, same, num1;
+
+    *num_can = 0;
+
+    if (video->forwardRefVop->predictionType == P_VOP)
+    {
+        /* Spatio-Temporal Candidate (five candidates) */
+        if (type_pred == 0) /* first pass */
+        {
+            pmot = &mot[mbnum][0]; /* same coordinate previous frame */
+            mvx[(*num_can)] = (pmot->x) >> 1;
+            mvy[(*num_can)++] = (pmot->y) >> 1;
+            if (imb >= (mbwidth >> 1) && imb > 0)  /*left neighbor previous frame */
+            {
+                pmot = &mot[mbnum-1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            else if (imb + 1 < mbwidth)   /*right neighbor previous frame */
+            {
+                pmot = &mot[mbnum+1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+
+            if (jmb < mbheight - 1)  /*bottom neighbor previous frame */
+            {
+                pmot = &mot[mbnum+mbwidth][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            else if (jmb > 0)   /*upper neighbor previous frame */
+            {
+                pmot = &mot[mbnum-mbwidth][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+
+            if (imb > 0 && jmb > 0)  /* upper-left neighbor current frame*/
+            {
+                pmot = &mot[mbnum-mbwidth-1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (jmb > 0 && imb < mbheight - 1)  /* upper right neighbor current frame*/
+            {
+                pmot = &mot[mbnum-mbwidth+1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+        }
+        else    /* second pass */
+            /* original ST1 algorithm */
+        {
+            pmot = &mot[mbnum][0]; /* same coordinate previous frame */
+            mvx[(*num_can)] = (pmot->x) >> 1;
+            mvy[(*num_can)++] = (pmot->y) >> 1;
+
+            if (imb > 0)  /*left neighbor current frame */
+            {
+                pmot = &mot[mbnum-1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (jmb > 0)  /*upper neighbor current frame */
+            {
+                pmot = &mot[mbnum-mbwidth][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (imb < mbwidth - 1)  /*right neighbor previous frame */
+            {
+                pmot = &mot[mbnum+1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (jmb < mbheight - 1)  /*bottom neighbor previous frame */
+            {
+                pmot = &mot[mbnum+mbwidth][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+        }
+    }
+    else  /* only Spatial Candidate (four candidates)*/
+    {
+        if (type_pred == 0) /*first pass*/
+        {
+            if (imb > 1)  /* neighbor two blocks away to the left */
+            {
+                pmot = &mot[mbnum-2][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (imb > 0 && jmb > 0)  /* upper-left neighbor */
+            {
+                pmot = &mot[mbnum-mbwidth-1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (jmb > 0 && imb < mbheight - 1)  /* upper right neighbor */
+            {
+                pmot = &mot[mbnum-mbwidth+1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+        }
+//#ifdef SCENE_CHANGE_DETECTION
+        /* second pass (ST2 algorithm)*/
+        else if (type_pred == 1) /* 4/7/01 */
+        {
+            if (imb > 0)  /*left neighbor current frame */
+            {
+                pmot = &mot[mbnum-1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (jmb > 0)  /*upper neighbor current frame */
+            {
+                pmot = &mot[mbnum-mbwidth][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (imb < mbwidth - 1)  /*right neighbor current frame */
+            {
+                pmot = &mot[mbnum+1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+            if (jmb < mbheight - 1)  /*bottom neighbor current frame */
+            {
+                pmot = &mot[mbnum+mbwidth][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+            }
+        }
+//#else
+        else /* original ST1 algorithm */
+        {
+            if (imb > 0)  /*left neighbor current frame */
+            {
+                pmot = &mot[mbnum-1][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+
+                if (jmb > 0)  /*upper-left neighbor current frame */
+                {
+                    pmot = &mot[mbnum-mbwidth-1][0];
+                    mvx[(*num_can)] = (pmot->x) >> 1;
+                    mvy[(*num_can)++] = (pmot->y) >> 1;
+                }
+
+            }
+            if (jmb > 0)  /*upper neighbor current frame */
+            {
+                pmot = &mot[mbnum-mbwidth][0];
+                mvx[(*num_can)] = (pmot->x) >> 1;
+                mvy[(*num_can)++] = (pmot->y) >> 1;
+
+                if (imb < mbheight - 1)  /*upper-right neighbor current frame */
+                {
+                    pmot = &mot[mbnum-mbwidth+1][0];
+                    mvx[(*num_can)] = (pmot->x) >> 1;
+                    mvy[(*num_can)++] = (pmot->y) >> 1;
+                }
+            }
+        }
+//#endif
+    }
+
+    /* 3/23/01, remove redundant candidate (possible k-mean) */
+    num1 = *num_can;
+    *num_can = 1;
+    for (i = 1; i < num1; i++)
+    {
+        same = 0;
+        j = 0;
+        while (!same && j < *num_can)
+        {
+#if (CANDIDATE_DISTANCE==0)
+            if (mvx[i] == mvx[j] && mvy[i] == mvy[j])
+#else
+            // modified k-mean, 3/24/01, shouldn't be greater than 3
+            if (PV_ABS(mvx[i] - mvx[j]) + PV_ABS(mvy[i] - mvy[j]) < CANDIDATE_DISTANCE)
+#endif
+                same = 1;
+            j++;
+        }
+        if (!same)
+        {
+            mvx[*num_can] = mvx[i];
+            mvy[*num_can] = mvy[i];
+            (*num_can)++;
+        }
+    }
+
+#ifdef _SAD_STAT
+    num_cand += (*num_can);
+#endif
+
+    if (num1 == 5 && *num_can == 1)
+        *num_can = ALL_CAND_EQUAL; /* all are equal */
+
+    return ;
+}
+
+/*===========================================================================
+    Function:   RasterIntraUpdate
+    Date:       2/26/01
+    Purpose:    To raster-scan assign INTRA-update .
+                N macroblocks are updated (also was programmable).
+===========================================================================*/
+void RasterIntraUpdate(UChar *intraArray, UChar *Mode, Int totalMB, Int numRefresh)
+{
+    Int indx, i;
+
+    /* find the last refresh MB */
+    indx = 0;
+    while (intraArray[indx] == 1 && indx < totalMB)
+        indx++;
+
+    /* add more  */
+    for (i = 0; i < numRefresh && indx < totalMB; i++)
+    {
+        Mode[indx] = MODE_INTRA;
+        intraArray[indx++] = 1;
+    }
+
+    /* if read the end of frame, reset and loop around */
+    if (indx >= totalMB - 1)
+    {
+        ResetIntraUpdate(intraArray, totalMB);
+        indx = 0;
+        while (i < numRefresh && indx < totalMB)
+        {
+            intraArray[indx] = 1;
+            Mode[indx++] = MODE_INTRA;
+            i++;
+        }
+    }
+
+    return ;
+}
+
+/*===========================================================================
+    Function:   ResetIntraUpdate
+    Date:       11/28/00
+    Purpose:    Reset already intra updated flags to all zero
+===========================================================================*/
+
+void ResetIntraUpdate(UChar *intraArray, Int totalMB)
+{
+    M4VENC_MEMSET(intraArray, 0, sizeof(UChar)*totalMB);
+    return ;
+}
+
+/*===========================================================================
+    Function:   ResetIntraUpdateRegion
+    Date:       12/1/00
+    Purpose:    Reset already intra updated flags in one region to all zero
+===========================================================================*/
+void ResetIntraUpdateRegion(UChar *intraArray, Int start_i, Int rwidth,
+                            Int start_j, Int rheight, Int mbwidth, Int mbheight)
+{
+    Int indx, j;
+
+    if (start_i + rwidth >= mbwidth)
+        rwidth = mbwidth - start_i;
+    if (start_j + rheight >= mbheight)
+        rheight = mbheight - start_j;
+
+    for (j = start_j; j < start_j + rheight; j++)
+    {
+        indx = j * mbwidth;
+        M4VENC_MEMSET(intraArray + indx + start_i, 0, sizeof(UChar)*rwidth);
+    }
+
+    return ;
+}
+
+/*************************************************************
+    Function:   MoveNeighborSAD
+    Date:       3/27/01
+    Purpose:    Move neighboring SAD around when center has shifted
+*************************************************************/
+
+void MoveNeighborSAD(Int dn[], Int new_loc)
+{
+    Int tmp[9];
+    tmp[0] = dn[0];
+    tmp[1] = dn[1];
+    tmp[2] = dn[2];
+    tmp[3] = dn[3];
+    tmp[4] = dn[4];
+    tmp[5] = dn[5];
+    tmp[6] = dn[6];
+    tmp[7] = dn[7];
+    tmp[8] = dn[8];
+    dn[0] = dn[1] = dn[2] = dn[3] = dn[4] = dn[5] = dn[6] = dn[7] = dn[8] = 65536;
+
+    switch (new_loc)
+    {
+        case 0:
+            break;
+        case 1:
+            dn[4] = tmp[2];
+            dn[5] = tmp[0];
+            dn[6] = tmp[8];
+            break;
+        case 2:
+            dn[4] = tmp[3];
+            dn[5] = tmp[4];
+            dn[6] = tmp[0];
+            dn[7] = tmp[8];
+            dn[8] = tmp[1];
+            break;
+        case 3:
+            dn[6] = tmp[4];
+            dn[7] = tmp[0];
+            dn[8] = tmp[2];
+            break;
+        case 4:
+            dn[1] = tmp[2];
+            dn[2] = tmp[3];
+            dn[6] = tmp[5];
+            dn[7] = tmp[6];
+            dn[8] = tmp[0];
+            break;
+        case 5:
+            dn[1] = tmp[0];
+            dn[2] = tmp[4];
+            dn[8] = tmp[6];
+            break;
+        case 6:
+            dn[1] = tmp[8];
+            dn[2] = tmp[0];
+            dn[3] = tmp[4];
+            dn[4] = tmp[5];
+            dn[8] = tmp[7];
+            break;
+        case 7:
+            dn[2] = tmp[8];
+            dn[3] = tmp[0];
+            dn[4] = tmp[6];
+            break;
+        case 8:
+            dn[2] = tmp[1];
+            dn[3] = tmp[2];
+            dn[4] = tmp[0];
+            dn[5] = tmp[6];
+            dn[6] = tmp[7];
+            break;
+    }
+    dn[0] = tmp[new_loc];
+
+    return ;
+}
+
+/* 3/28/01, find minimal of dn[9] */
+
+Int FindMin(Int dn[])
+{
+    Int min, i;
+    Int dmin;
+
+    dmin = dn[1];
+    min = 1;
+    for (i = 2; i < 9; i++)
+    {
+        if (dn[i] < dmin)
+        {
+            dmin = dn[i];
+            min = i;
+        }
+    }
+
+    return min;
+}
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h b/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h
new file mode 100644
index 0000000..0d5a3e8
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h
@@ -0,0 +1,229 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _PVDECDEF_H_
+#define _PVDECDEF_H_
+
+#include <stdint.h> // for uint8_t, etc
+#include <stdlib.h>
+#include <string.h>
+
+// Redefine the int types
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef int16_t int16;
+typedef uint32_t uint32;
+typedef int32_t int32;
+typedef unsigned int uint;
+
+/********** platform dependent in-line assembly *****************************/
+
+/*************** Intel *****************/
+
+/*************** ARM *****************/
+/* for general ARM instruction. #define __ARM has to be defined in compiler set up.*/
+/* for DSP MUL */
+#ifdef __TARGET_FEATURE_DSPMUL
+#define _ARM_DSP_MUL
+#endif
+
+/* for Count Leading Zero instruction */
+#ifdef __TARGET_ARCH_5T
+#define _ARM_CLZ
+#endif
+#ifdef __TARGET_ARCH_5TE
+#define _ARM_CLZ
+#endif
+/****************************************************************************/
+
+#ifndef _PV_TYPES_
+#define _PV_TYPES_
+typedef unsigned char UChar;
+typedef char Char;
+typedef unsigned int UInt;
+typedef int Int;
+typedef unsigned short UShort;
+typedef short Short;
+typedef short int SInt;
+typedef unsigned int Bool;
+typedef unsigned long   ULong;
+typedef void Void;
+
+#define PV_CODEC_INIT       0
+#define PV_CODEC_STOP       1
+#define PV_CODEC_RUNNING    2
+#define PV_CODEC_RESET      3
+#endif
+
+typedef enum
+{
+    PV_SUCCESS,
+    PV_FAIL,
+    PV_EOS,             /* hit End_Of_Sequence     */
+    PV_MB_STUFFING,     /* hit Macroblock_Stuffing */
+    PV_END_OF_VOP,      /* hit End_of_Video_Object_Plane */
+    PV_END_OF_MB,       /* hit End_of_Macroblock */
+    PV_END_OF_BUF       /* hit End_of_Bitstream_Buffer */
+} PV_STATUS;
+
+typedef UChar PIXEL;
+//typedef Int MOT;   /* : "int" type runs faster on RISC machine */
+
+#define HTFM            /*  3/2/01, Hypothesis Test Fast Matching for early drop-out*/
+//#define _MOVE_INTERFACE
+
+//#define RANDOM_REFSELCODE
+
+/* handle the case of devision by zero in RC */
+#define MAD_MIN 1
+
+/* 4/11/01, if SSE or MMX, no HTFM, no SAD_HP_FLY */
+
+/* Code size reduction related Macros */
+#ifdef H263_ONLY
+#ifndef NO_RVLC
+#define NO_RVLC
+#endif
+#ifndef NO_MPEG_QUANT
+#define NO_MPEG_QUANT
+#endif
+#ifndef NO_INTER4V
+#define NO_INTER4V
+#endif
+#endif
+/**************************************/
+
+#define TRUE    1
+#define FALSE   0
+
+#define PV_ABS(x)       (((x)<0)? -(x) : (x))
+#define PV_SIGN(x)      (((x)<0)? -1 : 1)
+#define PV_SIGN0(a)     (((a)<0)? -1 : (((a)>0) ? 1 : 0))
+#define PV_MAX(a,b)     ((a)>(b)? (a):(b))
+#define PV_MIN(a,b)     ((a)<(b)? (a):(b))
+
+#define MODE_INTRA      0
+#define MODE_INTER      1
+#define MODE_INTRA_Q    2
+#define MODE_INTER_Q    3
+#define MODE_INTER4V    4
+#define MODE_SKIPPED    6
+
+#define I_VOP       0
+#define P_VOP       1
+#define B_VOP       2
+
+/*09/04/00 Add MB height and width */
+#define MB_WIDTH 16
+#define MB_HEIGHT 16
+
+#define VOP_BRIGHT_WHITEENC 255
+
+
+#define LUMINANCE_DC_TYPE   1
+#define CHROMINANCE_DC_TYPE 2
+
+#define EOB_CODE                        1
+#define EOB_CODE_LENGTH                32
+
+/* 11/30/98 */
+#define FoundRM     1   /* Resync Marker */
+#define FoundVSC    2   /* VOP_START_CODE. */
+#define FoundGSC    3   /* GROUP_START_CODE */
+#define FoundEOB    4   /* EOB_CODE */
+
+
+/* 05/08/2000, the error code returned from BitstreamShowBits() */
+#define BITSTREAM_ERROR_CODE 0xFFFFFFFF
+
+/* PacketVideo "absolution timestamp" object.  06/13/2000 */
+#define PVTS_START_CODE         0x01C4
+#define PVTS_START_CODE_LENGTH  32
+
+/* session layer and vop layer start codes */
+
+#define SESSION_START_CODE  0x01B0
+#define SESSION_END_CODE    0x01B1
+#define VISUAL_OBJECT_START_CODE 0x01B5
+
+#define VO_START_CODE           0x8
+#define VO_HEADER_LENGTH        32      /* lengtho of VO header: VO_START_CODE +  VO_ID */
+
+#define SOL_START_CODE          0x01BE
+#define SOL_START_CODE_LENGTH   32
+
+#define VOL_START_CODE 0x12
+#define VOL_START_CODE_LENGTH 28
+
+#define VOP_START_CODE 0x1B6
+#define VOP_START_CODE_LENGTH   32
+
+#define GROUP_START_CODE    0x01B3
+#define GROUP_START_CODE_LENGTH  32
+
+#define VOP_ID_CODE_LENGTH      5
+#define VOP_TEMP_REF_CODE_LENGTH    16
+
+#define USER_DATA_START_CODE        0x01B2
+#define USER_DATA_START_CODE_LENGTH 32
+
+#define START_CODE_PREFIX       0x01
+#define START_CODE_PREFIX_LENGTH    24
+
+#define SHORT_VIDEO_START_MARKER         0x20
+#define SHORT_VIDEO_START_MARKER_LENGTH  22
+#define SHORT_VIDEO_END_MARKER            0x3F
+#define GOB_RESYNC_MARKER         0x01
+#define GOB_RESYNC_MARKER_LENGTH  17
+
+/* motion and resync markers used in error resilient mode  */
+
+#define DC_MARKER                      438273
+#define DC_MARKER_LENGTH                19
+
+#define MOTION_MARKER_COMB             126977
+#define MOTION_MARKER_COMB_LENGTH       17
+
+#define MOTION_MARKER_SEP              81921
+#define MOTION_MARKER_SEP_LENGTH        17
+
+#define RESYNC_MARKER           1
+#define RESYNC_MARKER_LENGTH    17
+
+#define SPRITE_NOT_USED     0
+#define STATIC_SPRITE       1
+#define ONLINE_SPRITE       2
+#define GMC_SPRITE      3
+
+/* macroblock and block size */
+#define MB_SIZE 16
+#define NCOEFF_MB (MB_SIZE*MB_SIZE)
+#define B_SIZE 8
+#define NCOEFF_BLOCK (B_SIZE*B_SIZE)
+#define NCOEFF_Y NCOEFF_MB
+#define NCOEFF_U NCOEFF_BLOCK
+#define NCOEFF_V NCOEFF_BLOCK
+
+/* overrun buffer size  */
+#define DEFAULT_OVERRUN_BUFFER_SIZE 1000
+
+
+/* VLC decoding related definitions */
+#define VLC_ERROR   (-1)
+#define VLC_ESCAPE  7167
+
+#endif /* _PVDECDEF_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
new file mode 100644
index 0000000..946e3d0
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -0,0 +1,3278 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+
+#include "mp4enc_lib.h"
+#include "bitstream_io.h"
+#include "rate_control.h"
+#include "m4venc_oscl.h"
+
+
+/* Inverse normal zigzag */
+const static Int zigzag_i[NCOEFF_BLOCK] =
+{
+    0, 1, 8, 16, 9, 2, 3, 10,
+    17, 24, 32, 25, 18, 11, 4, 5,
+    12, 19, 26, 33, 40, 48, 41, 34,
+    27, 20, 13, 6, 7, 14, 21, 28,
+    35, 42, 49, 56, 57, 50, 43, 36,
+    29, 22, 15, 23, 30, 37, 44, 51,
+    58, 59, 52, 45, 38, 31, 39, 46,
+    53, 60, 61, 54, 47, 55, 62, 63
+};
+
+/* INTRA */
+const static Int mpeg_iqmat_def[NCOEFF_BLOCK] =
+    {  8, 17, 18, 19, 21, 23, 25, 27,
+       17, 18, 19, 21, 23, 25, 27, 28,
+       20, 21, 22, 23, 24, 26, 28, 30,
+       21, 22, 23, 24, 26, 28, 30, 32,
+       22, 23, 24, 26, 28, 30, 32, 35,
+       23, 24, 26, 28, 30, 32, 35, 38,
+       25, 26, 28, 30, 32, 35, 38, 41,
+       27, 28, 30, 32, 35, 38, 41, 45
+    };
+
+/* INTER */
+const static Int mpeg_nqmat_def[64]  =
+    { 16, 17, 18, 19, 20, 21, 22, 23,
+      17, 18, 19, 20, 21, 22, 23, 24,
+      18, 19, 20, 21, 22, 23, 24, 25,
+      19, 20, 21, 22, 23, 24, 26, 27,
+      20, 21, 22, 23, 25, 26, 27, 28,
+      21, 22, 23, 24, 26, 27, 28, 30,
+      22, 23, 24, 26, 27, 28, 30, 31,
+      23, 24, 25, 27, 28, 30, 31, 33
+    };
+
+/* Profiles and levels */
+/* Simple profile(level 0-3) and Core profile (level 1-2) */
+/* {SPL0, SPL1, SPL2, SPL3, CPL1, CPL2, CPL2, CPL2} , SPL0: Simple Profile@Level0, CPL1: Core Profile@Level1, the last two are redundant for easy table manipulation */
+const static Int profile_level_code[8] =
+{
+    0x08, 0x01, 0x02, 0x03, 0x21, 0x22, 0x22, 0x22
+};
+
+const static Int profile_level_max_bitrate[8] =
+{
+    64000, 64000, 128000, 384000, 384000, 2000000, 2000000, 2000000
+};
+
+const static Int profile_level_max_packet_size[8] =
+{
+    2048, 2048, 4096, 8192, 4096, 8192, 8192, 8192
+};
+
+const static Int profile_level_max_mbsPerSec[8] =
+{
+    1485, 1485, 5940, 11880, 5940, 23760, 23760, 23760
+};
+
+const static Int profile_level_max_VBV_size[8] =
+{
+    163840, 163840, 655360, 655360, 262144, 1310720, 1310720, 1310720
+};
+
+
+/* Simple scalable profile (level 0-2) and Core scalable profile (level 1-3) */
+/* {SSPL0, SSPL1, SSPL2, SSPL2, CSPL1, CSPL2, CSPL3, CSPL3} , SSPL0: Simple Scalable Profile@Level0, CSPL1: Core Scalable Profile@Level1, the fourth is redundant for easy table manipulation */
+
+const static Int scalable_profile_level_code[8] =
+{
+    0x10, 0x11, 0x12, 0x12, 0xA1, 0xA2, 0xA3, 0xA3
+};
+
+const static Int scalable_profile_level_max_bitrate[8] =
+{
+    128000, 128000, 256000, 256000, 768000, 1500000, 4000000, 4000000
+};
+
+/* in bits */
+const static Int scalable_profile_level_max_packet_size[8] =
+{
+    2048, 2048, 4096, 4096, 4096, 4096, 16384, 16384
+};
+
+const static Int scalable_profile_level_max_mbsPerSec[8] =
+{
+    1485, 7425, 23760, 23760, 14850, 29700, 120960, 120960
+};
+
+const static Int scalable_profile_level_max_VBV_size[8] =
+{
+    163840, 655360, 655360, 655360, 1048576, 1310720, 1310720, 1310720
+};
+
+
+/* H263 profile 0 @ level 10-70 */
+const static Int   h263Level[8] = {0, 10, 20, 30, 40, 50, 60, 70};
+const static float rBR_bound[8] = {0, 1, 2, 6, 32, 64, 128, 256};
+const static float max_h263_framerate[2] = {(float)30000 / (float)2002,
+        (float)30000 / (float)1001
+                                           };
+const static Int   max_h263_width[2]  = {176, 352};
+const static Int   max_h263_height[2] = {144, 288};
+
+/* 6/2/2001, newly added functions to make PVEncodeVop more readable. */
+Int DetermineCodingLayer(VideoEncData *video, Int *nLayer, ULong modTime);
+void DetermineVopType(VideoEncData *video, Int currLayer);
+Int UpdateSkipNextFrame(VideoEncData *video, ULong *modTime, Int *size, PV_STATUS status);
+Bool SetProfile_BufferSize(VideoEncData *video, float delay, Int bInitialized);
+
+#ifdef PRINT_RC_INFO
+extern FILE *facct;
+extern int tiTotalNumBitsGenerated;
+extern int iStuffBits;
+#endif
+
+#ifdef PRINT_EC
+extern FILE *fec;
+#endif
+
+
+/* ======================================================================== */
+/*  Function : PVGetDefaultEncOption()                                      */
+/*  Date     : 12/12/2005                                                   */
+/*  Purpose  :                                                              */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetDefaultEncOption(VideoEncOptions *encOption, Int encUseCase)
+{
+    VideoEncOptions defaultUseCase = {H263_MODE, profile_level_max_packet_size[SIMPLE_PROFILE_LEVEL0] >> 3,
+                                      SIMPLE_PROFILE_LEVEL0, PV_OFF, 0, 1, 1000, 33, {144, 144}, {176, 176}, {15, 30}, {64000, 128000},
+                                      {10, 10}, {12, 12}, {0, 0}, CBR_1, 0.0, PV_OFF, -1, 0, PV_OFF, 16, PV_OFF, 0, PV_ON
+                                     };
+
+    OSCL_UNUSED_ARG(encUseCase); // unused for now. Later we can add more defaults setting and use this
+    // argument to select the right one.
+    /* in the future we can create more meaningful use-cases */
+    if (encOption == NULL)
+    {
+        return PV_FALSE;
+    }
+
+    M4VENC_MEMCPY(encOption, &defaultUseCase, sizeof(VideoEncOptions));
+
+    return PV_TRUE;
+}
+
+/* ======================================================================== */
+/*  Function : PVInitVideoEncoder()                                         */
+/*  Date     : 08/22/2000                                                   */
+/*  Purpose  : Initialization of MP4 Encoder and VO bitstream               */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :  5/21/01, allocate only yChan and assign uChan & vChan   */
+/*              12/12/05, add encoding option as input argument         */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool    PVInitVideoEncoder(VideoEncControls *encoderControl, VideoEncOptions *encOption)
+{
+
+    Bool        status = PV_TRUE;
+    Int         nLayers, idx, i, j;
+    Int         max = 0, max_width = 0, max_height = 0, pitch, offset;
+    Int         size = 0, nTotalMB = 0;
+    VideoEncData *video;
+    Vol         *pVol;
+    VideoEncParams  *pEncParams;
+    Int         temp_w, temp_h, mbsPerSec;
+
+    /******************************************/
+    /*      this part use to be PVSetEncode() */
+    Int profile_table_index, *profile_level_table;
+    Int profile_level = encOption->profile_level;
+    Int PacketSize = encOption->packetSize << 3;
+    Int timeInc, timeIncRes;
+    float profile_max_framerate;
+    VideoEncParams *encParams;
+
+    if (encoderControl->videoEncoderData) /* this has been called */
+    {
+        if (encoderControl->videoEncoderInit) /* check if PVInitVideoEncoder() has been called  */
+        {
+            PVCleanUpVideoEncoder(encoderControl);
+            encoderControl->videoEncoderInit = 0;
+        }
+
+        M4VENC_FREE(encoderControl->videoEncoderData);
+        encoderControl->videoEncoderData = NULL;
+    }
+    encoderControl->videoEncoderInit = 0;   /* reset this value */
+
+    video = (VideoEncData *)M4VENC_MALLOC(sizeof(VideoEncData)); /* allocate memory for encData */
+
+    if (video == NULL)
+        return PV_FALSE;
+
+    M4VENC_MEMSET(video, 0, sizeof(VideoEncData));
+
+    encoderControl->videoEncoderData = (void *) video;         /* set up pointer in VideoEncData structure */
+
+    video->encParams = (VideoEncParams *)M4VENC_MALLOC(sizeof(VideoEncParams));
+    if (video->encParams == NULL)
+        goto CLEAN_UP;
+
+    M4VENC_MEMSET(video->encParams, 0, sizeof(VideoEncParams));
+
+    encParams = video->encParams;
+    encParams->nLayers = encOption->numLayers;
+
+    /* Check whether the input packetsize is valid (Note: put code here (before any memory allocation) in order to avoid memory leak */
+    if ((Int)profile_level < (Int)(SIMPLE_SCALABLE_PROFILE_LEVEL0))  /* non-scalable profile */
+    {
+        profile_level_table = (Int *)profile_level_max_packet_size;
+        profile_table_index = (Int)profile_level;
+        if (encParams->nLayers != 1)
+        {
+            goto CLEAN_UP;
+        }
+
+        encParams->LayerMaxMbsPerSec[0] = profile_level_max_mbsPerSec[profile_table_index];
+
+    }
+    else   /* scalable profile */
+    {
+        profile_level_table = (Int *)scalable_profile_level_max_packet_size;
+        profile_table_index = (Int)profile_level - (Int)(SIMPLE_SCALABLE_PROFILE_LEVEL0);
+        if (encParams->nLayers < 2)
+        {
+            goto CLEAN_UP;
+        }
+        for (i = 0; i < encParams->nLayers; i++)
+        {
+            encParams->LayerMaxMbsPerSec[i] = scalable_profile_level_max_mbsPerSec[profile_table_index];
+        }
+
+    }
+
+    /* cannot have zero size packet with these modes */
+    if (PacketSize == 0)
+    {
+        if (encOption->encMode == DATA_PARTITIONING_MODE)
+        {
+            goto CLEAN_UP;
+        }
+        if (encOption->encMode == COMBINE_MODE_WITH_ERR_RES)
+        {
+            encOption->encMode = COMBINE_MODE_NO_ERR_RES;
+        }
+    }
+
+    if (encOption->gobHeaderInterval == 0)
+    {
+        if (encOption->encMode == H263_MODE_WITH_ERR_RES)
+        {
+            encOption->encMode = H263_MODE;
+        }
+
+        if (encOption->encMode == SHORT_HEADER_WITH_ERR_RES)
+        {
+            encOption->encMode = SHORT_HEADER;
+        }
+    }
+
+    if (PacketSize > profile_level_table[profile_table_index])
+        goto CLEAN_UP;
+
+    /* Initial Defaults for all Modes */
+
+    encParams->SequenceStartCode = 1;
+    encParams->GOV_Enabled = 0;
+    encParams->RoundingType = 0;
+    encParams->IntraDCVlcThr = PV_MAX(PV_MIN(encOption->intraDCVlcTh, 7), 0);
+    encParams->ACDCPrediction = ((encOption->useACPred == PV_ON) ? TRUE : FALSE);
+    encParams->RC_Type = encOption->rcType;
+    encParams->Refresh = encOption->numIntraMB;
+    encParams->ResyncMarkerDisable = 0; /* Enable Resync Marker */
+
+    for (i = 0; i < encOption->numLayers; i++)
+    {
+#ifdef NO_MPEG_QUANT
+        encParams->QuantType[i] = 0;
+#else
+        encParams->QuantType[i] = encOption->quantType[i];      /* H263 */
+#endif
+        if (encOption->pQuant[i] >= 1 && encOption->pQuant[i] <= 31)
+        {
+            encParams->InitQuantPvop[i] = encOption->pQuant[i];
+        }
+        else
+        {
+            goto CLEAN_UP;
+        }
+        if (encOption->iQuant[i] >= 1 && encOption->iQuant[i] <= 31)
+        {
+            encParams->InitQuantIvop[i] = encOption->iQuant[i];
+        }
+        else
+        {
+            goto CLEAN_UP;
+        }
+    }
+
+    encParams->HalfPel_Enabled = 1;
+    encParams->SearchRange = encOption->searchRange; /* 4/16/2001 */
+    encParams->FullSearch_Enabled = 0;
+#ifdef NO_INTER4V
+    encParams->MV8x8_Enabled = 0;
+#else
+    encParams->MV8x8_Enabled = 0;// comment out for now!! encOption->mv8x8Enable;
+#endif
+    encParams->H263_Enabled = 0;
+    encParams->GOB_Header_Interval = 0; // need to be reset to 0
+    encParams->IntraPeriod = encOption->intraPeriod;    /* Intra update period update default*/
+    encParams->SceneChange_Det = encOption->sceneDetect;
+    encParams->FineFrameSkip_Enabled = 0;
+    encParams->NoFrameSkip_Enabled = encOption->noFrameSkipped;
+    encParams->NoPreSkip_Enabled = encOption->noFrameSkipped;
+    encParams->GetVolHeader[0] = 0;
+    encParams->GetVolHeader[1] = 0;
+    encParams->ResyncPacketsize = encOption->packetSize << 3;
+    encParams->LayerMaxBitRate[0] = 0;
+    encParams->LayerMaxBitRate[1] = 0;
+    encParams->LayerMaxFrameRate[0] = (float)0.0;
+    encParams->LayerMaxFrameRate[1] = (float)0.0;
+    encParams->VBV_delay = encOption->vbvDelay;  /* 2sec VBV buffer size */
+
+    switch (encOption->encMode)
+    {
+
+        case SHORT_HEADER:
+        case SHORT_HEADER_WITH_ERR_RES:
+
+            /* From Table 6-26 */
+            encParams->nLayers = 1;
+            encParams->QuantType[0] = 0;    /*H263 */
+            encParams->ResyncMarkerDisable = 1; /* Disable Resync Marker */
+            encParams->DataPartitioning = 0; /* Combined Mode */
+            encParams->ReversibleVLC = 0;   /* Disable RVLC */
+            encParams->RoundingType = 0;
+            encParams->IntraDCVlcThr = 7;   /* use_intra_dc_vlc = 0 */
+            encParams->MV8x8_Enabled = 0;
+
+            encParams->GOB_Header_Interval = encOption->gobHeaderInterval;
+            encParams->H263_Enabled = 2;
+            encParams->GOV_Enabled = 0;
+            encParams->TimeIncrementRes = 30000;        /* timeIncrementRes for H263 */
+            break;
+
+        case H263_MODE:
+        case H263_MODE_WITH_ERR_RES:
+
+            /* From Table 6-26 */
+            encParams->nLayers = 1;
+            encParams->QuantType[0] = 0;    /*H263 */
+            encParams->ResyncMarkerDisable = 1; /* Disable Resync Marker */
+            encParams->DataPartitioning = 0; /* Combined Mode */
+            encParams->ReversibleVLC = 0;   /* Disable RVLC */
+            encParams->RoundingType = 0;
+            encParams->IntraDCVlcThr = 7;   /* use_intra_dc_vlc = 0 */
+            encParams->MV8x8_Enabled = 0;
+
+            encParams->H263_Enabled = 1;
+            encParams->GOV_Enabled = 0;
+            encParams->TimeIncrementRes = 30000;        /* timeIncrementRes for H263 */
+
+            break;
+#ifndef H263_ONLY
+        case DATA_PARTITIONING_MODE:
+
+            encParams->DataPartitioning = 1;        /* Base Layer Data Partitioning */
+            encParams->ResyncMarkerDisable = 0; /* Resync Marker */
+#ifdef NO_RVLC
+            encParams->ReversibleVLC = 0;
+#else
+            encParams->ReversibleVLC = (encOption->rvlcEnable == PV_ON); /* RVLC when Data Partitioning */
+#endif
+            encParams->ResyncPacketsize = PacketSize;
+            break;
+
+        case COMBINE_MODE_WITH_ERR_RES:
+
+            encParams->DataPartitioning = 0;        /* Combined Mode */
+            encParams->ResyncMarkerDisable = 0; /* Resync Marker */
+            encParams->ReversibleVLC = 0;           /* No RVLC */
+            encParams->ResyncPacketsize = PacketSize;
+            break;
+
+        case COMBINE_MODE_NO_ERR_RES:
+
+            encParams->DataPartitioning = 0;        /* Combined Mode */
+            encParams->ResyncMarkerDisable = 1; /* Disable Resync Marker */
+            encParams->ReversibleVLC = 0;           /* No RVLC */
+            break;
+#endif
+        default:
+            goto CLEAN_UP;
+    }
+    /* Set the constraints (maximum values) according to the input profile and level */
+    /* Note that profile_table_index is already figured out above */
+
+    /* base layer */
+    encParams->profile_table_index    = profile_table_index; /* Used to limit the profile and level in SetProfile_BufferSize() */
+
+    /* check timeIncRes */
+    timeIncRes = encOption->timeIncRes;
+    timeInc = encOption->tickPerSrc;
+
+    if ((timeIncRes >= 1) && (timeIncRes <= 65536) && (timeInc < timeIncRes) && (timeInc != 0))
+    {
+        if (!encParams->H263_Enabled)
+        {
+            encParams->TimeIncrementRes = timeIncRes;
+        }
+        else
+        {
+            encParams->TimeIncrementRes = 30000;
+//          video->FrameRate = 30000/(float)1001; /* fix it to 29.97 fps */
+        }
+        video->FrameRate = timeIncRes / ((float)timeInc);
+    }
+    else
+    {
+        goto CLEAN_UP;
+    }
+
+    /* check frame dimension */
+    if (encParams->H263_Enabled)
+    {
+        switch (encOption->encWidth[0])
+        {
+            case 128:
+                if (encOption->encHeight[0] != 96) /* source_format = 1 */
+                    goto CLEAN_UP;
+                break;
+            case 176:
+                if (encOption->encHeight[0] != 144) /* source_format = 2 */
+                    goto CLEAN_UP;
+                break;
+            case 352:
+                if (encOption->encHeight[0] != 288) /* source_format = 2 */
+                    goto CLEAN_UP;
+                break;
+
+            case 704:
+                if (encOption->encHeight[0] != 576) /* source_format = 2 */
+                    goto CLEAN_UP;
+                break;
+            case 1408:
+                if (encOption->encHeight[0] != 1152) /* source_format = 2 */
+                    goto CLEAN_UP;
+                break;
+
+            default:
+                goto CLEAN_UP;
+        }
+    }
+    for (i = 0; i < encParams->nLayers; i++)
+    {
+        encParams->LayerHeight[i] = encOption->encHeight[i];
+        encParams->LayerWidth[i] = encOption->encWidth[i];
+    }
+
+    /* check frame rate */
+    for (i = 0; i < encParams->nLayers; i++)
+    {
+        encParams->LayerFrameRate[i] = encOption->encFrameRate[i];
+    }
+
+    if (encParams->nLayers > 1)
+    {
+        if (encOption->encFrameRate[0] == encOption->encFrameRate[1] ||
+                encOption->encFrameRate[0] == 0. || encOption->encFrameRate[1] == 0.) /* 7/31/03 */
+            goto CLEAN_UP;
+    }
+    /* set max frame rate */
+    for (i = 0; i < encParams->nLayers; i++)
+    {
+
+        /* Make sure the maximum framerate is consistent with the given profile and level */
+        nTotalMB = ((encParams->LayerWidth[i] + 15) / 16) * ((encParams->LayerHeight[i] + 15) / 16);
+
+        if (nTotalMB > 0)
+            profile_max_framerate = (float)encParams->LayerMaxMbsPerSec[i] / (float)nTotalMB;
+
+        else
+            profile_max_framerate = (float)30.0;
+
+        encParams->LayerMaxFrameRate[i] = PV_MIN(profile_max_framerate, encParams->LayerFrameRate[i]);
+    }
+
+    /* check bit rate */
+    /* set max bit rate */
+    for (i = 0; i < encParams->nLayers; i++)
+    {
+        encParams->LayerBitRate[i] = encOption->bitRate[i];
+        encParams->LayerMaxBitRate[i] = encOption->bitRate[i];
+    }
+    if (encParams->nLayers > 1)
+    {
+        if (encOption->bitRate[0] == encOption->bitRate[1] ||
+                encOption->bitRate[0] == 0 || encOption->bitRate[1] == 0) /* 7/31/03 */
+            goto CLEAN_UP;
+    }
+    /* check rate control and vbv delay*/
+    encParams->RC_Type = encOption->rcType;
+
+    if (encOption->vbvDelay == 0.0) /* set to default */
+    {
+        switch (encOption->rcType)
+        {
+            case CBR_1:
+            case CBR_2:
+                encParams->VBV_delay = (float)2.0; /* default 2sec VBV buffer size */
+                break;
+
+            case CBR_LOWDELAY:
+                encParams->VBV_delay = (float)0.5; /* default 0.5sec VBV buffer size */
+                break;
+
+            case VBR_1:
+            case VBR_2:
+                encParams->VBV_delay = (float)10.0; /* default 10sec VBV buffer size */
+                break;
+            default:
+                break;
+        }
+    }
+    else /* force this value */
+    {
+        encParams->VBV_delay = encOption->vbvDelay;
+    }
+
+    /* check search range */
+    if (encParams->H263_Enabled && encOption->searchRange > 16)
+    {
+        encParams->SearchRange = 16; /* 4/16/2001 */
+    }
+
+    /*****************************************/
+    /* checking for conflict between options */
+    /*****************************************/
+
+    if (video->encParams->RC_Type == CBR_1 || video->encParams->RC_Type == CBR_2 || video->encParams->RC_Type == CBR_LOWDELAY)  /* if CBR */
+    {
+#ifdef _PRINT_STAT
+        if (video->encParams->NoFrameSkip_Enabled == PV_ON ||
+                video->encParams->NoPreSkip_Enabled == PV_ON) /* don't allow frame skip*/
+            printf("WARNING!!!! CBR with NoFrameSkip\n");
+#endif
+    }
+    else if (video->encParams->RC_Type == CONSTANT_Q)   /* constant_Q */
+    {
+        video->encParams->NoFrameSkip_Enabled = PV_ON;  /* no frame skip */
+        video->encParams->NoPreSkip_Enabled = PV_ON;    /* no frame skip */
+#ifdef _PRINT_STAT
+        printf("Turn on NoFrameSkip\n");
+#endif
+    }
+
+    if (video->encParams->NoFrameSkip_Enabled == PV_ON) /* if no frame skip */
+    {
+        video->encParams->FineFrameSkip_Enabled = PV_OFF;
+#ifdef _PRINT_STAT
+        printf("NoFrameSkip !!! may violate VBV_BUFFER constraint.\n");
+        printf("Turn off FineFrameSkip\n");
+#endif
+    }
+
+    /******************************************/
+    /******************************************/
+
+    nLayers = video->encParams->nLayers; /* Number of Layers to be encoded */
+
+    /* Find the maximum width*height for memory allocation of the VOPs */
+    for (idx = 0; idx < nLayers; idx++)
+    {
+        temp_w = video->encParams->LayerWidth[idx];
+        temp_h = video->encParams->LayerHeight[idx];
+
+        if ((temp_w*temp_h) > max)
+        {
+            max = temp_w * temp_h;
+            max_width = ((temp_w + 15) >> 4) << 4;
+            max_height = ((temp_h + 15) >> 4) << 4;
+            nTotalMB = ((max_width * max_height) >> 8);
+        }
+
+        /* Check if the video size and framerate(MBsPerSec) are vald */
+        mbsPerSec = (Int)(nTotalMB * video->encParams->LayerFrameRate[idx]);
+        if (mbsPerSec > video->encParams->LayerMaxMbsPerSec[idx]) status = PV_FALSE;
+    }
+
+    /****************************************************/
+    /* Set Profile and Video Buffer Size for each layer */
+    /****************************************************/
+    if (video->encParams->RC_Type == CBR_LOWDELAY) video->encParams->VBV_delay = 0.5; /* For CBR_LOWDELAY, we set 0.5sec buffer */
+    status = SetProfile_BufferSize(video, video->encParams->VBV_delay, 1);
+    if (status != PV_TRUE)
+        goto CLEAN_UP;
+
+    /****************************************/
+    /* memory allocation and initialization */
+    /****************************************/
+
+    if (video == NULL) goto CLEAN_UP;
+
+    /* cyclic reference for passing through both structures */
+    video->videoEncControls = encoderControl;
+
+    //video->currLayer = 0; /* Set current Layer to 0 */
+    //video->currFrameNo = 0; /* Set current frame Number to 0 */
+    video->nextModTime = 0;
+    video->nextEncIVop = 0; /* Sets up very first frame to be I-VOP! */
+    video->numVopsInGOP = 0; /* counter for Vops in Gop, 2/8/01 */
+
+    //video->frameRate = video->encParams->LayerFrameRate[0]; /* Set current layer frame rate */
+
+    video->QPMB = (UChar *) M4VENC_MALLOC(nTotalMB * sizeof(UChar)); /* Memory for MB quantizers */
+    if (video->QPMB == NULL) goto CLEAN_UP;
+
+
+    video->headerInfo.Mode = (UChar *) M4VENC_MALLOC(sizeof(UChar) * nTotalMB); /* Memory for MB Modes */
+    if (video->headerInfo.Mode == NULL) goto CLEAN_UP;
+    video->headerInfo.CBP = (UChar *) M4VENC_MALLOC(sizeof(UChar) * nTotalMB);   /* Memory for CBP (Y and C) of each MB */
+    if (video->headerInfo.CBP == NULL) goto CLEAN_UP;
+
+    /* Allocating motion vector space and interpolation memory*/
+
+    video->mot = (MOT **)M4VENC_MALLOC(sizeof(MOT *) * nTotalMB);
+    if (video->mot == NULL) goto CLEAN_UP;
+
+    for (idx = 0; idx < nTotalMB; idx++)
+    {
+        video->mot[idx] = (MOT *)M4VENC_MALLOC(sizeof(MOT) * 8);
+        if (video->mot[idx] == NULL)
+        {
+            goto CLEAN_UP;
+        }
+    }
+
+    video->intraArray = (UChar *)M4VENC_MALLOC(sizeof(UChar) * nTotalMB);
+    if (video->intraArray == NULL) goto CLEAN_UP;
+
+    video->sliceNo = (UChar *) M4VENC_MALLOC(nTotalMB); /* Memory for Slice Numbers */
+    if (video->sliceNo == NULL) goto CLEAN_UP;
+    /* Allocating space for predDCAC[][8][16], Not that I intentionally  */
+    /*    increase the dimension of predDCAC from [][6][15] to [][8][16] */
+    /*    so that compilers can generate faster code to indexing the     */
+    /*    data inside (by using << instead of *).         04/14/2000. */
+    /* 5/29/01, use  decoder lib ACDC prediction memory scheme.  */
+    video->predDC = (typeDCStore *) M4VENC_MALLOC(nTotalMB * sizeof(typeDCStore));
+    if (video->predDC == NULL) goto CLEAN_UP;
+
+    if (!video->encParams->H263_Enabled)
+    {
+        video->predDCAC_col = (typeDCACStore *) M4VENC_MALLOC(((max_width >> 4) + 1) * sizeof(typeDCACStore));
+        if (video->predDCAC_col == NULL) goto CLEAN_UP;
+
+        /* element zero will be used for storing vertical (col) AC coefficients */
+        /*  the rest will be used for storing horizontal (row) AC coefficients  */
+        video->predDCAC_row = video->predDCAC_col + 1;        /*  ACDC */
+
+        video->acPredFlag = (Int *) M4VENC_MALLOC(nTotalMB * sizeof(Int)); /* Memory for acPredFlag */
+        if (video->acPredFlag == NULL) goto CLEAN_UP;
+    }
+
+    video->outputMB = (MacroBlock *) M4VENC_MALLOC(sizeof(MacroBlock)); /* Allocating macroblock space */
+    if (video->outputMB == NULL) goto CLEAN_UP;
+    M4VENC_MEMSET(video->outputMB->block[0], 0, (sizeof(Short) << 6)*6);
+
+    M4VENC_MEMSET(video->dataBlock, 0, sizeof(Short) << 7);
+    /* Allocate (2*packetsize) working bitstreams */
+
+    video->bitstream1 = BitStreamCreateEnc(2 * 4096); /*allocate working stream 1*/
+    if (video->bitstream1 == NULL) goto CLEAN_UP;
+    video->bitstream2 = BitStreamCreateEnc(2 * 4096); /*allocate working stream 2*/
+    if (video->bitstream2 == NULL) goto CLEAN_UP;
+    video->bitstream3 = BitStreamCreateEnc(2 * 4096); /*allocate working stream 3*/
+    if (video->bitstream3 == NULL) goto CLEAN_UP;
+
+    /* allocate overrun buffer */
+    // this buffer is used when user's buffer is too small to hold one frame.
+    // It is not needed for slice-based encoding.
+    if (nLayers == 1)
+    {
+        video->oBSize = encParams->BufferSize[0] >> 3;
+    }
+    else
+    {
+        video->oBSize = PV_MAX((encParams->BufferSize[0] >> 3), (encParams->BufferSize[1] >> 3));
+    }
+
+    if (video->oBSize > DEFAULT_OVERRUN_BUFFER_SIZE || encParams->RC_Type == CONSTANT_Q) // set limit
+    {
+        video->oBSize = DEFAULT_OVERRUN_BUFFER_SIZE;
+    }
+    video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * video->oBSize);
+    if (video->overrunBuffer == NULL) goto CLEAN_UP;
+
+
+    video->currVop = (Vop *) M4VENC_MALLOC(sizeof(Vop)); /* Memory for Current VOP */
+    if (video->currVop == NULL) goto CLEAN_UP;
+
+    /* add padding, 09/19/05 */
+    if (video->encParams->H263_Enabled) /* make it conditional  11/28/05 */
+    {
+        pitch = max_width;
+        offset = 0;
+    }
+    else
+    {
+        pitch = max_width + 32;
+        offset = (pitch << 4) + 16;
+        max_height += 32;
+    }
+    size = pitch * max_height;
+
+    video->currVop->yChan = (PIXEL *)M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for currVop Y */
+    if (video->currVop->yChan == NULL) goto CLEAN_UP;
+    video->currVop->uChan = video->currVop->yChan + size;/* Memory for currVop U */
+    video->currVop->vChan = video->currVop->uChan + (size >> 2);/* Memory for currVop V */
+
+    /* shift for the offset */
+    if (offset)
+    {
+        video->currVop->yChan += offset; /* offset to the origin.*/
+        video->currVop->uChan += (offset >> 2) + 4;
+        video->currVop->vChan += (offset >> 2) + 4;
+    }
+
+    video->forwardRefVop = video->currVop;      /*  Initialize forwardRefVop */
+    video->backwardRefVop = video->currVop;     /*  Initialize backwardRefVop */
+
+    video->prevBaseVop = (Vop *) M4VENC_MALLOC(sizeof(Vop));         /* Memory for Previous Base Vop */
+    if (video->prevBaseVop == NULL) goto CLEAN_UP;
+    video->prevBaseVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for prevBaseVop Y */
+    if (video->prevBaseVop->yChan == NULL) goto CLEAN_UP;
+    video->prevBaseVop->uChan = video->prevBaseVop->yChan + size; /* Memory for prevBaseVop U */
+    video->prevBaseVop->vChan = video->prevBaseVop->uChan + (size >> 2); /* Memory for prevBaseVop V */
+
+    if (offset)
+    {
+        video->prevBaseVop->yChan += offset; /* offset to the origin.*/
+        video->prevBaseVop->uChan += (offset >> 2) + 4;
+        video->prevBaseVop->vChan += (offset >> 2) + 4;
+    }
+
+
+    if (0) /* If B Frames */
+    {
+        video->nextBaseVop = (Vop *) M4VENC_MALLOC(sizeof(Vop));         /* Memory for Next Base Vop */
+        if (video->nextBaseVop == NULL) goto CLEAN_UP;
+        video->nextBaseVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for nextBaseVop Y */
+        if (video->nextBaseVop->yChan == NULL) goto CLEAN_UP;
+        video->nextBaseVop->uChan = video->nextBaseVop->yChan + size; /* Memory for nextBaseVop U */
+        video->nextBaseVop->vChan = video->nextBaseVop->uChan + (size >> 2); /* Memory for nextBaseVop V */
+
+        if (offset)
+        {
+            video->nextBaseVop->yChan += offset; /* offset to the origin.*/
+            video->nextBaseVop->uChan += (offset >> 2) + 4;
+            video->nextBaseVop->vChan += (offset >> 2) + 4;
+        }
+    }
+
+    if (nLayers > 1)   /* If enhancement layers */
+    {
+        video->prevEnhanceVop = (Vop *) M4VENC_MALLOC(sizeof(Vop));      /* Memory for Previous Enhancement Vop */
+        if (video->prevEnhanceVop == NULL) goto CLEAN_UP;
+        video->prevEnhanceVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for Previous Ehancement Y */
+        if (video->prevEnhanceVop->yChan == NULL) goto CLEAN_UP;
+        video->prevEnhanceVop->uChan = video->prevEnhanceVop->yChan + size; /* Memory for Previous Enhancement U */
+        video->prevEnhanceVop->vChan = video->prevEnhanceVop->uChan + (size >> 2); /* Memory for Previous Enhancement V */
+
+        if (offset)
+        {
+            video->prevEnhanceVop->yChan += offset; /* offset to the origin.*/
+            video->prevEnhanceVop->uChan += (offset >> 2) + 4;
+            video->prevEnhanceVop->vChan += (offset >> 2) + 4;
+        }
+    }
+
+    video->numberOfLayers = nLayers; /* Number of Layers */
+    video->sumMAD = 0;
+
+
+    /* 04/09/01, for Vops in the use multipass processing */
+    for (idx = 0; idx < nLayers; idx++)
+    {
+        video->pMP[idx] = (MultiPass *)M4VENC_MALLOC(sizeof(MultiPass));
+        if (video->pMP[idx] == NULL)    goto CLEAN_UP;
+        M4VENC_MEMSET(video->pMP[idx], 0, sizeof(MultiPass));
+
+        video->pMP[idx]->encoded_frames = -1; /* forget about the very first I frame */
+
+
+        /* RDInfo **pRDSamples */
+        video->pMP[idx]->pRDSamples = (RDInfo **)M4VENC_MALLOC(30 * sizeof(RDInfo *));
+        if (video->pMP[idx]->pRDSamples == NULL)    goto CLEAN_UP;
+        for (i = 0; i < 30; i++)
+        {
+            video->pMP[idx]->pRDSamples[i] = (RDInfo *)M4VENC_MALLOC(32 * sizeof(RDInfo));
+            if (video->pMP[idx]->pRDSamples[i] == NULL) goto CLEAN_UP;
+            for (j = 0; j < 32; j++)    M4VENC_MEMSET(&(video->pMP[idx]->pRDSamples[i][j]), 0, sizeof(RDInfo));
+        }
+        video->pMP[idx]->frameRange = (Int)(video->encParams->LayerFrameRate[idx] * 1.0); /* 1.0s time frame*/
+        video->pMP[idx]->frameRange = PV_MAX(video->pMP[idx]->frameRange, 5);
+        video->pMP[idx]->frameRange = PV_MIN(video->pMP[idx]->frameRange, 30);
+
+        video->pMP[idx]->framePos = -1;
+
+    }
+    /* /// End /////////////////////////////////////// */
+
+
+    video->vol = (Vol **)M4VENC_MALLOC(nLayers * sizeof(Vol *)); /* Memory for VOL pointers */
+
+    /* Memory allocation and Initialization of Vols and writing of headers */
+    if (video->vol == NULL) goto CLEAN_UP;
+
+    for (idx = 0; idx < nLayers; idx++)
+    {
+        video->volInitialize[idx] = 1;
+        video->refTick[idx] = 0;
+        video->relLayerCodeTime[idx] = 1000;
+        video->vol[idx] = (Vol *)M4VENC_MALLOC(sizeof(Vol));
+        if (video->vol[idx] == NULL)  goto CLEAN_UP;
+
+        pVol = video->vol[idx];
+        pEncParams = video->encParams;
+
+        M4VENC_MEMSET(video->vol[idx], 0, sizeof(Vol));
+        /* Initialize some VOL parameters */
+        pVol->volID = idx;  /* Set VOL ID */
+        pVol->shortVideoHeader = pEncParams->H263_Enabled; /*Short Header */
+        pVol->GOVStart = pEncParams->GOV_Enabled; /* GOV Header */
+        pVol->timeIncrementResolution = video->encParams->TimeIncrementRes;
+        pVol->nbitsTimeIncRes = 1;
+        while (pVol->timeIncrementResolution > (1 << pVol->nbitsTimeIncRes))
+        {
+            pVol->nbitsTimeIncRes++;
+        }
+
+        /* timing stuff */
+        pVol->timeIncrement = 0;
+        pVol->moduloTimeBase = 0;
+        pVol->fixedVopRate = 0; /* No fixed VOP rate */
+        pVol->stream = (BitstreamEncVideo *)M4VENC_MALLOC(sizeof(BitstreamEncVideo)); /* allocate BitstreamEncVideo Instance */
+        if (pVol->stream == NULL)  goto CLEAN_UP;
+
+        pVol->width = pEncParams->LayerWidth[idx];      /* Layer Width */
+        pVol->height = pEncParams->LayerHeight[idx];    /* Layer Height */
+        //  pVol->intra_acdcPredDisable = pEncParams->ACDCPrediction; /* ACDC Prediction */
+        pVol->ResyncMarkerDisable = pEncParams->ResyncMarkerDisable; /* Resync Marker Mode */
+        pVol->dataPartitioning = pEncParams->DataPartitioning; /* Data Partitioning */
+        pVol->useReverseVLC = pEncParams->ReversibleVLC; /* RVLC */
+        if (idx > 0) /* Scalability layers */
+        {
+            pVol->ResyncMarkerDisable = 1;
+            pVol->dataPartitioning = 0;
+            pVol->useReverseVLC = 0; /*  No RVLC */
+        }
+        pVol->quantType = pEncParams->QuantType[idx];           /* Quantizer Type */
+
+        /* no need to init Quant Matrices */
+
+        pVol->scalability = 0;  /* Vol Scalability */
+        if (idx > 0)
+            pVol->scalability = 1; /* Multiple layers => Scalability */
+
+        /* Initialize Vol to Temporal scalability.  It can change during encoding */
+        pVol->scalType = 1;
+        /* Initialize reference Vol ID to the base layer = 0 */
+        pVol->refVolID = 0;
+        /* Initialize layer resolution to same as the reference */
+        pVol->refSampDir = 0;
+        pVol->horSamp_m = 1;
+        pVol->horSamp_n = 1;
+        pVol->verSamp_m = 1;
+        pVol->verSamp_n = 1;
+        pVol->enhancementType = 0; /* We always enhance the entire region */
+
+        pVol->nMBPerRow = (pVol->width + 15) / 16;
+        pVol->nMBPerCol = (pVol->height + 15) / 16;
+        pVol->nTotalMB = pVol->nMBPerRow * pVol->nMBPerCol;
+
+        if (pVol->nTotalMB >= 1)
+            pVol->nBitsForMBID = 1;
+        if (pVol->nTotalMB >= 3)
+            pVol->nBitsForMBID = 2;
+        if (pVol->nTotalMB >= 5)
+            pVol->nBitsForMBID = 3;
+        if (pVol->nTotalMB >= 9)
+            pVol->nBitsForMBID = 4;
+        if (pVol->nTotalMB >= 17)
+            pVol->nBitsForMBID = 5;
+        if (pVol->nTotalMB >= 33)
+            pVol->nBitsForMBID = 6;
+        if (pVol->nTotalMB >= 65)
+            pVol->nBitsForMBID = 7;
+        if (pVol->nTotalMB >= 129)
+            pVol->nBitsForMBID = 8;
+        if (pVol->nTotalMB >= 257)
+            pVol->nBitsForMBID = 9;
+        if (pVol->nTotalMB >= 513)
+            pVol->nBitsForMBID = 10;
+        if (pVol->nTotalMB >= 1025)
+            pVol->nBitsForMBID = 11;
+        if (pVol->nTotalMB >= 2049)
+            pVol->nBitsForMBID = 12;
+        if (pVol->nTotalMB >= 4097)
+            pVol->nBitsForMBID = 13;
+        if (pVol->nTotalMB >= 8193)
+            pVol->nBitsForMBID = 14;
+        if (pVol->nTotalMB >= 16385)
+            pVol->nBitsForMBID = 15;
+        if (pVol->nTotalMB >= 32769)
+            pVol->nBitsForMBID = 16;
+        if (pVol->nTotalMB >= 65537)
+            pVol->nBitsForMBID = 17;
+        if (pVol->nTotalMB >= 131073)
+            pVol->nBitsForMBID = 18;
+
+        if (pVol->shortVideoHeader)
+        {
+            switch (pVol->width)
+            {
+                case 128:
+                    if (pVol->height == 96)  /* source_format = 1 */
+                    {
+                        pVol->nGOBinVop = 6;
+                        pVol->nMBinGOB = 8;
+                    }
+                    else
+                        status = PV_FALSE;
+                    break;
+
+                case 176:
+                    if (pVol->height == 144)  /* source_format = 2 */
+                    {
+                        pVol->nGOBinVop = 9;
+                        pVol->nMBinGOB = 11;
+                    }
+                    else
+                        status = PV_FALSE;
+                    break;
+                case 352:
+                    if (pVol->height == 288)  /* source_format = 2 */
+                    {
+                        pVol->nGOBinVop = 18;
+                        pVol->nMBinGOB = 22;
+                    }
+                    else
+                        status = PV_FALSE;
+                    break;
+
+                case 704:
+                    if (pVol->height == 576)  /* source_format = 2 */
+                    {
+                        pVol->nGOBinVop = 18;
+                        pVol->nMBinGOB = 88;
+                    }
+                    else
+                        status = PV_FALSE;
+                    break;
+                case 1408:
+                    if (pVol->height == 1152)  /* source_format = 2 */
+                    {
+                        pVol->nGOBinVop = 18;
+                        pVol->nMBinGOB = 352;
+                    }
+                    else
+                        status = PV_FALSE;
+                    break;
+
+                default:
+                    status = PV_FALSE;
+                    break;
+            }
+        }
+    }
+
+    /***************************************************/
+    /* allocate and initialize rate control parameters */
+    /***************************************************/
+
+    /* BEGIN INITIALIZATION OF ANNEX L RATE CONTROL */
+    if (video->encParams->RC_Type != CONSTANT_Q)
+    {
+        for (idx = 0; idx < nLayers; idx++) /* 12/25/00 */
+        {
+            video->rc[idx] =
+                (rateControl *)M4VENC_MALLOC(sizeof(rateControl));
+
+            if (video->rc[idx] == NULL) goto CLEAN_UP;
+
+            M4VENC_MEMSET(video->rc[idx], 0, sizeof(rateControl));
+        }
+        if (PV_SUCCESS != RC_Initialize(video))
+        {
+            goto CLEAN_UP;
+        }
+        /* initialization for 2-pass rate control */
+    }
+    /* END INITIALIZATION OF ANNEX L RATE CONTROL */
+
+    /********** assign platform dependent functions ***********************/
+    /* 1/23/01 */
+    /* This must be done at run-time not a compile time */
+    video->functionPointer = (FuncPtr*) M4VENC_MALLOC(sizeof(FuncPtr));
+    if (video->functionPointer == NULL) goto CLEAN_UP;
+
+    video->functionPointer->ComputeMBSum = &ComputeMBSum_C;
+    video->functionPointer->SAD_MB_HalfPel[0] = NULL;
+    video->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HalfPel_Cxh;
+    video->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HalfPel_Cyh;
+    video->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HalfPel_Cxhyh;
+
+#ifndef NO_INTER4V
+    video->functionPointer->SAD_Blk_HalfPel = &SAD_Blk_HalfPel_C;
+    video->functionPointer->SAD_Block = &SAD_Block_C;
+#endif
+    video->functionPointer->SAD_Macroblock = &SAD_Macroblock_C;
+    video->functionPointer->ChooseMode = &ChooseMode_C;
+    video->functionPointer->GetHalfPelMBRegion = &GetHalfPelMBRegion_C;
+//  video->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING; /* 4/21/01 */
+
+
+    encoderControl->videoEncoderInit = 1;  /* init done! */
+
+    return PV_TRUE;
+
+CLEAN_UP:
+    PVCleanUpVideoEncoder(encoderControl);
+
+    return PV_FALSE;
+}
+
+
+/* ======================================================================== */
+/*  Function : PVCleanUpVideoEncoder()                                      */
+/*  Date     : 08/22/2000                                                   */
+/*  Purpose  : Deallocates allocated memory from InitVideoEncoder()         */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified : 5/21/01, free only yChan in Vop                          */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool    PVCleanUpVideoEncoder(VideoEncControls *encoderControl)
+{
+    Int idx, i;
+    VideoEncData *video = (VideoEncData *)encoderControl->videoEncoderData;
+    int nTotalMB;
+    int max_width, offset;
+
+#ifdef PRINT_RC_INFO
+    if (facct != NULL)
+    {
+        fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+        fprintf(facct, "TOTAL NUM BITS GENERATED %d\n", tiTotalNumBitsGenerated);
+        fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+        fprintf(facct, "TOTAL NUMBER OF FRAMES CODED %d\n",
+                video->encParams->rc[0]->totalFrameNumber);
+        fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+        fprintf(facct, "Average BitRate %d\n",
+                (tiTotalNumBitsGenerated / (90 / 30)));
+        fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+        fprintf(facct, "TOTAL NUMBER OF STUFF BITS %d\n", (iStuffBits + 10740));
+        fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+        fprintf(facct, "TOTAL NUMBER OF BITS TO NETWORK %d\n", (35800*90 / 30));;
+        fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+        fprintf(facct, "SUM OF STUFF BITS AND GENERATED BITS %d\n",
+                (tiTotalNumBitsGenerated + iStuffBits + 10740));
+        fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+        fprintf(facct, "UNACCOUNTED DIFFERENCE %d\n",
+                ((35800*90 / 30) - (tiTotalNumBitsGenerated + iStuffBits + 10740)));
+        fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+        fclose(facct);
+    }
+#endif
+
+#ifdef PRINT_EC
+    fclose(fec);
+#endif
+
+    if (video != NULL)
+    {
+
+        if (video->QPMB) M4VENC_FREE(video->QPMB);
+        if (video->headerInfo.Mode)M4VENC_FREE(video->headerInfo.Mode);
+        if (video->headerInfo.CBP)M4VENC_FREE(video->headerInfo.CBP);
+
+
+        if (video->mot)
+        {
+            nTotalMB = video->vol[0]->nTotalMB;
+            for (idx = 1; idx < video->currLayer; idx++)
+                if (video->vol[idx]->nTotalMB > nTotalMB)
+                    nTotalMB = video->vol[idx]->nTotalMB;
+            for (idx = 0; idx < nTotalMB; idx++)
+            {
+                if (video->mot[idx])
+                    M4VENC_FREE(video->mot[idx]);
+            }
+            M4VENC_FREE(video->mot);
+        }
+
+        if (video->intraArray) M4VENC_FREE(video->intraArray);
+
+        if (video->sliceNo)M4VENC_FREE(video->sliceNo);
+        if (video->acPredFlag)M4VENC_FREE(video->acPredFlag);
+//      if(video->predDCAC)M4VENC_FREE(video->predDCAC);
+        if (video->predDC) M4VENC_FREE(video->predDC);
+        video->predDCAC_row = NULL;
+        if (video->predDCAC_col) M4VENC_FREE(video->predDCAC_col);
+        if (video->outputMB)M4VENC_FREE(video->outputMB);
+
+        if (video->bitstream1)BitstreamCloseEnc(video->bitstream1);
+        if (video->bitstream2)BitstreamCloseEnc(video->bitstream2);
+        if (video->bitstream3)BitstreamCloseEnc(video->bitstream3);
+
+        if (video->overrunBuffer) M4VENC_FREE(video->overrunBuffer);
+
+        max_width = video->encParams->LayerWidth[0];
+        max_width = (((max_width + 15) >> 4) << 4); /* 09/19/05 */
+        if (video->encParams->H263_Enabled)
+        {
+            offset = 0;
+        }
+        else
+        {
+            offset = ((max_width + 32) << 4) + 16;
+        }
+
+        if (video->currVop)
+        {
+            if (video->currVop->yChan)
+            {
+                video->currVop->yChan -= offset;
+                M4VENC_FREE(video->currVop->yChan);
+            }
+            M4VENC_FREE(video->currVop);
+        }
+
+        if (video->nextBaseVop)
+        {
+            if (video->nextBaseVop->yChan)
+            {
+                video->nextBaseVop->yChan -= offset;
+                M4VENC_FREE(video->nextBaseVop->yChan);
+            }
+            M4VENC_FREE(video->nextBaseVop);
+        }
+
+        if (video->prevBaseVop)
+        {
+            if (video->prevBaseVop->yChan)
+            {
+                video->prevBaseVop->yChan -= offset;
+                M4VENC_FREE(video->prevBaseVop->yChan);
+            }
+            M4VENC_FREE(video->prevBaseVop);
+        }
+        if (video->prevEnhanceVop)
+        {
+            if (video->prevEnhanceVop->yChan)
+            {
+                video->prevEnhanceVop->yChan -= offset;
+                M4VENC_FREE(video->prevEnhanceVop->yChan);
+            }
+            M4VENC_FREE(video->prevEnhanceVop);
+        }
+
+        /* 04/09/01, for Vops in the use multipass processing */
+        for (idx = 0; idx < video->encParams->nLayers; idx++)
+        {
+            if (video->pMP[idx])
+            {
+                if (video->pMP[idx]->pRDSamples)
+                {
+                    for (i = 0; i < 30; i++)
+                    {
+                        if (video->pMP[idx]->pRDSamples[i])
+                            M4VENC_FREE(video->pMP[idx]->pRDSamples[i]);
+                    }
+                    M4VENC_FREE(video->pMP[idx]->pRDSamples);
+                }
+
+                M4VENC_MEMSET(video->pMP[idx], 0, sizeof(MultiPass));
+                M4VENC_FREE(video->pMP[idx]);
+            }
+        }
+        /* //  End /////////////////////////////////////// */
+
+        if (video->vol)
+        {
+            for (idx = 0; idx < video->encParams->nLayers; idx++)
+            {
+                if (video->vol[idx])
+                {
+                    if (video->vol[idx]->stream)
+                        M4VENC_FREE(video->vol[idx]->stream);
+                    M4VENC_FREE(video->vol[idx]);
+                }
+            }
+            M4VENC_FREE(video->vol);
+        }
+
+        /***************************************************/
+        /* stop rate control parameters */
+        /***************************************************/
+
+        /* ANNEX L RATE CONTROL */
+        if (video->encParams->RC_Type != CONSTANT_Q)
+        {
+            RC_Cleanup(video->rc, video->encParams->nLayers);
+
+            for (idx = 0; idx < video->encParams->nLayers; idx++)
+            {
+                if (video->rc[idx])
+                    M4VENC_FREE(video->rc[idx]);
+            }
+        }
+
+        if (video->functionPointer) M4VENC_FREE(video->functionPointer);
+
+        /* If application has called PVCleanUpVideoEncoder then we deallocate */
+        /* If PVInitVideoEncoder class it, then we DO NOT deallocate */
+        if (video->encParams)
+        {
+            M4VENC_FREE(video->encParams);
+        }
+
+        M4VENC_FREE(video);
+        encoderControl->videoEncoderData = NULL; /* video */
+    }
+
+    encoderControl->videoEncoderInit = 0;
+
+    return PV_TRUE;
+}
+
+/* ======================================================================== */
+/*  Function : PVGetVolHeader()                                             */
+/*  Date     : 7/17/2001,                                                   */
+/*  Purpose  :                                                              */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetVolHeader(VideoEncControls *encCtrl, UChar *volHeader, Int *size, Int layer)
+{
+    VideoEncData    *encData;
+    PV_STATUS   EncodeVOS_Start(VideoEncControls *encCtrl);
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+
+    encData->currLayer = layer; /* Set Layer */
+    /*pv_status = */
+    EncodeVOS_Start(encCtrl); /* Encode VOL Header */
+
+    encData->encParams->GetVolHeader[layer] = 1; /* Set usage flag: Needed to support old method*/
+
+    /* Copy bitstream to buffer and set the size */
+
+    if (*size > encData->bitstream1->byteCount)
+    {
+        *size = encData->bitstream1->byteCount;
+        M4VENC_MEMCPY(volHeader, encData->bitstream1->bitstreamBuffer, *size);
+    }
+    else
+        return PV_FALSE;
+
+    /* Reset bitstream1 buffer parameters */
+    BitstreamEncReset(encData->bitstream1);
+
+    return PV_TRUE;
+}
+
+/* ======================================================================== */
+/*  Function : PVGetOverrunBuffer()                                         */
+/*  Purpose  : Get the overrun buffer `                                     */
+/*  In/out   :                                                              */
+/*  Return   : Pointer to overrun buffer.                                   */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF UChar* PVGetOverrunBuffer(VideoEncControls *encCtrl)
+{
+    VideoEncData *video = (VideoEncData *)encCtrl->videoEncoderData;
+    Int currLayer = video->currLayer;
+    Vol *currVol = video->vol[currLayer];
+
+    if (currVol->stream->bitstreamBuffer != video->overrunBuffer) // not used
+    {
+        return NULL;
+    }
+
+    return video->overrunBuffer;
+}
+
+
+
+
+/* ======================================================================== */
+/*  Function : EncodeVideoFrame()                                           */
+/*  Date     : 08/22/2000                                                   */
+/*  Purpose  : Encode video frame and return bitstream                      */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*  02.14.2001                                      */
+/*              Finishing new timestamp 32-bit input                        */
+/*              Applications need to take care of wrap-around               */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVEncodeVideoFrame(VideoEncControls *encCtrl, VideoEncFrameIO *vid_in, VideoEncFrameIO *vid_out,
+                                        ULong *nextModTime, UChar *bstream, Int *size, Int *nLayer)
+{
+    Bool status = PV_TRUE;
+    PV_STATUS pv_status;
+    VideoEncData *video = (VideoEncData *)encCtrl->videoEncoderData;
+    VideoEncParams *encParams = video->encParams;
+    Vol *currVol;
+    Vop *tempForwRefVop = NULL;
+    Int tempRefSelCode = 0;
+    PV_STATUS   EncodeVOS_Start(VideoEncControls *encCtrl);
+    Int width_16, height_16;
+    Int width, height;
+    Vop *temp;
+    Int encodeVop = 0;
+    void  PaddingEdge(Vop *padVop);
+    Int currLayer = -1;
+    //Int nLayers = encParams->nLayers;
+
+    ULong modTime = vid_in->timestamp;
+
+#ifdef RANDOM_REFSELCODE   /* add random selection of reference Vop */
+    Int random_val[30] = {0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0};
+    static Int rand_idx = 0;
+#endif
+
+    /*******************************************************/
+    /* Determine Next Vop to encode, if any, and nLayer    */
+    /*******************************************************/
+    //i = nLayers-1;
+
+    if (video->volInitialize[0]) /* first vol to code */
+    {
+        video->nextModTime = video->modTimeRef = ((modTime) - ((modTime) % 1000));
+    }
+
+    encodeVop = DetermineCodingLayer(video, nLayer, modTime);
+    currLayer = *nLayer;
+    if ((currLayer < 0) || (currLayer > encParams->nLayers - 1))
+        return PV_FALSE;
+
+    /******************************************/
+    /* If post-skipping still effective --- return */
+    /******************************************/
+
+    if (!encodeVop) /* skip enh layer, no base layer coded --- return */
+    {
+#ifdef _PRINT_STAT
+        printf("No frame coded. Continue to next frame.");
+#endif
+        /* expected next code time, convert back to millisec */
+        *nextModTime = video->nextModTime;
+
+#ifdef ALLOW_VOP_NOT_CODED
+        if (video->vol[0]->shortVideoHeader) /* Short Video Header = 1 */
+        {
+            *size = 0;
+            *nLayer = -1;
+        }
+        else
+        {
+            *nLayer = 0;
+            EncodeVopNotCoded(video, bstream, size, modTime);
+            *size = video->vol[0]->stream->byteCount;
+        }
+#else
+        *size = 0;
+        *nLayer = -1;
+#endif
+        return status;
+    }
+
+
+//ENCODE_VOP_AGAIN:  /* 12/30/00 */
+
+    /**************************************************************/
+    /* Initialize Vol stream structure with application bitstream */
+    /**************************************************************/
+
+    currVol = video->vol[currLayer];
+    currVol->stream->bitstreamBuffer = bstream;
+    currVol->stream->bufferSize = *size;
+    BitstreamEncReset(currVol->stream);
+    BitstreamSetOverrunBuffer(currVol->stream, video->overrunBuffer, video->oBSize, video);
+
+    /***********************************************************/
+    /* Encode VOS and VOL Headers on first call for each layer */
+    /***********************************************************/
+
+    if (video->volInitialize[currLayer])
+    {
+        video->currVop->timeInc = 0;
+        video->prevBaseVop->timeInc = 0;
+        if (!video->encParams->GetVolHeader[currLayer])
+            pv_status = EncodeVOS_Start(encCtrl);
+    }
+
+    /***************************************************/
+    /* Copy Input Video Frame to Internal Video Buffer */
+    /***************************************************/
+    /* Determine Width and Height of Vop Layer */
+
+    width = encParams->LayerWidth[currLayer];   /* Get input width */
+    height = encParams->LayerHeight[currLayer]; /* Get input height */
+    /* Round Up to nearest multiple of 16 : MPEG-4 Standard */
+
+    width_16 = ((width + 15) / 16) * 16;            /* Round up to nearest multiple of 16 */
+    height_16 = ((height + 15) / 16) * 16;          /* Round up to nearest multiple of 16 */
+
+    video->input = vid_in;  /* point to the frame input */
+
+    /*//  End ////////////////////////////// */
+
+
+    /**************************************/
+    /* Determine VOP Type                 */
+    /* 6/2/2001, separate function      */
+    /**************************************/
+    DetermineVopType(video, currLayer);
+
+    /****************************/
+    /*    Initialize VOP        */
+    /****************************/
+    video->currVop->volID = currVol->volID;
+    video->currVop->width = width_16;
+    video->currVop->height = height_16;
+    if (video->encParams->H263_Enabled) /*  11/28/05 */
+    {
+        video->currVop->pitch = width_16;
+    }
+    else
+    {
+        video->currVop->pitch = width_16 + 32;
+    }
+    video->currVop->timeInc = currVol->timeIncrement;
+    video->currVop->vopCoded = 1;
+    video->currVop->roundingType = 0;
+    video->currVop->intraDCVlcThr = encParams->IntraDCVlcThr;
+
+    if (currLayer == 0
+#ifdef RANDOM_REFSELCODE   /* add random selection of reference Vop */
+            || random_val[rand_idx] || video->volInitialize[currLayer]
+#endif
+       )
+    {
+        tempForwRefVop = video->forwardRefVop; /* keep initial state */
+        if (tempForwRefVop != NULL) tempRefSelCode = tempForwRefVop->refSelectCode;
+
+        video->forwardRefVop = video->prevBaseVop;
+        video->forwardRefVop->refSelectCode = 1;
+    }
+#ifdef RANDOM_REFSELCODE
+    else
+    {
+        tempForwRefVop = video->forwardRefVop; /* keep initial state */
+        if (tempForwRefVop != NULL) tempRefSelCode = tempForwRefVop->refSelectCode;
+
+        video->forwardRefVop = video->prevEnhanceVop;
+        video->forwardRefVop->refSelectCode = 0;
+    }
+    rand_idx++;
+    rand_idx %= 30;
+#endif
+
+    video->currVop->refSelectCode = video->forwardRefVop->refSelectCode;
+    video->currVop->gobNumber = 0;
+    video->currVop->gobFrameID = video->currVop->predictionType;
+    video->currVop->temporalRef = (modTime * 30 / 1001) % 256;
+
+    video->currVop->temporalInterval = 0;
+
+    if (video->currVop->predictionType == I_VOP)
+        video->currVop->quantizer = encParams->InitQuantIvop[currLayer];
+    else
+        video->currVop->quantizer = encParams->InitQuantPvop[currLayer];
+
+
+    /****************/
+    /* Encode Vop */
+    /****************/
+    video->slice_coding = 0;
+
+    pv_status = EncodeVop(video);
+#ifdef _PRINT_STAT
+    if (video->currVop->predictionType == I_VOP)
+        printf(" I-VOP ");
+    else
+        printf(" P-VOP (ref.%d)", video->forwardRefVop->refSelectCode);
+#endif
+
+    /************************************/
+    /* Update Skip Next Frame           */
+    /************************************/
+    *nLayer = UpdateSkipNextFrame(video, nextModTime, size, pv_status);
+    if (*nLayer == -1) /* skip current frame */
+    {
+        /* make sure that pointers are restored to the previous state */
+        if (currLayer == 0)
+        {
+            video->forwardRefVop = tempForwRefVop; /* For P-Vop base only */
+            video->forwardRefVop->refSelectCode = tempRefSelCode;
+        }
+
+        return status;
+    }
+
+    /* If I-VOP was encoded, reset IntraPeriod */
+    if ((currLayer == 0) && (encParams->IntraPeriod > 0) && (video->currVop->predictionType == I_VOP))
+        video->nextEncIVop = encParams->IntraPeriod;
+
+    /* Set HintTrack Information */
+    if (currLayer != -1)
+    {
+        if (currVol->prevModuloTimeBase)
+            video->hintTrackInfo.MTB = 1;
+        else
+            video->hintTrackInfo.MTB = 0;
+        video->hintTrackInfo.LayerID = (UChar)currVol->volID;
+        video->hintTrackInfo.CodeType = (UChar)video->currVop->predictionType;
+        video->hintTrackInfo.RefSelCode = (UChar)video->currVop->refSelectCode;
+    }
+
+    /************************************************/
+    /* Determine nLayer and timeInc for next encode */
+    /* 12/27/00 always go by the highest layer*/
+    /************************************************/
+
+    /**********************************************************/
+    /* Copy Reconstructed Buffer to Output Video Frame Buffer */
+    /**********************************************************/
+    vid_out->yChan = video->currVop->yChan;
+    vid_out->uChan = video->currVop->uChan;
+    vid_out->vChan = video->currVop->vChan;
+    if (video->encParams->H263_Enabled)
+    {
+        vid_out->height = video->currVop->height; /* padded height */
+        vid_out->pitch = video->currVop->width; /* padded width */
+    }
+    else
+    {
+        vid_out->height = video->currVop->height + 32; /* padded height */
+        vid_out->pitch = video->currVop->width + 32; /* padded width */
+    }
+    //video_out->timestamp = video->modTime;
+    vid_out->timestamp = (ULong)(((video->prevFrameNum[currLayer] * 1000) / encParams->LayerFrameRate[currLayer]) + video->modTimeRef + 0.5);
+
+    /*// End /////////////////////// */
+
+    /***********************************/
+    /* Update Ouput bstream byte count */
+    /***********************************/
+
+    *size = currVol->stream->byteCount;
+
+    /****************************************/
+    /* Swap Vop Pointers for Base Layer     */
+    /****************************************/
+    if (currLayer == 0)
+    {
+        temp = video->prevBaseVop;
+        video->prevBaseVop = video->currVop;
+        video->prevBaseVop->padded = 0; /* not padded */
+        video->currVop  = temp;
+        video->forwardRefVop = video->prevBaseVop; /* For P-Vop base only */
+        video->forwardRefVop->refSelectCode = 1;
+    }
+    else
+    {
+        temp = video->prevEnhanceVop;
+        video->prevEnhanceVop = video->currVop;
+        video->prevEnhanceVop->padded = 0; /* not padded */
+        video->currVop = temp;
+        video->forwardRefVop = video->prevEnhanceVop;
+        video->forwardRefVop->refSelectCode = 0;
+    }
+
+    /****************************************/
+    /* Modify the intialize flag at the end.*/
+    /****************************************/
+    if (video->volInitialize[currLayer])
+        video->volInitialize[currLayer] = 0;
+
+    return status;
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/*  Function : PVEncodeFrameSet()                                           */
+/*  Date     : 04/18/2000                                                   */
+/*  Purpose  : Enter a video frame and perform front-end time check plus ME */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVEncodeFrameSet(VideoEncControls *encCtrl, VideoEncFrameIO *vid_in, ULong *nextModTime, Int *nLayer)
+{
+    Bool status = PV_TRUE;
+    VideoEncData *video = (VideoEncData *)encCtrl->videoEncoderData;
+    VideoEncParams *encParams = video->encParams;
+    Vol *currVol;
+    PV_STATUS   EncodeVOS_Start(VideoEncControls *encCtrl);
+    Int width_16, height_16;
+    Int width, height;
+    Int encodeVop = 0;
+    void  PaddingEdge(Vop *padVop);
+    Int currLayer = -1;
+    //Int nLayers = encParams->nLayers;
+
+    ULong   modTime = vid_in->timestamp;
+
+#ifdef RANDOM_REFSELCODE   /* add random selection of reference Vop */
+    Int random_val[30] = {0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0};
+    static Int rand_idx = 0;
+#endif
+    /*******************************************************/
+    /* Determine Next Vop to encode, if any, and nLayer    */
+    /*******************************************************/
+
+    video->modTime = modTime;
+
+    //i = nLayers-1;
+
+    if (video->volInitialize[0]) /* first vol to code */
+    {
+        video->nextModTime = video->modTimeRef = ((modTime) - ((modTime) % 1000));
+    }
+
+
+    encodeVop = DetermineCodingLayer(video, nLayer, modTime);
+
+    currLayer = *nLayer;
+
+    /******************************************/
+    /* If post-skipping still effective --- return */
+    /******************************************/
+
+    if (!encodeVop) /* skip enh layer, no base layer coded --- return */
+    {
+#ifdef _PRINT_STAT
+        printf("No frame coded. Continue to next frame.");
+#endif
+        *nLayer = -1;
+
+        /* expected next code time, convert back to millisec */
+        *nextModTime = video->nextModTime;;
+        return status;
+    }
+
+    /**************************************************************/
+    /* Initialize Vol stream structure with application bitstream */
+    /**************************************************************/
+
+    currVol = video->vol[currLayer];
+    currVol->stream->bufferSize = 0;
+    BitstreamEncReset(currVol->stream);
+
+    /***********************************************************/
+    /* Encode VOS and VOL Headers on first call for each layer */
+    /***********************************************************/
+
+    if (video->volInitialize[currLayer])
+    {
+        video->currVop->timeInc = 0;
+        video->prevBaseVop->timeInc = 0;
+    }
+
+    /***************************************************/
+    /* Copy Input Video Frame to Internal Video Buffer */
+    /***************************************************/
+    /* Determine Width and Height of Vop Layer */
+
+    width = encParams->LayerWidth[currLayer];   /* Get input width */
+    height = encParams->LayerHeight[currLayer]; /* Get input height */
+    /* Round Up to nearest multiple of 16 : MPEG-4 Standard */
+
+    width_16 = ((width + 15) / 16) * 16;            /* Round up to nearest multiple of 16 */
+    height_16 = ((height + 15) / 16) * 16;          /* Round up to nearest multiple of 16 */
+
+    video->input = vid_in;  /* point to the frame input */
+
+    /*//  End ////////////////////////////// */
+
+
+    /**************************************/
+    /* Determine VOP Type                 */
+    /* 6/2/2001, separate function      */
+    /**************************************/
+    DetermineVopType(video, currLayer);
+
+    /****************************/
+    /*    Initialize VOP        */
+    /****************************/
+    video->currVop->volID = currVol->volID;
+    video->currVop->width = width_16;
+    video->currVop->height = height_16;
+    if (video->encParams->H263_Enabled) /*  11/28/05 */
+    {
+        video->currVop->pitch = width_16;
+    }
+    else
+    {
+        video->currVop->pitch = width_16 + 32;
+    }
+    video->currVop->timeInc = currVol->timeIncrement;
+    video->currVop->vopCoded = 1;
+    video->currVop->roundingType = 0;
+    video->currVop->intraDCVlcThr = encParams->IntraDCVlcThr;
+
+    if (currLayer == 0
+#ifdef RANDOM_REFSELCODE   /* add random selection of reference Vop */
+            || random_val[rand_idx] || video->volInitialize[currLayer]
+#endif
+       )
+    {
+        video->tempForwRefVop = video->forwardRefVop; /* keep initial state */
+        if (video->tempForwRefVop != NULL) video->tempRefSelCode = video->tempForwRefVop->refSelectCode;
+
+        video->forwardRefVop = video->prevBaseVop;
+        video->forwardRefVop->refSelectCode = 1;
+    }
+#ifdef RANDOM_REFSELCODE
+    else
+    {
+        video->tempForwRefVop = video->forwardRefVop; /* keep initial state */
+        if (video->tempForwRefVop != NULL) video->tempRefSelCode = video->tempForwRefVop->refSelectCode;
+
+        video->forwardRefVop = video->prevEnhanceVop;
+        video->forwardRefVop->refSelectCode = 0;
+    }
+    rand_idx++;
+    rand_idx %= 30;
+#endif
+
+    video->currVop->refSelectCode = video->forwardRefVop->refSelectCode;
+    video->currVop->gobNumber = 0;
+    video->currVop->gobFrameID = video->currVop->predictionType;
+    video->currVop->temporalRef = ((modTime) * 30 / 1001) % 256;
+
+    video->currVop->temporalInterval = 0;
+
+    if (video->currVop->predictionType == I_VOP)
+        video->currVop->quantizer = encParams->InitQuantIvop[currLayer];
+    else
+        video->currVop->quantizer = encParams->InitQuantPvop[currLayer];
+
+    /****************/
+    /* Encode Vop   */
+    /****************/
+    video->slice_coding = 1;
+
+    /*pv_status =*/
+    EncodeVop(video);
+
+#ifdef _PRINT_STAT
+    if (video->currVop->predictionType == I_VOP)
+        printf(" I-VOP ");
+    else
+        printf(" P-VOP (ref.%d)", video->forwardRefVop->refSelectCode);
+#endif
+
+    /* Set HintTrack Information */
+    if (currVol->prevModuloTimeBase)
+        video->hintTrackInfo.MTB = 1;
+    else
+        video->hintTrackInfo.MTB = 0;
+
+    video->hintTrackInfo.LayerID = (UChar)currVol->volID;
+    video->hintTrackInfo.CodeType = (UChar)video->currVop->predictionType;
+    video->hintTrackInfo.RefSelCode = (UChar)video->currVop->refSelectCode;
+
+    return status;
+}
+#endif /* NO_SLICE_ENCODE */
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/*  Function : PVEncodePacket()                                             */
+/*  Date     : 04/18/2002                                                   */
+/*  Purpose  : Encode one packet and return bitstream                       */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVEncodeSlice(VideoEncControls *encCtrl, UChar *bstream, Int *size,
+                                   Int *endofFrame, VideoEncFrameIO *vid_out, ULong *nextModTime)
+{
+    PV_STATUS pv_status;
+    VideoEncData *video = (VideoEncData *)encCtrl->videoEncoderData;
+    VideoEncParams *encParams = video->encParams;
+    Vol *currVol;
+    PV_STATUS   EncodeVOS_Start(VideoEncControls *encCtrl);
+    Vop *temp;
+    void  PaddingEdge(Vop *padVop);
+    Int currLayer = video->currLayer;
+    Int pre_skip;
+    Int pre_size;
+    /**************************************************************/
+    /* Initialize Vol stream structure with application bitstream */
+    /**************************************************************/
+
+    currVol = video->vol[currLayer];
+    currVol->stream->bitstreamBuffer = bstream;
+    pre_size = currVol->stream->byteCount;
+    currVol->stream->bufferSize = pre_size + (*size);
+
+    /***********************************************************/
+    /* Encode VOS and VOL Headers on first call for each layer */
+    /***********************************************************/
+
+    if (video->volInitialize[currLayer])
+    {
+        if (!video->encParams->GetVolHeader[currLayer])
+            pv_status = EncodeVOS_Start(encCtrl);
+    }
+
+    /****************/
+    /* Encode Slice */
+    /****************/
+    pv_status = EncodeSlice(video);
+
+    *endofFrame = 0;
+
+    if (video->mbnum >= currVol->nTotalMB && !video->end_of_buf)
+    {
+        *endofFrame = 1;
+
+        /************************************/
+        /* Update Skip Next Frame           */
+        /************************************/
+        pre_skip = UpdateSkipNextFrame(video, nextModTime, size, pv_status); /* modified such that no pre-skipped */
+
+        if (pre_skip == -1) /* error */
+        {
+            *endofFrame = -1;
+            /* make sure that pointers are restored to the previous state */
+            if (currLayer == 0)
+            {
+                video->forwardRefVop = video->tempForwRefVop; /* For P-Vop base only */
+                video->forwardRefVop->refSelectCode = video->tempRefSelCode;
+            }
+
+            return pv_status;
+        }
+
+        /* If I-VOP was encoded, reset IntraPeriod */
+        if ((currLayer == 0) && (encParams->IntraPeriod > 0) && (video->currVop->predictionType == I_VOP))
+            video->nextEncIVop = encParams->IntraPeriod;
+
+        /**********************************************************/
+        /* Copy Reconstructed Buffer to Output Video Frame Buffer */
+        /**********************************************************/
+        vid_out->yChan = video->currVop->yChan;
+        vid_out->uChan = video->currVop->uChan;
+        vid_out->vChan = video->currVop->vChan;
+        if (video->encParams->H263_Enabled)
+        {
+            vid_out->height = video->currVop->height; /* padded height */
+            vid_out->pitch = video->currVop->width; /* padded width */
+        }
+        else
+        {
+            vid_out->height = video->currVop->height + 32; /* padded height */
+            vid_out->pitch = video->currVop->width + 32; /* padded width */
+        }
+        //vid_out->timestamp = video->modTime;
+        vid_out->timestamp = (ULong)(((video->prevFrameNum[currLayer] * 1000) / encParams->LayerFrameRate[currLayer]) + video->modTimeRef + 0.5);
+
+        /*// End /////////////////////// */
+
+        /****************************************/
+        /* Swap Vop Pointers for Base Layer     */
+        /****************************************/
+
+        if (currLayer == 0)
+        {
+            temp = video->prevBaseVop;
+            video->prevBaseVop = video->currVop;
+            video->prevBaseVop->padded = 0; /* not padded */
+            video->currVop = temp;
+            video->forwardRefVop = video->prevBaseVop; /* For P-Vop base only */
+            video->forwardRefVop->refSelectCode = 1;
+        }
+        else
+        {
+            temp = video->prevEnhanceVop;
+            video->prevEnhanceVop = video->currVop;
+            video->prevEnhanceVop->padded = 0; /* not padded */
+            video->currVop = temp;
+            video->forwardRefVop = video->prevEnhanceVop;
+            video->forwardRefVop->refSelectCode = 0;
+        }
+    }
+
+    /***********************************/
+    /* Update Ouput bstream byte count */
+    /***********************************/
+
+    *size = currVol->stream->byteCount - pre_size;
+
+    /****************************************/
+    /* Modify the intialize flag at the end.*/
+    /****************************************/
+    if (video->volInitialize[currLayer])
+        video->volInitialize[currLayer] = 0;
+
+    return pv_status;
+}
+#endif /* NO_SLICE_ENCODE */
+
+
+/* ======================================================================== */
+/*  Function : PVGetH263ProfileLevelID()                                    */
+/*  Date     : 02/05/2003                                                   */
+/*  Purpose  : Get H.263 Profile ID and level ID for profile 0              */
+/*  In/out   : Profile ID=0, levelID is what we want                        */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*  Note     : h263Level[8], rBR_bound[8], max_h263_framerate[2]            */
+/*             max_h263_width[2], max_h263_height[2] are global             */
+/*                                                                          */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVGetH263ProfileLevelID(VideoEncControls *encCtrl, Int *profileID, Int *levelID)
+{
+    VideoEncData *encData;
+    Int width, height;
+    float bitrate_r, framerate;
+
+
+    /* For this version, we only support H.263 profile 0 */
+    *profileID = 0;
+
+    *levelID = 0;
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+    if (!encData->encParams->H263_Enabled) return PV_FALSE;
+
+
+    /* get image width, height, bitrate and framerate */
+    width     = encData->encParams->LayerWidth[0];
+    height    = encData->encParams->LayerHeight[0];
+    bitrate_r = (float)(encData->encParams->LayerBitRate[0]) / (float)64000.0;
+    framerate = encData->encParams->LayerFrameRate[0];
+    if (!width || !height || !(bitrate_r > 0 && framerate > 0)) return PV_FALSE;
+
+    /* This is the most frequent case : level 10 */
+    if (bitrate_r <= rBR_bound[1] && framerate <= max_h263_framerate[0] &&
+            (width <= max_h263_width[0] && height <= max_h263_height[0]))
+    {
+        *levelID = h263Level[1];
+        return PV_TRUE;
+    }
+    else if (bitrate_r > rBR_bound[4] ||
+             (width > max_h263_width[1] || height > max_h263_height[1]) ||
+             framerate > max_h263_framerate[1])    /* check the highest level 70 */
+    {
+        *levelID = h263Level[7];
+        return PV_TRUE;
+    }
+    else   /* search level 20, 30, 40 */
+    {
+
+        /* pick out level 20 */
+        if (bitrate_r <= rBR_bound[2] &&
+                ((width <= max_h263_width[0] && height <= max_h263_height[0] && framerate <= max_h263_framerate[1]) ||
+                 (width <= max_h263_width[1] && height <= max_h263_height[1] && framerate <= max_h263_framerate[0])))
+        {
+            *levelID = h263Level[2];
+            return PV_TRUE;
+        }
+        else   /* width, height and framerate are ok, now choose level 30 or 40 */
+        {
+            *levelID = (bitrate_r <= rBR_bound[3] ? h263Level[3] : h263Level[4]);
+            return PV_TRUE;
+        }
+    }
+}
+
+/* ======================================================================== */
+/*  Function : PVGetMPEG4ProfileLevelID()                                   */
+/*  Date     : 26/06/2008                                                   */
+/*  Purpose  : Get MPEG4 Level after initialized                            */
+/*  In/out   : profile_level according to interface                         */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVGetMPEG4ProfileLevelID(VideoEncControls *encCtrl, Int *profile_level, Int nLayer)
+{
+    VideoEncData* video;
+    Int i;
+
+    video = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (nLayer == 0)
+    {
+        for (i = 0; i < 8; i++)
+        {
+            if (video->encParams->ProfileLevel[0] == profile_level_code[i])
+            {
+                break;
+            }
+        }
+        *profile_level = i;
+    }
+    else
+    {
+        for (i = 0; i < 8; i++)
+        {
+            if (video->encParams->ProfileLevel[0] == scalable_profile_level_code[i])
+            {
+                break;
+            }
+        }
+        *profile_level = i + SIMPLE_SCALABLE_PROFILE_LEVEL0;
+    }
+
+    return true;
+}
+
+#ifndef LIMITED_API
+/* ======================================================================== */
+/*  Function : PVUpdateEncFrameRate                                         */
+/*  Date     : 04/08/2002                                                   */
+/*  Purpose  : Update target frame rates of the encoded base and enhance    */
+/*             layer(if any) while encoding operation is ongoing            */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVUpdateEncFrameRate(VideoEncControls *encCtrl, float *frameRate)
+{
+    VideoEncData    *encData;
+    Int i;// nTotalMB, mbPerSec;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+    /* Update the framerates for all the layers */
+    for (i = 0; i < encData->encParams->nLayers; i++)
+    {
+
+        /* New check: encoding framerate should be consistent with the given profile and level */
+        //nTotalMB = (((encData->encParams->LayerWidth[i]+15)/16)*16)*(((encData->encParams->LayerHeight[i]+15)/16)*16)/(16*16);
+        //mbPerSec = (Int)(nTotalMB * frameRate[i]);
+        //if(mbPerSec > encData->encParams->LayerMaxMbsPerSec[i]) return PV_FALSE;
+        if (frameRate[i] > encData->encParams->LayerMaxFrameRate[i]) return PV_FALSE; /* set by users or profile */
+
+        encData->encParams->LayerFrameRate[i] = frameRate[i];
+    }
+
+    return RC_UpdateBXRCParams((void*) encData);
+
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/*  Function : PVUpdateBitRate                                              */
+/*  Date     : 04/08/2002                                                   */
+/*  Purpose  : Update target bit rates of the encoded base and enhance      */
+/*             layer(if any) while encoding operation is ongoing            */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVUpdateBitRate(VideoEncControls *encCtrl, Int *bitRate)
+{
+    VideoEncData    *encData;
+    Int i;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+    /* Update the bitrates for all the layers */
+    for (i = 0; i < encData->encParams->nLayers; i++)
+    {
+        if (bitRate[i] > encData->encParams->LayerMaxBitRate[i]) /* set by users or profile */
+        {
+            return PV_FALSE;
+        }
+        encData->encParams->LayerBitRate[i] = bitRate[i];
+    }
+
+    return RC_UpdateBXRCParams((void*) encData);
+
+}
+#endif
+#ifndef LIMITED_API
+/* ============================================================================ */
+/*  Function : PVUpdateVBVDelay()                                                   */
+/*  Date     : 4/23/2004                                                        */
+/*  Purpose  : Update VBV buffer size(in delay)                                 */
+/*  In/out   :                                                                  */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                        */
+/*  Modified :                                                                  */
+/*                                                                              */
+/* ============================================================================ */
+
+Bool PVUpdateVBVDelay(VideoEncControls *encCtrl, float delay)
+{
+
+    VideoEncData    *encData;
+    Int total_bitrate, max_buffer_size;
+    int index;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+    /* Check whether the input delay is valid based on the given profile */
+    total_bitrate   = (encData->encParams->nLayers == 1 ? encData->encParams->LayerBitRate[0] :
+                       encData->encParams->LayerBitRate[1]);
+    index = encData->encParams->profile_table_index;
+    max_buffer_size = (encData->encParams->nLayers == 1 ? profile_level_max_VBV_size[index] :
+                       scalable_profile_level_max_VBV_size[index]);
+
+    if (total_bitrate*delay > (float)max_buffer_size)
+        return PV_FALSE;
+
+    encData->encParams->VBV_delay = delay;
+    return PV_TRUE;
+
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/*  Function : PVUpdateIFrameInterval()                                         */
+/*  Date     : 04/10/2002                                                   */
+/*  Purpose  : updates the INTRA frame refresh interval while encoding      */
+/*             is ongoing                                                   */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVUpdateIFrameInterval(VideoEncControls *encCtrl, Int aIFramePeriod)
+{
+    VideoEncData    *encData;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+    encData->encParams->IntraPeriod = aIFramePeriod;
+    return PV_TRUE;
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/*  Function : PVSetNumIntraMBRefresh()                                     */
+/*  Date     : 08/05/2003                                                   */
+/*  Purpose  :                                                              */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool    PVUpdateNumIntraMBRefresh(VideoEncControls *encCtrl, Int numMB)
+{
+    VideoEncData    *encData;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+
+    encData->encParams->Refresh = numMB;
+
+    return PV_TRUE;
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/*  Function : PVIFrameRequest()                                            */
+/*  Date     : 04/10/2002                                                   */
+/*  Purpose  : encodes the next base frame as an I-Vop                      */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVIFrameRequest(VideoEncControls *encCtrl)
+{
+    VideoEncData    *encData;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+    encData->nextEncIVop = 1;
+    return PV_TRUE;
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/*  Function : PVGetEncMemoryUsage()                                        */
+/*  Date     : 10/17/2000                                                   */
+/*  Purpose  :                                                              */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Int PVGetEncMemoryUsage(VideoEncControls *encCtrl)
+{
+    VideoEncData    *encData;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+    return encData->encParams->MemoryUsage;
+}
+#endif
+
+/* ======================================================================== */
+/*  Function : PVGetHintTrack()                                             */
+/*  Date     : 1/17/2001,                                                   */
+/*  Purpose  :                                                              */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetHintTrack(VideoEncControls *encCtrl, MP4HintTrack *info)
+{
+    VideoEncData    *encData;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+    info->MTB = encData->hintTrackInfo.MTB;
+    info->LayerID = encData->hintTrackInfo.LayerID;
+    info->CodeType = encData->hintTrackInfo.CodeType;
+    info->RefSelCode = encData->hintTrackInfo.RefSelCode;
+
+    return PV_TRUE;
+}
+
+/* ======================================================================== */
+/*  Function : PVGetMaxVideoFrameSize()                                     */
+/*  Date     : 7/17/2001,                                                   */
+/*  Purpose  : Function merely returns the maximum buffer size              */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetMaxVideoFrameSize(VideoEncControls *encCtrl, Int *maxVideoFrameSize)
+{
+    VideoEncData    *encData;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+
+
+    *maxVideoFrameSize = encData->encParams->BufferSize[0];
+
+    if (encData->encParams->nLayers == 2)
+        if (*maxVideoFrameSize < encData->encParams->BufferSize[1])
+            *maxVideoFrameSize = encData->encParams->BufferSize[1];
+    *maxVideoFrameSize >>= 3;   /* Convert to Bytes */
+
+    if (*maxVideoFrameSize <= 4000)
+        *maxVideoFrameSize = 4000;
+
+    return PV_TRUE;
+}
+#ifndef LIMITED_API
+/* ======================================================================== */
+/*  Function : PVGetVBVSize()                                               */
+/*  Date     : 4/15/2002                                                    */
+/*  Purpose  : Function merely returns the maximum buffer size              */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetVBVSize(VideoEncControls *encCtrl, Int *VBVSize)
+{
+    VideoEncData    *encData;
+
+    encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+    if (encData == NULL)
+        return PV_FALSE;
+    if (encData->encParams == NULL)
+        return PV_FALSE;
+
+    *VBVSize = encData->encParams->BufferSize[0];
+    if (encData->encParams->nLayers == 2)
+        *VBVSize += encData->encParams->BufferSize[1];
+
+    return PV_TRUE;
+
+}
+#endif
+/* ======================================================================== */
+/*  Function : EncodeVOS_Start()                                            */
+/*  Date     : 08/22/2000                                                   */
+/*  Purpose  : Encodes the VOS,VO, and VOL or Short Headers                 */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+PV_STATUS EncodeVOS_Start(VideoEncControls *encoderControl)
+{
+
+    VideoEncData *video = (VideoEncData *)encoderControl->videoEncoderData;
+    Vol         *currVol = video->vol[video->currLayer];
+    PV_STATUS status = PV_SUCCESS;
+    //int profile_level=0x01;
+    BitstreamEncVideo *stream = video->bitstream1;
+    int i, j;
+
+    /********************************/
+    /* Check for short_video_header */
+    /********************************/
+    if (currVol->shortVideoHeader == 1)
+        return status;
+    else
+    {
+        /* Short Video Header or M4V */
+
+        /**************************/
+        /* VisualObjectSequence ()*/
+        /**************************/
+        status = BitstreamPutGT16Bits(stream, 32, SESSION_START_CODE);
+        /*  Determine profile_level */
+        status = BitstreamPutBits(stream, 8, video->encParams->ProfileLevel[video->currLayer]);
+
+        /******************/
+        /* VisualObject() */
+        /******************/
+
+        status = BitstreamPutGT16Bits(stream, 32, VISUAL_OBJECT_START_CODE);
+        status = BitstreamPut1Bits(stream, 0x00); /* visual object identifier */
+        status = BitstreamPutBits(stream, 4, 0x01); /* visual object Type == "video ID" */
+        status = BitstreamPut1Bits(stream, 0x00); /* no video signal type */
+
+        /*temp   = */
+        BitstreamMpeg4ByteAlignStuffing(stream);
+
+
+        status = BitstreamPutGT16Bits(stream, 27, VO_START_CODE);/* byte align: should be 2 bits */
+        status = BitstreamPutBits(stream, 5, 0x00);/*  Video ID = 0  */
+
+
+
+        /**********************/
+        /* VideoObjectLayer() */
+        /**********************/
+        if (currVol->shortVideoHeader == 0)
+        { /* M4V  else Short Video Header */
+            status = BitstreamPutGT16Bits(stream, VOL_START_CODE_LENGTH, VOL_START_CODE);
+            status = BitstreamPutBits(stream, 4, currVol->volID);/*  video_object_layer_id */
+            status = BitstreamPut1Bits(stream, 0x00);/*  Random Access = 0  */
+
+            if (video->currLayer == 0)
+                status = BitstreamPutBits(stream, 8, 0x01);/* Video Object Type Indication = 1  ... Simple Object Type */
+            else
+                status = BitstreamPutBits(stream, 8, 0x02);/* Video Object Type Indication = 2  ... Simple Scalable Object Type */
+
+            status = BitstreamPut1Bits(stream, 0x00);/*  is_object_layer_identifer = 0 */
+
+
+            status = BitstreamPutBits(stream, 4, 0x01); /* aspect_ratio_info = 1 ... 1:1(Square) */
+            status = BitstreamPut1Bits(stream, 0x00);/* vol_control_parameters = 0 */
+            status = BitstreamPutBits(stream, 2, 0x00);/* video_object_layer_shape = 00 ... rectangular */
+            status = BitstreamPut1Bits(stream, 0x01);/* marker bit */
+            status = BitstreamPutGT8Bits(stream, 16, currVol->timeIncrementResolution);/* vop_time_increment_resolution */
+            status = BitstreamPut1Bits(stream, 0x01);/* marker bit */
+            status = BitstreamPut1Bits(stream, currVol->fixedVopRate);/* fixed_vop_rate = 0 */
+
+            /* For Rectangular VO layer shape */
+            status = BitstreamPut1Bits(stream, 0x01);/* marker bit */
+            status = BitstreamPutGT8Bits(stream, 13, currVol->width);/* video_object_layer_width */
+            status = BitstreamPut1Bits(stream, 0x01);/* marker bit */
+            status = BitstreamPutGT8Bits(stream, 13, currVol->height);/* video_object_layer_height */
+            status = BitstreamPut1Bits(stream, 0x01);/*marker bit */
+
+            status = BitstreamPut1Bits(stream, 0x00);/*interlaced = 0 */
+            status = BitstreamPut1Bits(stream, 0x01);/* obmc_disable = 1 */
+            status = BitstreamPut1Bits(stream, 0x00);/* sprite_enable = 0 */
+            status = BitstreamPut1Bits(stream, 0x00);/* not_8_bit = 0 */
+            status = BitstreamPut1Bits(stream, currVol->quantType);/*   quant_type */
+
+            if (currVol->quantType)
+            {
+                status = BitstreamPut1Bits(stream, currVol->loadIntraQuantMat); /* Intra quant matrix */
+                if (currVol->loadIntraQuantMat)
+                {
+                    for (j = 63; j >= 1; j--)
+                        if (currVol->iqmat[*(zigzag_i+j)] != currVol->iqmat[*(zigzag_i+j-1)])
+                            break;
+                    if ((j == 1) && (currVol->iqmat[*(zigzag_i+j)] == currVol->iqmat[*(zigzag_i+j-1)]))
+                        j = 0;
+                    for (i = 0; i < j + 1; i++)
+                        BitstreamPutBits(stream, 8, currVol->iqmat[*(zigzag_i+i)]);
+                    if (j < 63)
+                        BitstreamPutBits(stream, 8, 0);
+                }
+                else
+                {
+                    for (j = 0; j < 64; j++)
+                        currVol->iqmat[j] = mpeg_iqmat_def[j];
+
+                }
+                status = BitstreamPut1Bits(stream, currVol->loadNonIntraQuantMat); /* Non-Intra quant matrix */
+                if (currVol->loadNonIntraQuantMat)
+                {
+                    for (j = 63; j >= 1; j--)
+                        if (currVol->niqmat[*(zigzag_i+j)] != currVol->niqmat[*(zigzag_i+j-1)])
+                            break;
+                    if ((j == 1) && (currVol->niqmat[*(zigzag_i+j)] == currVol->niqmat[*(zigzag_i+j-1)]))
+                        j = 0;
+                    for (i = 0; i < j + 1; i++)
+                        BitstreamPutBits(stream, 8, currVol->niqmat[*(zigzag_i+i)]);
+                    if (j < 63)
+                        BitstreamPutBits(stream, 8, 0);
+                }
+                else
+                {
+                    for (j = 0; j < 64; j++)
+                        currVol->niqmat[j] = mpeg_nqmat_def[j];
+                }
+            }
+
+            status = BitstreamPut1Bits(stream, 0x01);   /* complexity_estimation_disable = 1 */
+            status = BitstreamPut1Bits(stream, currVol->ResyncMarkerDisable);/* Resync_marker_disable */
+            status = BitstreamPut1Bits(stream, currVol->dataPartitioning);/* Data partitioned */
+
+            if (currVol->dataPartitioning)
+                status = BitstreamPut1Bits(stream, currVol->useReverseVLC); /* Reversible_vlc */
+
+
+            if (currVol->scalability) /* Scalability*/
+            {
+
+                status = BitstreamPut1Bits(stream, currVol->scalability);/* Scalability = 1 */
+                status = BitstreamPut1Bits(stream, currVol->scalType);/* hierarchy _type ... Spatial= 0 and Temporal = 1 */
+                status = BitstreamPutBits(stream, 4, currVol->refVolID);/* ref_layer_id  */
+                status = BitstreamPut1Bits(stream, currVol->refSampDir);/* ref_layer_sampling_direc*/
+                status = BitstreamPutBits(stream, 5, currVol->horSamp_n);/*hor_sampling_factor_n*/
+                status = BitstreamPutBits(stream, 5, currVol->horSamp_m);/*hor_sampling_factor_m*/
+                status = BitstreamPutBits(stream, 5, currVol->verSamp_n);/*vert_sampling_factor_n*/
+                status = BitstreamPutBits(stream, 5, currVol->verSamp_m);/*vert_sampling_factor_m*/
+                status = BitstreamPut1Bits(stream, currVol->enhancementType);/* enhancement_type*/
+            }
+            else /* No Scalability */
+                status = BitstreamPut1Bits(stream, currVol->scalability);/* Scalability = 0 */
+
+            /*temp = */
+            BitstreamMpeg4ByteAlignStuffing(stream); /* Byte align Headers for VOP */
+        }
+    }
+
+    return status;
+}
+
+/* ======================================================================== */
+/*  Function : VOS_End()                                                    */
+/*  Date     : 08/22/2000                                                   */
+/*  Purpose  : Visual Object Sequence End                                   */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+PV_STATUS VOS_End(VideoEncControls *encoderControl)
+{
+    PV_STATUS status = PV_SUCCESS;
+    VideoEncData *video = (VideoEncData *)encoderControl->videoEncoderData;
+    Vol         *currVol = video->vol[video->currLayer];
+    BitstreamEncVideo *stream = currVol->stream;
+
+
+    status = BitstreamPutBits(stream, SESSION_END_CODE, 32);
+
+    return status;
+}
+
+/* ======================================================================== */
+/*  Function : DetermineCodingLayer                                         */
+/*  Date     : 06/02/2001                                                   */
+/*  Purpose  : Find layer to code based on current mod time, assuming that
+               it's time to encode enhanced layer.                          */
+/*  In/out   :                                                              */
+/*  Return   : Number of layer to code.                                     */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+Int DetermineCodingLayer(VideoEncData *video, Int *nLayer, ULong modTime)
+{
+    Vol **vol = video->vol;
+    VideoEncParams *encParams = video->encParams;
+    Int numLayers = encParams->nLayers;
+    UInt modTimeRef = video->modTimeRef;
+    float *LayerFrameRate = encParams->LayerFrameRate;
+    UInt frameNum[4], frameTick;
+    ULong frameModTime, nextFrmModTime;
+#ifdef REDUCE_FRAME_VARIANCE    /* To limit how close 2 frames can be */
+    float frameInterval;
+#endif
+    float srcFrameInterval;
+    Int frameInc;
+    Int i, extra_skip;
+    Int encodeVop = 0;
+
+    i = numLayers - 1;
+
+    if (modTime - video->nextModTime > ((ULong)(-1)) >> 1) /* next time wrapped around */
+        return 0; /* not time to code it yet */
+
+    video->relLayerCodeTime[i] -= 1000;
+    video->nextEncIVop--;  /* number of Vops in highest layer resolution. */
+    video->numVopsInGOP++;
+
+    /* from this point frameModTime and nextFrmModTime are internal */
+
+    frameNum[i] = (UInt)((modTime - modTimeRef) * LayerFrameRate[i] + 500) / 1000;
+    if (video->volInitialize[i])
+    {
+        video->prevFrameNum[i] = frameNum[i] - 1;
+    }
+    else if (frameNum[i] <= video->prevFrameNum[i])
+    {
+        return 0; /* do not encode this frame */
+    }
+
+    /**** this part computes expected next frame *******/
+    frameModTime = (ULong)(((frameNum[i] * 1000) / LayerFrameRate[i]) + modTimeRef + 0.5); /* rec. time */
+    nextFrmModTime = (ULong)((((frameNum[i] + 1) * 1000) / LayerFrameRate[i]) + modTimeRef + 0.5); /* rec. time */
+
+    srcFrameInterval = 1000 / video->FrameRate;
+
+    video->nextModTime = nextFrmModTime - (ULong)(srcFrameInterval / 2.) - 1; /* between current and next frame */
+
+#ifdef REDUCE_FRAME_VARIANCE    /* To limit how close 2 frames can be */
+    frameInterval = 1000 / LayerFrameRate[i]; /* next rec. time */
+    delta = (Int)(frameInterval / 4); /* empirical number */
+    if (video->nextModTime - modTime  < (ULong)delta) /* need to move nextModTime further. */
+    {
+        video->nextModTime += ((delta - video->nextModTime + modTime)); /* empirical formula  */
+    }
+#endif
+    /****************************************************/
+
+    /* map frame no.to tick from modTimeRef */
+    /*frameTick = (frameNum[i]*vol[i]->timeIncrementResolution) ;
+    frameTick = (UInt)((frameTick + (encParams->LayerFrameRate[i]/2))/encParams->LayerFrameRate[i]);*/
+    /*  11/16/01, change frameTick to be the closest tick from the actual modTime */
+    /*  12/12/02, add (double) to prevent large number wrap-around */
+    frameTick = (Int)(((double)(modTime - modTimeRef) * vol[i]->timeIncrementResolution + 500) / 1000);
+
+    /* find timeIncrement to be put in the bitstream */
+    /* refTick is second boundary reference. */
+    vol[i]->timeIncrement = frameTick - video->refTick[i];
+
+
+    vol[i]->moduloTimeBase = 0;
+    while (vol[i]->timeIncrement >= vol[i]->timeIncrementResolution)
+    {
+        vol[i]->timeIncrement -= vol[i]->timeIncrementResolution;
+        vol[i]->moduloTimeBase++;
+        /* do not update refTick and modTimeRef yet, do it after encoding!! */
+    }
+
+    if (video->relLayerCodeTime[i] <= 0)    /* no skipping */
+    {
+        encodeVop = 1;
+        video->currLayer = *nLayer = i;
+        video->relLayerCodeTime[i] += 1000;
+
+        /* takes care of more dropped frame than expected */
+        extra_skip = -1;
+        frameInc = (frameNum[i] - video->prevFrameNum[i]);
+        extra_skip += frameInc;
+
+        if (extra_skip > 0)
+        {   /* update rc->Nr, rc->B, (rc->Rr)*/
+            video->nextEncIVop -= extra_skip;
+            video->numVopsInGOP += extra_skip;
+            if (encParams->RC_Type != CONSTANT_Q)
+            {
+                RC_UpdateBuffer(video, i, extra_skip);
+            }
+        }
+
+    }
+    /* update frame no. */
+    video->prevFrameNum[i] = frameNum[i];
+
+    /* go through all lower layer */
+    for (i = (numLayers - 2); i >= 0; i--)
+    {
+
+        video->relLayerCodeTime[i] -= 1000;
+
+        /* find timeIncrement to be put in the bitstream */
+        vol[i]->timeIncrement = frameTick - video->refTick[i];
+
+        if (video->relLayerCodeTime[i] <= 0) /* time to encode base */
+        {
+            /* 12/27/00 */
+            encodeVop = 1;
+            video->currLayer = *nLayer = i;
+            video->relLayerCodeTime[i] +=
+                (Int)((1000.0 * encParams->LayerFrameRate[numLayers-1]) / encParams->LayerFrameRate[i]);
+
+            vol[i]->moduloTimeBase = 0;
+            while (vol[i]->timeIncrement >= vol[i]->timeIncrementResolution)
+            {
+                vol[i]->timeIncrement -= vol[i]->timeIncrementResolution;
+                vol[i]->moduloTimeBase++;
+                /* do not update refTick and modTimeRef yet, do it after encoding!! */
+            }
+
+            /* takes care of more dropped frame than expected */
+            frameNum[i] = (UInt)((frameModTime - modTimeRef) * encParams->LayerFrameRate[i] + 500) / 1000;
+            if (video->volInitialize[i])
+                video->prevFrameNum[i] = frameNum[i] - 1;
+
+            extra_skip = -1;
+            frameInc = (frameNum[i] - video->prevFrameNum[i]);
+            extra_skip += frameInc;
+
+            if (extra_skip > 0)
+            {   /* update rc->Nr, rc->B, (rc->Rr)*/
+                if (encParams->RC_Type != CONSTANT_Q)
+                {
+                    RC_UpdateBuffer(video, i, extra_skip);
+                }
+            }
+            /* update frame no. */
+            video->prevFrameNum[i] = frameNum[i];
+        }
+    }
+
+#ifdef _PRINT_STAT
+    if (encodeVop)
+        printf(" TI: %d ", vol[*nLayer]->timeIncrement);
+#endif
+
+    return encodeVop;
+}
+
+/* ======================================================================== */
+/*  Function : DetermineVopType                                             */
+/*  Date     : 06/02/2001                                                   */
+/*  Purpose  : The name says it all.                                        */
+/*  In/out   :                                                              */
+/*  Return   : void .                                                       */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+void DetermineVopType(VideoEncData *video, Int currLayer)
+{
+    VideoEncParams *encParams = video->encParams;
+//  Vol *currVol = video->vol[currLayer];
+
+    if (encParams->IntraPeriod == 0) /* I-VOPs only */
+    {
+        if (video->currLayer > 0)
+            video->currVop->predictionType = P_VOP;
+        else
+        {
+            video->currVop->predictionType = I_VOP;
+            if (video->numVopsInGOP >= 132)
+                video->numVopsInGOP = 0;
+        }
+    }
+    else if (encParams->IntraPeriod == -1)  /* IPPPPP... */
+    {
+
+        /* maintain frame type if previous frame is pre-skipped, 06/02/2001 */
+        if (encParams->RC_Type == CONSTANT_Q || video->rc[currLayer]->skip_next_frame != -1)
+            video->currVop->predictionType = P_VOP;
+
+        if (video->currLayer == 0)
+        {
+            if (/*video->numVopsInGOP>=132 || */video->volInitialize[currLayer])
+            {
+                video->currVop->predictionType = I_VOP;
+                video->numVopsInGOP = 0; /* force INTRA update every 132 base frames*/
+                video->nextEncIVop = 1;
+            }
+            else if (video->nextEncIVop == 0 || video->currVop->predictionType == I_VOP)
+            {
+                video->numVopsInGOP = 0;
+                video->nextEncIVop = 1;
+            }
+        }
+    }
+    else   /* IntraPeriod>0 : IPPPPPIPPPPPI... */
+    {
+
+        /* maintain frame type if previous frame is pre-skipped, 06/02/2001 */
+        if (encParams->RC_Type == CONSTANT_Q || video->rc[currLayer]->skip_next_frame != -1)
+            video->currVop->predictionType = P_VOP;
+
+        if (currLayer == 0)
+        {
+            if (video->nextEncIVop <= 0 || video->currVop->predictionType == I_VOP)
+            {
+                video->nextEncIVop = encParams->IntraPeriod;
+                video->currVop->predictionType = I_VOP;
+                video->numVopsInGOP = 0;
+            }
+        }
+    }
+
+    return ;
+}
+
+/* ======================================================================== */
+/*  Function : UpdateSkipNextFrame                                          */
+/*  Date     : 06/02/2001                                                   */
+/*  Purpose  : From rate control frame skipping decision, update timing
+                related parameters.                                         */
+/*  In/out   :                                                              */
+/*  Return   : Current coded layer.                                         */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+Int UpdateSkipNextFrame(VideoEncData *video, ULong *modTime, Int *size, PV_STATUS status)
+{
+    Int currLayer = video->currLayer;
+    Int nLayer = currLayer;
+    VideoEncParams *encParams = video->encParams;
+    Int numLayers = encParams->nLayers;
+    Vol *currVol = video->vol[currLayer];
+    Vol **vol = video->vol;
+    Int num_skip, extra_skip;
+    Int i;
+    UInt newRefTick, deltaModTime;
+    UInt temp;
+
+    if (encParams->RC_Type != CONSTANT_Q)
+    {
+        if (video->volInitialize[0] && currLayer == 0)  /* always encode the first frame */
+        {
+            RC_ResetSkipNextFrame(video, currLayer);
+            //return currLayer;  09/15/05
+        }
+        else
+        {
+            if (RC_GetSkipNextFrame(video, currLayer) < 0 || status == PV_END_OF_BUF)   /* Skip Current Frame */
+            {
+
+#ifdef _PRINT_STAT
+                printf("Skip current frame");
+#endif
+                currVol->moduloTimeBase = currVol->prevModuloTimeBase;
+
+                /*********************/
+                /* prepare to return */
+                /*********************/
+                *size = 0;  /* Set Bitstream buffer to zero */
+
+                /* Determine nLayer and modTime for next encode */
+
+                *modTime = video->nextModTime;
+                nLayer = -1;
+
+                return nLayer; /* return immediately without updating RefTick & modTimeRef */
+                /* If I-VOP was attempted, then ensure next base is I-VOP */
+                /*if((encParams->IntraPeriod>0) && (video->currVop->predictionType == I_VOP))
+                video->nextEncIVop = 0; commented out by 06/05/01 */
+
+            }
+            else if ((num_skip = RC_GetSkipNextFrame(video, currLayer)) > 0)
+            {
+
+#ifdef _PRINT_STAT
+                printf("Skip next %d frames", num_skip);
+#endif
+                /* to keep the Nr of enh layer the same */
+                /* adjust relLayerCodeTime only, do not adjust layerCodeTime[numLayers-1] */
+                extra_skip = 0;
+                for (i = 0; i < currLayer; i++)
+                {
+                    if (video->relLayerCodeTime[i] <= 1000)
+                    {
+                        extra_skip = 1;
+                        break;
+                    }
+                }
+
+                for (i = currLayer; i < numLayers; i++)
+                {
+                    video->relLayerCodeTime[i] += (num_skip + extra_skip) *
+                                                  ((Int)((1000.0 * encParams->LayerFrameRate[numLayers-1]) / encParams->LayerFrameRate[i]));
+                }
+            }
+        }/* first frame */
+    }
+    /*****  current frame is encoded, now update refTick ******/
+
+    video->refTick[currLayer] += vol[currLayer]->prevModuloTimeBase * vol[currLayer]->timeIncrementResolution;
+
+    /* Reset layerCodeTime every I-VOP to prevent overflow */
+    if (currLayer == 0)
+    {
+        /*  12/12/02, fix for weird targer frame rate of 9.99 fps or 3.33 fps */
+        if (((encParams->IntraPeriod != 0) /*&& (video->currVop->predictionType==I_VOP)*/) ||
+                ((encParams->IntraPeriod == 0) && (video->numVopsInGOP == 0)))
+        {
+            newRefTick = video->refTick[0];
+
+            for (i = 1; i < numLayers; i++)
+            {
+                if (video->refTick[i] < newRefTick)
+                    newRefTick = video->refTick[i];
+            }
+
+            /* check to make sure that the update is integer multiple of frame number */
+            /* how many msec elapsed from last modTimeRef */
+            deltaModTime = (newRefTick / vol[0]->timeIncrementResolution) * 1000;
+
+            for (i = numLayers - 1; i >= 0; i--)
+            {
+                temp = (UInt)(deltaModTime * encParams->LayerFrameRate[i]); /* 12/12/02 */
+                if (temp % 1000)
+                    newRefTick = 0;
+
+            }
+            if (newRefTick > 0)
+            {
+                video->modTimeRef += deltaModTime;
+                for (i = numLayers - 1; i >= 0; i--)
+                {
+                    video->prevFrameNum[i] -= (UInt)(deltaModTime * encParams->LayerFrameRate[i]) / 1000;
+                    video->refTick[i] -= newRefTick;
+                }
+            }
+        }
+    }
+
+    *modTime =  video->nextModTime;
+
+    return nLayer;
+}
+
+
+#ifndef ORIGINAL_VERSION
+
+/* ======================================================================== */
+/*  Function : SetProfile_BufferSize                                        */
+/*  Date     : 04/08/2002                                                   */
+/*  Purpose  : Set profile and video buffer size, copied from Jim's code    */
+/*             in PVInitVideoEncoder(.), since we have different places     */
+/*             to reset profile and video buffer size                       */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+Bool SetProfile_BufferSize(VideoEncData *video, float delay, Int bInitialized)
+{
+    Int i, j, start, end;
+//  Int BaseMBsPerSec = 0, EnhMBsPerSec = 0;
+    Int nTotalMB = 0;
+    Int idx, temp_w, temp_h, max = 0, max_width, max_height;
+
+    Int nLayers = video->encParams->nLayers; /* Number of Layers to be encoded */
+
+    Int total_bitrate = 0, base_bitrate;
+    Int total_packet_size = 0, base_packet_size;
+    Int total_MBsPerSec = 0, base_MBsPerSec;
+    Int total_VBV_size = 0, base_VBV_size, enhance_VBV_size = 0;
+    float total_framerate, base_framerate;
+    float upper_bound_ratio;
+    Int bFound = 0;
+    Int k = 0, width16, height16, index;
+    Int lowest_level;
+
+#define MIN_BUFF    16000 /* 16k minimum buffer size */
+#define BUFF_CONST  2.0    /* 2000ms */
+#define UPPER_BOUND_RATIO 8.54 /* upper_bound = 1.4*(1.1+bound/10)*bitrate/framerate */
+
+#define QCIF_WIDTH  176
+#define QCIF_HEIGHT 144
+
+    index = video->encParams->profile_table_index;
+
+    /* Calculate "nTotalMB" */
+    /* Find the maximum width*height for memory allocation of the VOPs */
+    for (idx = 0; idx < nLayers; idx++)
+    {
+        temp_w = video->encParams->LayerWidth[idx];
+        temp_h = video->encParams->LayerHeight[idx];
+
+        if ((temp_w*temp_h) > max)
+        {
+            max = temp_w * temp_h;
+            max_width = temp_w;
+            max_height = temp_h;
+            nTotalMB = ((max_width + 15) >> 4) * ((max_height + 15) >> 4);
+        }
+    }
+    upper_bound_ratio = (video->encParams->RC_Type == CBR_LOWDELAY ? (float)5.0 : (float)UPPER_BOUND_RATIO);
+
+
+    /* Get the basic information: bitrate, packet_size, MBs/s and VBV_size */
+    base_bitrate        = video->encParams->LayerBitRate[0];
+    if (video->encParams->LayerMaxBitRate[0] != 0) /* video->encParams->LayerMaxBitRate[0] == 0 means it has not been set */
+    {
+        base_bitrate    = PV_MAX(base_bitrate, video->encParams->LayerMaxBitRate[0]);
+    }
+    else /* if the max is not set, set it to the specified profile/level */
+    {
+        video->encParams->LayerMaxBitRate[0] = profile_level_max_bitrate[index];
+    }
+
+    base_framerate      = video->encParams->LayerFrameRate[0];
+    if (video->encParams->LayerMaxFrameRate[0] != 0)
+    {
+        base_framerate  = PV_MAX(base_framerate, video->encParams->LayerMaxFrameRate[0]);
+    }
+    else /* if the max is not set, set it to the specified profile/level */
+    {
+        video->encParams->LayerMaxFrameRate[0] = (float)profile_level_max_mbsPerSec[index] / nTotalMB;
+    }
+
+    base_packet_size    = video->encParams->ResyncPacketsize;
+    base_MBsPerSec      = (Int)(base_framerate * nTotalMB);
+    base_VBV_size       = PV_MAX((Int)(base_bitrate * delay),
+                                 (Int)(upper_bound_ratio * base_bitrate / base_framerate));
+    base_VBV_size       = PV_MAX(base_VBV_size, MIN_BUFF);
+
+    /* if the buffer is larger than maximum buffer size, we'll clip it */
+    if (base_VBV_size > profile_level_max_VBV_size[5])
+        base_VBV_size = profile_level_max_VBV_size[5];
+
+
+    /* Check if the buffer exceeds the maximum buffer size given the maximum profile and level */
+    if (nLayers == 1 && base_VBV_size > profile_level_max_VBV_size[index])
+        return FALSE;
+
+
+    if (nLayers == 2)
+    {
+        total_bitrate       = video->encParams->LayerBitRate[1];
+        if (video->encParams->LayerMaxBitRate[1] != 0)
+        {
+            total_bitrate   = PV_MIN(total_bitrate, video->encParams->LayerMaxBitRate[1]);
+        }
+        else /* if the max is not set, set it to the specified profile/level */
+        {
+            video->encParams->LayerMaxBitRate[1] = scalable_profile_level_max_bitrate[index];
+        }
+
+        total_framerate     = video->encParams->LayerFrameRate[1];
+        if (video->encParams->LayerMaxFrameRate[1] != 0)
+        {
+            total_framerate     = PV_MIN(total_framerate, video->encParams->LayerMaxFrameRate[1]);
+        }
+        else /* if the max is not set, set it to the specified profile/level */
+        {
+            video->encParams->LayerMaxFrameRate[1] = (float)scalable_profile_level_max_mbsPerSec[index] / nTotalMB;
+        }
+
+        total_packet_size   = video->encParams->ResyncPacketsize;
+        total_MBsPerSec     = (Int)(total_framerate * nTotalMB);
+
+        enhance_VBV_size    = PV_MAX((Int)((total_bitrate - base_bitrate) * delay),
+                                     (Int)(upper_bound_ratio * (total_bitrate - base_bitrate) / (total_framerate - base_framerate)));
+        enhance_VBV_size    = PV_MAX(enhance_VBV_size, MIN_BUFF);
+
+        total_VBV_size      = base_VBV_size + enhance_VBV_size;
+
+        /* if the buffer is larger than maximum buffer size, we'll clip it */
+        if (total_VBV_size > scalable_profile_level_max_VBV_size[6])
+        {
+            total_VBV_size = scalable_profile_level_max_VBV_size[6];
+            enhance_VBV_size = total_VBV_size - base_VBV_size;
+        }
+
+        /* Check if the buffer exceeds the maximum buffer size given the maximum profile and level */
+        if (total_VBV_size > scalable_profile_level_max_VBV_size[index])
+            return FALSE;
+    }
+
+
+    if (!bInitialized) /* Has been initialized --> profile @ level has been figured out! */
+    {
+        video->encParams->BufferSize[0] = base_VBV_size;
+        if (nLayers > 1)
+            video->encParams->BufferSize[1] = enhance_VBV_size;
+
+        return PV_TRUE;
+    }
+
+
+    /* Profile @ level determination */
+    if (nLayers == 1)
+    {
+        /* BASE ONLY : Simple Profile(SP) Or Core Profile(CP) */
+        if (base_bitrate     > profile_level_max_bitrate[index]     ||
+                base_packet_size > profile_level_max_packet_size[index] ||
+                base_MBsPerSec   > profile_level_max_mbsPerSec[index]   ||
+                base_VBV_size    > profile_level_max_VBV_size[index])
+
+            return PV_FALSE; /* Beyond the bound of Core Profile @ Level2 */
+
+        /* For H263/Short header, determine k*16384 */
+        width16  = ((video->encParams->LayerWidth[0] + 15) >> 4) << 4;
+        height16 = ((video->encParams->LayerHeight[0] + 15) >> 4) << 4;
+        if (video->encParams->H263_Enabled)
+        {
+            k = 4;
+            if (width16  == 2*QCIF_WIDTH && height16 == 2*QCIF_HEIGHT)  /* CIF */
+                k = 16;
+
+            else if (width16  == 4*QCIF_WIDTH && height16 == 4*QCIF_HEIGHT)  /* 4CIF */
+                k = 32;
+
+            else if (width16  == 8*QCIF_WIDTH && height16 == 8*QCIF_HEIGHT)  /* 16CIF */
+                k = 64;
+
+            video->encParams->maxFrameSize  = k * 16384;
+
+            /* Make sure the buffer size is limited to the top profile and level: the Core profile and level 2 */
+            if (base_VBV_size > (Int)(k*16384 + 4*(float)profile_level_max_bitrate[5]*1001.0 / 30000.0))
+                base_VBV_size = (Int)(k * 16384 + 4 * (float)profile_level_max_bitrate[5] * 1001.0 / 30000.0);
+
+            if (base_VBV_size > (Int)(k*16384 + 4*(float)profile_level_max_bitrate[index]*1001.0 / 30000.0))
+                return PV_FALSE;
+        }
+
+        /* Search the appropriate profile@level index */
+        if (!video->encParams->H263_Enabled &&
+                (video->encParams->IntraDCVlcThr != 0 || video->encParams->SearchRange > 16))
+        {
+            lowest_level = 1; /* cannot allow SPL0 */
+        }
+        else
+        {
+            lowest_level = 0; /* SPL0 */
+        }
+
+        for (i = lowest_level; i <= index; i++)
+        {
+            if (i != 4 && /* skip Core Profile@Level1 because the parameters in it are smaller than those in Simple Profile@Level3 */
+                    base_bitrate     <= profile_level_max_bitrate[i]     &&
+                    base_packet_size <= profile_level_max_packet_size[i] &&
+                    base_MBsPerSec   <= profile_level_max_mbsPerSec[i]   &&
+                    base_VBV_size    <= (video->encParams->H263_Enabled ? (Int)(k*16384 + 4*(float)profile_level_max_bitrate[i]*1001.0 / 30000.0) :
+                                         profile_level_max_VBV_size[i]))
+                break;
+        }
+        if (i > index) return PV_FALSE; /* Nothing found!! */
+
+        /* Found out the actual profile @ level : index "i" */
+        if (i == 0)
+        {
+            /* For Simple Profile @ Level 0, we need to do one more check: image size <= QCIF */
+            if (width16 > QCIF_WIDTH || height16 > QCIF_HEIGHT)
+                i = 1; /* image size > QCIF, then set SP level1 */
+        }
+
+        video->encParams->ProfileLevel[0] = profile_level_code[i];
+        video->encParams->BufferSize[0]   = base_VBV_size;
+
+        if (video->encParams->LayerMaxBitRate[0] == 0)
+            video->encParams->LayerMaxBitRate[0] = profile_level_max_bitrate[i];
+
+        if (video->encParams->LayerMaxFrameRate[0] == 0)
+            video->encParams->LayerMaxFrameRate[0] = PV_MIN(30, (float)profile_level_max_mbsPerSec[i] / nTotalMB);
+
+        /* For H263/Short header, one special constraint for VBV buffer size */
+        if (video->encParams->H263_Enabled)
+            video->encParams->BufferSize[0] = (Int)(k * 16384 + 4 * (float)profile_level_max_bitrate[i] * 1001.0 / 30000.0);
+
+    }
+    else
+    {
+        /* SCALABALE MODE: Simple Scalable Profile(SSP) Or Core Scalable Profile(CSP) */
+
+        if (total_bitrate       > scalable_profile_level_max_bitrate[index]     ||
+                total_packet_size   > scalable_profile_level_max_packet_size[index] ||
+                total_MBsPerSec     > scalable_profile_level_max_mbsPerSec[index]   ||
+                total_VBV_size      > scalable_profile_level_max_VBV_size[index])
+
+            return PV_FALSE; /* Beyond given profile and level */
+
+        /* One-time check: Simple Scalable Profile or Core Scalable Profile */
+        if (total_bitrate       <= scalable_profile_level_max_bitrate[2]        &&
+                total_packet_size   <= scalable_profile_level_max_packet_size[2]    &&
+                total_MBsPerSec     <= scalable_profile_level_max_mbsPerSec[2]      &&
+                total_VBV_size      <= scalable_profile_level_max_VBV_size[2])
+
+        {
+            start = 0;
+            end = index;
+        }
+
+        else
+        {
+            start = 4;
+            end = index;
+        }
+
+
+        /* Search the scalable profile */
+        for (i = start; i <= end; i++)
+        {
+            if (total_bitrate       <= scalable_profile_level_max_bitrate[i]     &&
+                    total_packet_size   <= scalable_profile_level_max_packet_size[i] &&
+                    total_MBsPerSec     <= scalable_profile_level_max_mbsPerSec[i]   &&
+                    total_VBV_size      <= scalable_profile_level_max_VBV_size[i])
+
+                break;
+        }
+        if (i > end) return PV_FALSE;
+
+        /* Search the base profile */
+        if (i == 0)
+        {
+            j = 0;
+            bFound = 1;
+        }
+        else        bFound = 0;
+
+        for (j = start; !bFound && j <= i; j++)
+        {
+            if (base_bitrate        <= profile_level_max_bitrate[j]      &&
+                    base_packet_size    <= profile_level_max_packet_size[j]  &&
+                    base_MBsPerSec      <= profile_level_max_mbsPerSec[j]    &&
+                    base_VBV_size       <= profile_level_max_VBV_size[j])
+
+            {
+                bFound = 1;
+                break;
+            }
+        }
+
+        if (!bFound) // && start == 4)
+            return PV_FALSE; /* mis-match in the profiles between base layer and enhancement layer */
+
+        /* j for base layer, i for enhancement layer */
+        video->encParams->ProfileLevel[0] = profile_level_code[j];
+        video->encParams->ProfileLevel[1] = scalable_profile_level_code[i];
+        video->encParams->BufferSize[0]   = base_VBV_size;
+        video->encParams->BufferSize[1]   = enhance_VBV_size;
+
+        if (video->encParams->LayerMaxBitRate[0] == 0)
+            video->encParams->LayerMaxBitRate[0] = profile_level_max_bitrate[j];
+
+        if (video->encParams->LayerMaxBitRate[1] == 0)
+            video->encParams->LayerMaxBitRate[1] = scalable_profile_level_max_bitrate[i];
+
+        if (video->encParams->LayerMaxFrameRate[0] == 0)
+            video->encParams->LayerMaxFrameRate[0] = PV_MIN(30, (float)profile_level_max_mbsPerSec[j] / nTotalMB);
+
+        if (video->encParams->LayerMaxFrameRate[1] == 0)
+            video->encParams->LayerMaxFrameRate[1] = PV_MIN(30, (float)scalable_profile_level_max_mbsPerSec[i] / nTotalMB);
+
+
+    } /* end of: if(nLayers == 1) */
+
+
+    if (!video->encParams->H263_Enabled && (video->encParams->ProfileLevel[0] == 0x08)) /* SPL0 restriction*/
+    {
+        /* PV only allow frame-based rate control, no QP change from one MB to another
+        if(video->encParams->ACDCPrediction == TRUE && MB-based rate control)
+         return PV_FALSE */
+    }
+
+    return PV_TRUE;
+}
+
+#endif /* #ifndef ORIGINAL_VERSION */
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h
new file mode 100644
index 0000000..8293576
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h
@@ -0,0 +1,207 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _MP4ENC_LIB_H_
+#define _MP4ENC_LIB_H_
+
+#include "mp4def.h"     // typedef
+#include "mp4lib_int.h" // main video structure
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /* defined in vop.c */
+    PV_STATUS EncodeVop(VideoEncData *video);
+    PV_STATUS EncodeSlice(VideoEncData *video);
+    PV_STATUS EncodeVideoPacketHeader(VideoEncData *video, int MB_number,
+                                      int quant_scale, Int insert);
+#ifdef ALLOW_VOP_NOT_CODED
+    PV_STATUS EncodeVopNotCoded(VideoEncData *video, UChar *bstream, Int *size, ULong modTime);
+#endif
+
+    /* defined in combined_decode.c */
+    PV_STATUS EncodeFrameCombinedMode(VideoEncData *video);
+    PV_STATUS EncodeSliceCombinedMode(VideoEncData *video);
+
+    /* defined in datapart_decode.c */
+    PV_STATUS EncodeFrameDataPartMode(VideoEncData *video);
+    PV_STATUS EncodeSliceDataPartMode(VideoEncData *video);
+
+    /* defined in fastcodeMB.c */
+
+//void m4v_memset(void *adr_dst, uint8 value, uint32 size);
+
+    PV_STATUS CodeMB_H263(VideoEncData *video, approxDCT *function, Int offsetQP, Int ncoefblck[]);
+#ifndef NO_MPEG_QUANT
+    PV_STATUS CodeMB_MPEG(VideoEncData *video, approxDCT *function, Int offsetQP, Int ncoefblck[]);
+#endif
+    Int getBlockSAV(Short block[]);
+    Int Sad8x8(UChar *rec, UChar *prev, Int lx);
+    Int getBlockSum(UChar *rec, Int lx);
+
+    /* defined in dct.c */
+    void  blockIdct(Short *block);
+    void blockIdct_SSE(Short *input);
+    void BlockDCTEnc(Short *blockData, Short *blockCoeff);
+
+    /*---- FastQuant.c -----*/
+    Int cal_dc_scalerENC(Int QP, Int type) ;
+    Int BlockQuantDequantH263Inter(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+                                   UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                                   Int dctMode, Int comp, Int dummy, UChar shortHeader);
+
+    Int BlockQuantDequantH263Intra(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+                                   UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                                   Int dctMode, Int comp, Int dc_scaler, UChar shortHeader);
+
+    Int BlockQuantDequantH263DCInter(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+                                     UChar *bitmaprow, UInt *bitmapzz, Int dummy, UChar shortHeader);
+
+    Int BlockQuantDequantH263DCIntra(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+                                     UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler, UChar shortHeader);
+
+#ifndef NO_MPEG_QUANT
+    Int BlockQuantDequantMPEGInter(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+                                   UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                                   Int DctMode, Int comp, Int dc_scaler);
+
+    Int BlockQuantDequantMPEGIntra(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+                                   UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+                                   Int DctMode, Int comp, Int dc_scaler);
+
+    Int BlockQuantDequantMPEGDCInter(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+                                     UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dummy);
+
+    Int BlockQuantDequantMPEGDCIntra(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+                                     UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler);
+#endif
+
+    /*---- FastIDCT.c -----*/
+    void BlockIDCTMotionComp(Short *block, UChar *bitmapcol, UChar bitmaprow,
+                             Int dctMode, UChar *rec, UChar *prev, Int lx_intra_zeroMV);
+
+
+    /* defined in motion_comp.c */
+    void getMotionCompensatedMB(VideoEncData *video, Int ind_x, Int ind_y, Int offset);
+    void EncPrediction_INTER(Int xpred, Int ypred, UChar *c_prev, UChar *c_rec,
+                             Int width, Int round1);
+
+    void EncPrediction_INTER4V(Int xpred, Int ypred, MOT *mot, UChar *c_prev, UChar *c_rec,
+                               Int width, Int round1);
+
+    void EncPrediction_Chrom(Int xpred, Int ypred, UChar *cu_prev, UChar *cv_prev, UChar *cu_rec,
+                             UChar *cv_rec, Int pitch_uv, Int width_uv, Int height_uv, Int round1);
+
+    void get_MB(UChar *c_prev, UChar *c_prev_u  , UChar *c_prev_v,
+                Short mb[6][64], Int width, Int width_uv);
+
+    void PutSkippedBlock(UChar *rec, UChar *prev, Int lx);
+
+    /* defined in motion_est.c */
+    void MotionEstimation(VideoEncData *video);
+#ifdef HTFM
+    void InitHTFM(VideoEncData *video, HTFM_Stat *htfm_stat, double *newvar, Int *collect);
+    void UpdateHTFM(VideoEncData *video, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat);
+#endif
+
+    /* defined in ME_utils.c */
+    void ChooseMode_C(UChar *Mode, UChar *cur, Int lx, Int min_SAD);
+    void ChooseMode_MMX(UChar *Mode, UChar *cur, Int lx, Int min_SAD);
+    void GetHalfPelMBRegion_C(UChar *cand, UChar *hmem, Int lx);
+    void GetHalfPelMBRegion_SSE(UChar *cand, UChar *hmem, Int lx);
+    void GetHalfPelBlkRegion(UChar *cand, UChar *hmem, Int lx);
+    void PaddingEdge(Vop *padVop);
+    void ComputeMBSum_C(UChar *cur, Int lx, MOT *mot_mb);
+    void ComputeMBSum_MMX(UChar *cur, Int lx, MOT *mot_mb);
+    void ComputeMBSum_SSE(UChar *cur, Int lx, MOT *mot_mb);
+    void GetHalfPelMBRegionPadding(UChar *ncand, UChar *hmem, Int lx, Int *reptl);
+    void GetHalfPelBlkRegionPadding(UChar *ncand, UChar *hmem, Int lx, Int *reptl);
+
+    /* defined in findhalfpel.c */
+    void FindHalfPelMB(VideoEncData *video, UChar *cur, MOT *mot, UChar *ncand,
+                       Int xpos, Int ypos, Int *xhmin, Int *yhmin, Int hp_guess);
+    Int  FindHalfPelBlk(VideoEncData *video, UChar *cur, MOT *mot, Int sad16, UChar *ncand8[],
+                        UChar *mode, Int xpos, Int ypos, Int *xhmin, Int *yhmin, UChar *hp_mem);
+
+
+    /* defined in sad.c */
+    Int SAD_MB_HalfPel_Cxhyh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_MB_HalfPel_Cyh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_MB_HalfPel_Cxh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_MB_HalfPel_MMX(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_MB_HalfPel_SSE(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_Blk_HalfPel_C(UChar *ref, UChar *blk, Int dmin, Int lx, Int rx, Int xh, Int yh, void *extra_info);
+    Int SAD_Blk_HalfPel_MMX(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+    Int SAD_Blk_HalfPel_SSE(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+    Int SAD_Macroblock_C(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_Macroblock_MMX(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_Macroblock_SSE(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_Block_C(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+    Int SAD_Block_MMX(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+    Int SAD_Block_SSE(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+
+#ifdef HTFM /* Hypothesis Testing Fast Matching */
+    Int SAD_MB_HP_HTFM_Collectxhyh(UChar *ref, UChar *blk, Int dmin_x, void *extra_info);
+    Int SAD_MB_HP_HTFM_Collectyh(UChar *ref, UChar *blk, Int dmin_x, void *extra_info);
+    Int SAD_MB_HP_HTFM_Collectxh(UChar *ref, UChar *blk, Int dmin_x, void *extra_info);
+    Int SAD_MB_HP_HTFMxhyh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_MB_HP_HTFMyh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_MB_HP_HTFMxh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_MB_HTFM_Collect(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int SAD_MB_HTFM(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+#endif
+    /* on-the-fly padding */
+    Int SAD_Blk_PADDING(UChar *ref, UChar *cur, Int dmin, Int lx, void *extra_info);
+    Int SAD_MB_PADDING(UChar *ref, UChar *cur, Int dmin, Int lx, void *extra_info);
+#ifdef HTFM
+    Int SAD_MB_PADDING_HTFM_Collect(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+    Int SAD_MB_PADDING_HTFM(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+#endif
+
+    /* defined in rate_control.c */
+    /* These are APIs to rate control exposed to core encoder module. */
+    PV_STATUS RC_Initialize(void *video);
+    PV_STATUS RC_VopQPSetting(VideoEncData *video, rateControl *rc[]);
+    PV_STATUS RC_VopUpdateStat(VideoEncData *video, rateControl *rc);
+    PV_STATUS RC_MBQPSetting(VideoEncData *video, rateControl *rc, Int start_packet_header);
+    PV_STATUS RC_MBUpdateStat(VideoEncData *video, rateControl *rc, Int Bi, Int Hi);
+    PV_STATUS RC_Cleanup(rateControl *rc[], Int numLayers);
+
+    Int       RC_GetSkipNextFrame(VideoEncData *video, Int currLayer);
+    Int       RC_GetRemainingVops(VideoEncData *video, Int currLayer);
+    void      RC_ResetSkipNextFrame(VideoEncData *video, Int currLayer);
+    PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip);
+    PV_STATUS RC_UpdateBXRCParams(void *input);
+
+
+    /* defined in vlc_encode.c */
+    void MBVlcEncodeDataPar_I_VOP(VideoEncData *video, Int ncoefblck[], void *blkCodePtr);
+    void MBVlcEncodeDataPar_P_VOP(VideoEncData *video, Int ncoefblck[], void *blkCodePtr);
+    void MBVlcEncodeCombined_I_VOP(VideoEncData *video, Int ncoefblck[], void *blkCodePtr);
+    void MBVlcEncodeCombined_P_VOP(VideoEncData *video, Int ncoefblck[], void *blkCodePtr);
+    void BlockCodeCoeff_ShortHeader(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode);
+    void BlockCodeCoeff_RVLC(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode);
+    void BlockCodeCoeff_Normal(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MP4ENC_LIB_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h b/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h
new file mode 100644
index 0000000..3bc9421
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h
@@ -0,0 +1,472 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _MP4LIB_INT_H_
+#define _MP4LIB_INT_H_
+
+#include "mp4def.h"
+#include "mp4enc_api.h"
+#include "rate_control.h"
+
+/* BitstreamEncVideo will be modified */
+typedef struct tagBitstream
+{
+    Int(*writeVideoPacket)(UChar *buf, Int nbytes_required);   /*write video packet out */
+    UChar *bitstreamBuffer; /*buffer to hold one video packet*/
+    Int bufferSize; /*total bitstream buffer size in bytes */
+    Int byteCount;  /*how many bytes already encoded*/
+    UInt word;      /*hold one word temporarily */
+    Int bitLeft;    /*number of bits left in "word" */
+    UChar* overrunBuffer;  /* pointer to overrun buffer */
+    Int oBSize;     /* length of overrun buffer */
+    struct tagVideoEncData *video;
+} BitstreamEncVideo;
+
+typedef struct tagVOP
+{
+    PIXEL   *yChan;             /* The Y component */
+    PIXEL   *uChan;             /* The U component */
+    PIXEL   *vChan;             /* The V component */
+    Int     frame;              /* frame number */
+    Int     volID;              /* Layer number */
+    //Int       timeStamp;          /* Vop TimeStamp in msec */
+
+    /* Syntax elements copied from VOL (standard) */
+    Int     width;              /* Width (multiple of 16) */
+    Int     height;             /* Height (multiple of 16) */
+    Int     pitch;              /* Pitch (differs from width for UMV case) */
+    Int     padded;     /* flag whether this frame has been padded */
+
+    /* Actual syntax elements for VOP (standard) */
+    Int     predictionType;     /* VOP prediction type */
+    Int     timeInc;            /* VOP time increment (relative to last mtb) */
+    Int     vopCoded;
+    Int     roundingType;
+    Int     intraDCVlcThr;
+    Int     quantizer;          /* VOP quantizer */
+    Int     fcodeForward;       /* VOP dynamic range of motion vectors */
+    Int     fcodeBackward;      /* VOP dynamic range of motion vectors */
+    Int     refSelectCode;      /* enhancement layer reference select code */
+
+    /* H.263 parameters */
+    Int     gobNumber;
+    Int     gobFrameID;
+    Int     temporalRef;        /* temporal reference, roll over at 256 */
+    Int     temporalInterval;   /* increase every 256 temporalRef */
+
+} Vop;
+
+typedef struct tagVol
+{
+    Int     volID;              /* VOL identifier (for tracking) */
+    Int     shortVideoHeader;   /* shortVideoHeader mode */
+    Int     GOVStart;           /* Insert GOV Header */
+    Int     timeIncrementResolution;    /* VOL time increment */
+    Int     nbitsTimeIncRes;    /* number of bits for time increment */
+    Int     timeIncrement;      /* time increment */
+    Int     moduloTimeBase;     /* internal decoder clock */
+    Int     prevModuloTimeBase; /* in case of pre-frameskip */
+
+    Int     fixedVopRate;
+    BitstreamEncVideo  *stream; /* library bitstream buffer (input buffer) */
+
+    /* VOL Dimensions */
+    Int     width;              /* Width */
+    Int     height;             /* Height */
+
+    /* Error Resilience Flags */
+    Int     ResyncMarkerDisable; /* VOL Disable Resynch Markers */
+    Int     useReverseVLC;      /* VOL reversible VLCs */
+    Int     dataPartitioning;   /* VOL data partitioning */
+
+    /* Quantization related parameters */
+    Int     quantPrecision;     /* Quantizer precision */
+    Int     quantType;          /* MPEG-4 or H.263 Quantization Type */
+
+    /* Added loaded quant mat, 05/22/2000 */
+    Int     loadIntraQuantMat;      /* Load intra quantization matrix */
+    Int     loadNonIntraQuantMat;   /* Load nonintra quantization matrix */
+    Int     iqmat[64];          /* Intra quant.matrix */
+    Int     niqmat[64];         /* Non-intra quant.matrix */
+
+
+    /* Parameters used for scalability */
+    Int     scalability;        /* VOL scalability (flag) */
+    Int     scalType;           /* temporal = 0, spatial = 1, both = 2 */
+
+    Int     refVolID;           /* VOL id of reference VOL */
+    Int     refSampDir;         /* VOL resol. of ref. VOL */
+    Int     horSamp_n;          /* VOL hor. resampling of ref. VOL given by */
+    Int     horSamp_m;          /* sampfac = hor_samp_n/hor_samp_m      */
+    Int     verSamp_n;          /* VOL ver. resampling of ref. VOL given by */
+    Int     verSamp_m;          /* sampfac = ver_samp_n/ver_samp_m      */
+    Int     enhancementType;    /* VOL type of enhancement layer */
+
+    /* These variables were added since they are used a lot. */
+    Int     nMBPerRow, nMBPerCol;   /* number of MBs in each row & column    */
+    Int     nTotalMB;
+    Int     nBitsForMBID;           /* how many bits required for MB number? */
+
+    /* for short video header */
+    Int     nMBinGOB;           /* number of MBs in GOB, 05/22/00 */
+    Int     nGOBinVop;          /* number of GOB in Vop  05/22/00 */
+} Vol;
+
+typedef struct tagMacroBlock
+{
+    Int     mb_x;               /* X coordinate */
+    Int     mb_y;               /* Y coordinate */
+    Short   block[9][64];       /* 4-Y, U and V blocks , and AAN Scale*/
+} MacroBlock;
+
+typedef struct tagRunLevelBlock
+{
+    Int run[64];        /* Runlength */
+    Int level[64];      /* Abs(level) */
+    Int s[64];          /* sign level */
+} RunLevelBlock;
+
+typedef struct tagHeaderInfoDecVideo
+{
+    UChar       *Mode;              /* Modes INTRA/INTER/etc. */
+    UChar       *CBP;               /* MCBPC/CBPY stuff */
+} HeaderInfoEncVideo;
+
+typedef Short typeDCStore[6];   /* ACDC */
+typedef Short typeDCACStore[4][8];
+
+typedef struct tagMOT
+{
+    Int x;  /* half-pel resolution x component */
+    Int y;      /* half-pel resolution y component */
+    Int sad;  /* SAD */
+} MOT;
+
+typedef struct tagHintTrackInfo
+{
+    UChar MTB;
+    UChar LayerID;
+    UChar CodeType;
+    UChar RefSelCode;
+
+} HintTrackInfo;
+
+
+typedef struct tagVideoEncParams
+{
+    //Int       Width;                  /* Input Width */
+    //Int       Height;                 /* Input Height */
+    //float FrameRate;              /* Input Frame Rate */
+    UInt    TimeIncrementRes;       /* timeIncrementRes */
+
+    /*VOL Parameters */
+    Int     nLayers;
+    Int     LayerWidth[4];          /* Encoded Width */
+    Int     LayerHeight[4];         /* Encoded Height */
+    float   LayerFrameRate[4];      /* Encoded Frame Rate */
+    Int     LayerBitRate[4];        /* Encoded BitRate */
+    Int     LayerMaxBitRate[4];     /* Maximum Encoded BitRate */
+    float   LayerMaxFrameRate[4];   /* Maximum Encoded Frame Rate */
+    Int     LayerMaxMbsPerSec[4];   /* Maximum mbs per second, according to the specified profile and level */
+    Int     LayerMaxBufferSize[4];  /* Maximum buffer size, according to the specified profile and level */
+
+    Bool    ResyncMarkerDisable;    /* Disable Resync Marker */
+    Bool    DataPartitioning;       /* Base Layer Data Partitioning */
+    Bool    ReversibleVLC;          /* RVLC when Data Partitioning */
+    Bool    ACDCPrediction;         /* AC/DC Prediction    */
+    Int     QuantType[4];           /* H263, MPEG2 */
+    Int     InitQuantBvop[4];
+    Int     InitQuantPvop[4];
+    Int     InitQuantIvop[4];
+    Int     ResyncPacketsize;
+
+    Int     RoundingType;
+    Int     IntraDCVlcThr;
+
+    /* Rate Control Parameters */
+    MP4RateControlType  RC_Type;        /*Constant Q, M4 constantRate, VM5+, M4RC,MPEG2TM5 */
+
+    /* Intra Refresh Parameters */
+    Int     IntraPeriod;            /* Intra update period */
+    Int     Refresh;                /* Number of MBs refresh in each frame */
+    /* Other Parameters */
+    Bool    SceneChange_Det;        /* scene change detection */
+    Bool    FineFrameSkip_Enabled;  /* src rate resolution frame skipping */
+    Bool    VBR_Enabled;            /* VBR rate control */
+    Bool    NoFrameSkip_Enabled;    /* do not allow frame skip */
+    Bool    NoPreSkip_Enabled;      /* do not allow pre-skip */
+
+    Bool    H263_Enabled;           /* H263 Short Header */
+    Bool    GOV_Enabled;            /* GOV Header Enabled */
+    Bool    SequenceStartCode;      /* This probably should be removed */
+    Bool    FullSearch_Enabled;     /* full-pel exhaustive search motion estimation */
+    Bool    HalfPel_Enabled;        /* Turn Halfpel ME on or off */
+    Bool    MV8x8_Enabled;          /* Enable 8x8 motion vectors */
+    Bool    RD_opt_Enabled;         /* Enable operational R-D optimization */
+    Int     GOB_Header_Interval;        /* Enable encoding GOB header in H263_WITH_ERR_RES and SHORT_HERDER_WITH_ERR_RES */
+    Int     SearchRange;            /* Search range for 16x16 motion vector */
+    Int     MemoryUsage;            /* Amount of memory allocated */
+    Int     GetVolHeader[2];        /* Flag to check if Vol Header has been retrieved */
+    Int     BufferSize[2];          /* Buffer Size for Base and Enhance Layers */
+    Int     ProfileLevel[2];        /* Profile and Level for encoding purposes */
+    float   VBV_delay;              /* VBV buffer size in the form of delay */
+    Int     maxFrameSize;           /* maximum frame size(bits) for H263/Short header mode, k*16384 */
+    Int     profile_table_index;    /* index for profile and level tables given the specified profile and level */
+
+} VideoEncParams;
+
+/* platform dependent functions */
+typedef struct tagFuncPtr
+{
+//  Int (*SAD_MB_HalfPel)(UChar *ref,UChar *blk,Int dmin_lx,Int xh,Int yh,void *extra_info);
+    Int(*SAD_MB_HalfPel[4])(UChar*, UChar*, Int, void *);
+    Int(*SAD_Blk_HalfPel)(UChar *ref, UChar *blk, Int dmin, Int lx, Int rx, Int xh, Int yh, void *extra_info);
+    Int(*SAD_Macroblock)(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+    Int(*SAD_Block)(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+    Int(*SAD_MB_PADDING)(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info); /*, 4/21/01 */
+    void (*ComputeMBSum)(UChar *cur, Int lx, MOT *mot_mb);
+    void (*ChooseMode)(UChar *Mode, UChar *cur, Int lx, Int min_SAD);
+    void (*GetHalfPelMBRegion)(UChar *cand, UChar *hmem, Int lx);
+    void (*blockIdct)(Int *block);
+
+
+} FuncPtr;
+
+/* 04/09/01, for multipass rate control */
+
+typedef struct tagRDInfo
+{
+    Int QP;
+    Int actual_bits;
+    float mad;
+    float R_D;
+} RDInfo;
+
+typedef struct tagMultiPass
+{
+    /* multipass rate control data */
+    Int target_bits;    /* target bits for current frame, = rc->T */
+    Int actual_bits;    /* actual bits for current frame obtained after encoding, = rc->Rc*/
+    Int QP;             /* quantization level for current frame, = rc->Qc*/
+    Int prev_QP;        /* quantization level for previous frame */
+    Int prev_prev_QP;   /* quantization level for previous frame before last*/
+    float mad;          /* mad for current frame, = video->avgMAD*/
+    Int bitrate;        /* bitrate for current frame */
+    float framerate;    /* framerate for current frame*/
+
+    Int nRe_Quantized;  /* control variable for multipass encoding, */
+    /* 0 : first pass */
+    /* 1 : intermediate pass(quantization and VLC loop only) */
+    /* 2 : final pass(de-quantization, idct, etc) */
+    /* 3 : macroblock level rate control */
+
+    Int encoded_frames;     /* counter for all encoded frames */
+    Int re_encoded_frames;  /* counter for all multipass encoded frames*/
+    Int re_encoded_times;   /* counter for all times of multipass frame encoding */
+
+    /* Multiple frame prediction*/
+    RDInfo **pRDSamples;        /* pRDSamples[30][32], 30->30fps, 32 -> 5 bit quantizer, 32 candidates*/
+    Int framePos;               /* specific position in previous multiple frames*/
+    Int frameRange;             /* number of overall previous multiple frames */
+    Int samplesPerFrame[30];    /* number of samples per frame, 30->30fps */
+
+    /* Bit allocation for scene change frames and high motion frames */
+    float sum_mad;
+    Int counter_BTsrc;  /* BT = Bit Transfer, bit transfer from low motion frames or less complicatedly compressed frames */
+    Int counter_BTdst;  /* BT = Bit Transfer, bit transfer to scene change frames or high motion frames or more complicatedly compressed frames */
+    float sum_QP;
+    Int diff_counter;   /* diff_counter = -diff_counter_BTdst, or diff_counter_BTsrc */
+
+    /* For target bitrate or framerate update */
+    float target_bits_per_frame;        /* = C = bitrate/framerate */
+    float target_bits_per_frame_prev;   /* previous C */
+    float aver_mad;                     /* so-far average mad could replace sum_mad */
+    float aver_mad_prev;                /* previous average mad */
+    Int   overlapped_win_size;          /* transition period of time */
+    Int   encoded_frames_prev;          /* previous encoded_frames */
+} MultiPass;
+
+/* End */
+
+#ifdef HTFM
+typedef struct tagHTFM_Stat
+{
+    Int abs_dif_mad_avg;
+    UInt countbreak;
+    Int offsetArray[16];
+    Int offsetRef[16];
+} HTFM_Stat;
+#endif
+
+/* Global structure that can be passed around */
+typedef struct tagVideoEncData
+{
+    /* VOL Header Initialization */
+    UChar   volInitialize[4];       /* Used to Write VOL Headers */
+    /* Data For Layers (Scalability) */
+    Int     numberOfLayers;     /* Number of Layers */
+    Vol     **vol;              /* Data stored for each VOL */
+
+    /* Data used for encoding frames */
+    VideoEncFrameIO *input;     /* original input frame */
+    Vop     *currVop;           /* Current reconstructed VOP */
+    Vop     *prevBaseVop;       /* Previous reference Base Vop */
+    Vop     *nextBaseVop;       /* Next reference Base Vop */
+    Vop     *prevEnhanceVop;/* Previous Enhancement Layer Vop */
+    Vop     *forwardRefVop;     /* Forward Reference VOP */
+    Vop     *backwardRefVop;    /* Backward Reference VOP */
+
+    /* scratch memory */
+    BitstreamEncVideo  *bitstream1; /* Used for data partitioning */
+    BitstreamEncVideo  *bitstream2; /* and combined modes as      */
+    BitstreamEncVideo  *bitstream3; /* intermediate storages      */
+
+    UChar   *overrunBuffer;  /* extra output buffer to prevent current skip due to output buffer overrun*/
+    Int     oBSize;     /* size of allocated overrun buffer */
+
+    Int dc_scalar_1;            /*dc scalar for Y block */
+    Int dc_scalar_2;            /*dc scalar for U, V block*/
+
+    /* Annex L Rate Control */
+    rateControl     *rc[4];         /* Pointer to Rate Control structure*/
+    /* 12/25/00, each R.C. for each layer */
+
+    /********* motion compensation related variables ****************/
+    MOT     **mot;              /* Motion vectors */
+    /*  where [mbnum][0] = 1MV.
+        [mbnum][1...4] = 4MVs
+        [mbnum][5] = backward MV.
+        [mbnum][6] = delta MV for direct mode.
+        [mbnum][7] = nothing yet. */
+    UChar   *intraArray;            /* Intra Update Arrary */
+    float   sumMAD;             /* SAD/MAD for frame */
+
+    /* to speedup the SAD calculation */
+    void *sad_extra_info;
+#ifdef HTFM
+    Int nrmlz_th[48];       /* Threshold for fast SAD calculation using HTFM */
+    HTFM_Stat htfm_stat;    /* For statistics collection */
+#endif
+
+    /*Tao 04/09/00  For DCT routine */
+    UChar currYMB[256];     /* interleaved current macroblock in HTFM order */
+    MacroBlock  *outputMB;          /* Output MB to VLC encode */
+    UChar   predictedMB[384];   /* scrath memory for predicted value */
+    RunLevelBlock RLB[6];       /* Run and Level of coefficients! */
+    Short   dataBlock[128];     /* DCT block data before and after quant/dequant*/
+
+    UChar   bitmaprow[8];       /* Need to keep it for ACDCPrediction, 8 bytes for alignment, need only 6 */
+    UChar   bitmapcol[6][8];
+    UInt    bitmapzz[6][2]; /* for zigzag bitmap */
+    Int     zeroMV;         /* flag for zero MV */
+
+    Int     usePrevQP;      /* flag for intraDCVlcThreshold switch decision */
+    Int     QP_prev;            /* use for DQUANT calculation */
+    Int     *acPredFlag;        /* */
+    typeDCStore     *predDC;        /* The DC coeffs for each MB */
+    typeDCACStore   *predDCAC_row;
+    typeDCACStore   *predDCAC_col;
+
+
+    UChar   *sliceNo;           /* Slice Number for each MB */
+
+    Int     header_bits;        /* header bits in frmae */
+    HeaderInfoEncVideo  headerInfo; /* MB Header information */
+    UChar   zz_direction;       /* direction of zigzag scan */
+    UChar   *QPMB;              /* Quantizer value for each MB */
+
+    /* Miscellaneous data points to be passed */
+    float   FrameRate;          /* Src frame Rate */
+
+    ULong   nextModTime;        /* expected next frame time */
+    UInt    prevFrameNum[4];    /* previous frame number starting from modTimeRef */
+    UInt    modTimeRef;     /* Reference modTime update every I-Vop*/
+    UInt    refTick[4];         /* second aligned referenc tick */
+    Int     relLayerCodeTime[4];/* Next coding time for each Layer relative to highest layer */
+
+    ULong   modTime;            /* Input frame modTime */
+    Int     currLayer;          /* Current frame layer  */
+    Int     mbnum;              /*  Macroblock number */
+
+    /* slice coding, state variables */
+    Vop     *tempForwRefVop;
+    Int     tempRefSelCode;
+    Int     end_of_buf;         /* end of bitstream buffer flag */
+    Int     slice_coding;       /* flag for slice based coding */
+    Int     totalSAD;           /* So far total SAD for a frame */
+    Int     numIntra;           /* So far number of Intra MB */
+    Int     offset;             /* So far MB offset */
+    Int     ind_x, ind_y;       /* So far MB coordinate */
+    Int     collect;
+    Int     hp_guess;
+    /*********************************/
+
+    HintTrackInfo hintTrackInfo;    /* hintTrackInfo */
+    /* IntraPeriod, Timestamp, etc. */
+    float       nextEncIVop;    /* counter til the next I-Vop */
+    float       numVopsInGOP;   /* value at the beginning of nextEncIVop */
+
+    /* platform dependent functions */
+    FuncPtr     *functionPointer;   /* structure containing platform dependent functions */
+
+    /* Application controls */
+    VideoEncControls    *videoEncControls;
+    VideoEncParams      *encParams;
+
+    MultiPass *pMP[4]; /* for multipass encoding, 4 represents 4 layer encoding */
+
+} VideoEncData;
+
+/*************************************************************/
+/*                  VLC structures                           */
+/*************************************************************/
+
+typedef struct tagVLCtable
+{
+    unsigned int code; /* right justified */
+    int len;
+} VLCtable, *LPVLCtable;
+
+
+/*************************************************************/
+/*                  Approx DCT                               */
+/*************************************************************/
+typedef struct struct_approxDCT  approxDCT;
+struct struct_approxDCT
+{
+    Void(*BlockDCT8x8)(Int *, Int *, UChar *, UChar *, Int, Int);
+    Void(*BlockDCT8x8Intra)(Int *, Int *, UChar *, UChar *, Int, Int);
+    Void(*BlockDCT8x8wSub)(Int *, Int *, UChar *, UChar *, Int, Int);
+};
+
+/*************************************************************/
+/*                  QP structure                             */
+/*************************************************************/
+
+struct QPstruct
+{
+    Int QPx2 ;
+    Int QP;
+    Int QPdiv2;
+    Int QPx2plus;
+    Int Addition;
+};
+
+
+#endif /* _MP4LIB_INT_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
new file mode 100644
index 0000000..53149c1
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
@@ -0,0 +1,885 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "rate_control.h"
+#include "mp4enc_lib.h"
+#include "bitstream_io.h"
+#include "m4venc_oscl.h"
+
+void targetBitCalculation(void *input);
+void calculateQuantizer_Multipass(void *video);
+void updateRateControl(rateControl *rc, VideoEncData *video);
+void updateRC_PostProc(rateControl *rc, VideoEncData *video);
+
+/***************************************************************************
+**************  RC APIs to core encoding modules  *******************
+
+PV_STATUS RC_Initialize(void *video);
+PV_STATUS RC_Cleanup(rateControl *rc[],Int numLayers);
+PV_STATUS RC_VopQPSetting(VideoEncData *video,rateControl *rc[]);
+PV_STATUS RC_VopUpdateStat(VideoEncData *video,rateControl *rc[]);
+PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip);
+Int       RC_GetSkipNextFrame(VideoEncData *video,Int currLayer);
+void      RC_ResetSkipNextFrame(void *video,Int currLayer);
+
+PV_STATUS RC_UpdateBXRCParams(void *input);  Parameters update for target bitrate or framerate change
+
+****************************************************************************/
+
+
+/************************************************************************/
+/************ API part **************************************************/
+/* must be called before each sequence*/
+
+PV_STATUS RC_Initialize(void *input)
+{
+    VideoEncData *video = (VideoEncData *) input;
+    VideoEncParams *encParams = video->encParams;
+    rateControl **rc = video->rc;
+    Int numLayers = encParams->nLayers;
+    Int *LayerBitRate = encParams->LayerBitRate;
+    float *LayerFrameRate = encParams->LayerFrameRate;
+    MultiPass **pMP = video->pMP;
+
+    Int n;
+
+    for (n = 0; n < numLayers; n++)
+    {
+        /* rate control */
+        rc[n]->fine_frame_skip = encParams->FineFrameSkip_Enabled;
+        rc[n]->no_frame_skip = encParams->NoFrameSkip_Enabled;
+        rc[n]->no_pre_skip = encParams->NoPreSkip_Enabled;
+        rc[n]->skip_next_frame = 0; /* must be initialized */
+
+        //rc[n]->TMN_TH = (Int)((float)LayerBitRate[n]/LayerFrameRate[n]);
+        rc[n]->Bs = video->encParams->BufferSize[n];
+        rc[n]->TMN_W = 0;
+        rc[n]->VBV_fullness = (Int)(rc[n]->Bs * 0.5); /* rc[n]->Bs */
+        rc[n]->encoded_frames = 0;
+        rc[n]->framerate = LayerFrameRate[n];
+        if (n == 0)
+        {
+            rc[n]->TMN_TH = (Int)((float)LayerBitRate[n] / LayerFrameRate[n]);
+            rc[n]->bitrate = LayerBitRate[n];
+            rc[n]->framerate = LayerFrameRate[n];
+
+            // For h263 or short header mode, the bit variation is within (-2*Rmax*1001/3000, 2*Rmax*1001/3000)
+            if (video->encParams->H263_Enabled)
+            {
+                rc[n]->max_BitVariance_num = (Int)((rc[n]->Bs - video->encParams->maxFrameSize) / 2 / (rc[n]->bitrate / rc[n]->framerate / 10.0)) - 5;
+                if (rc[n]->max_BitVariance_num < 0) rc[n]->max_BitVariance_num += 5;
+            }
+            else   // MPEG-4 normal modes
+            {
+                rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - rc[n]->VBV_fullness) / ((float)LayerBitRate[n] / LayerFrameRate[n] / 10.0)) - 5;
+                if (rc[n]->max_BitVariance_num < 0) rc[n]->max_BitVariance_num += 5;
+            }
+        }
+        else
+        {
+            if (LayerFrameRate[n] - LayerFrameRate[n-1] > 0) /*  7/31/03 */
+            {
+                rc[n]->TMN_TH = (Int)((float)(LayerBitRate[n] - LayerBitRate[n-1]) / (LayerFrameRate[n] - LayerFrameRate[n-1]));
+                rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - rc[n]->VBV_fullness) * 10 / ((float)rc[n]->TMN_TH)) - 5;
+                if (rc[n]->max_BitVariance_num < 0) rc[n]->max_BitVariance_num += 5;
+            }
+            else   /*  7/31/03 */
+            {
+                rc[n]->TMN_TH = 1 << 30;
+                rc[n]->max_BitVariance_num = 0;
+            }
+            rc[n]->bitrate = LayerBitRate[n] - LayerBitRate[n-1];
+            rc[n]->framerate = LayerFrameRate[n] - LayerFrameRate[n-1];
+        }
+
+        // Set the initial buffer fullness
+        if (1) //!video->encParams->H263_Enabled)  { // MPEG-4
+        {
+            /* According to the spec, the initial buffer fullness needs to be set to 1/3 */
+            rc[n]->VBV_fullness = (Int)(rc[n]->Bs / 3.0 - rc[n]->Bs / 2.0); /* the buffer range is [-Bs/2, Bs/2] */
+            pMP[n]->counter_BTsrc = (Int)((rc[n]->Bs / 2.0 - rc[n]->Bs / 3.0) / (rc[n]->bitrate / rc[n]->framerate / 10.0));
+            rc[n]->TMN_W = (Int)(rc[n]->VBV_fullness + pMP[n]->counter_BTsrc * (rc[n]->bitrate / rc[n]->framerate / 10.0));
+
+            rc[n]->low_bound = -rc[n]->Bs / 2;
+            rc[n]-> VBV_fullness_offset = 0;
+        }
+        else   /* this part doesn't work in some cases, the low_bound is too high, Jan 4,2006 */
+        {
+            rc[n]->VBV_fullness =  rc[n]->Bs - (Int)(video->encParams->VBV_delay * rc[n]->bitrate);
+            if (rc[n]->VBV_fullness < 0) rc[n]->VBV_fullness = 0;
+            //rc[n]->VBV_fullness = (rc[n]->Bs-video->encParams->maxFrameSize)/2 + video->encParams->maxFrameSize;
+
+            rc[n]->VBV_fullness -= rc[n]->Bs / 2; /* the buffer range is [-Bs/2, Bs/2] */
+            rc[n]->low_bound = -rc[n]->Bs / 2 + video->encParams->maxFrameSize;  /*  too high */
+            rc[n]->VBV_fullness_offset = video->encParams->maxFrameSize / 2; /*  don't understand the meaning of this */
+            pMP[n]->counter_BTdst = pMP[n]->counter_BTsrc = 0;
+
+        }
+
+        /* Setting the bitrate and framerate */
+        pMP[n]->bitrate = rc[n]->bitrate;
+        pMP[n]->framerate = rc[n]->framerate;
+        pMP[n]->target_bits_per_frame = pMP[n]->bitrate / pMP[n]->framerate;
+
+    }
+
+    return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/*  Function : RC_Cleanup                                                   */
+/*  Date     : 12/20/2000                                                   */
+/*  Purpose  : free Rate Control memory                                     */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+
+PV_STATUS RC_Cleanup(rateControl *rc[], Int numLayers)
+{
+    OSCL_UNUSED_ARG(rc);
+    OSCL_UNUSED_ARG(numLayers);
+
+    return PV_SUCCESS;
+}
+
+
+
+/* ======================================================================== */
+/*  Function : RC_VopQPSetting                                              */
+/*  Date     : 4/11/2001                                                    */
+/*  Purpose  : Reset rate control before coding VOP, moved from vop.c       */
+/*              Compute QP for the whole VOP and initialize MB-based RC
+                reset QPMB[], currVop->quantizer, rc->Ec, video->header_bits */
+/* to          In order to  work RC_VopQPSetting has to do the followings
+                1. Set video->QPMB of all macroblocks.
+                2. Set currVop->quantizer
+                3. Reset video->header_bits to zero.
+                4. Initialize internal RC parameters for Vop cooding        */
+/*  In/out   :                                                              */
+/*  Return   : PV_STATUS                                                    */
+/*  Modified :                                                              */
+/* ======================================================================== */
+/* To be moved to rate_control.c and separate between BX_RC and ANNEX_L     */
+
+PV_STATUS RC_VopQPSetting(VideoEncData *video, rateControl *prc[])
+{
+    Int currLayer = video->currLayer;
+    Vol *currVol = video->vol[currLayer];
+    Vop *currVop = video->currVop;
+#ifdef TEST_MBBASED_QP
+    int i;
+#endif
+
+    rateControl *rc = video->rc[currLayer];
+    MultiPass *pMP = video->pMP[currLayer];
+
+    OSCL_UNUSED_ARG(prc);
+
+    if (video->encParams->RC_Type == CONSTANT_Q)
+    {
+        M4VENC_MEMSET(video->QPMB, currVop->quantizer, sizeof(UChar)*currVol->nTotalMB);
+        return PV_SUCCESS;
+    }
+    else
+    {
+
+        if (video->rc[currLayer]->encoded_frames == 0) /* rc[currLayer]->totalFrameNumber*/
+        {
+            M4VENC_MEMSET(video->QPMB, currVop->quantizer, sizeof(UChar)*currVol->nTotalMB);
+            video->rc[currLayer]->Qc = video->encParams->InitQuantIvop[currLayer];
+        }
+        else
+        {
+            calculateQuantizer_Multipass((void*) video);
+            currVop->quantizer = video->rc[currLayer]->Qc;
+#ifdef TEST_MBBASED_QP
+            i = currVol->nTotalMB;  /* testing changing QP at MB level */
+            while (i)
+            {
+                i--;
+                video->QPMB[i] = (i & 1) ? currVop->quantizer - 1 : currVop->quantizer + 1;
+            }
+#else
+            M4VENC_MEMSET(video->QPMB, currVop->quantizer, sizeof(UChar)*currVol->nTotalMB);
+#endif
+        }
+
+        video->header_bits = 0;
+    }
+
+    /* update pMP->framePos */
+    if (++pMP->framePos == pMP->frameRange) pMP->framePos = 0;
+
+    if (rc->T == 0)
+    {
+        pMP->counter_BTdst = (Int)(video->encParams->LayerFrameRate[video->currLayer] * 7.5 + 0.5); /* 0.75s time frame */
+        pMP->counter_BTdst = PV_MIN(pMP->counter_BTdst, (Int)(rc->max_BitVariance_num / 2 * 0.40)); /* 0.75s time frame may go beyond VBV buffer if we set the buffer size smaller than 0.75s */
+        pMP->counter_BTdst = PV_MAX(pMP->counter_BTdst, (Int)((rc->Bs / 2 - rc->VBV_fullness) * 0.30 / (rc->TMN_TH / 10.0) + 0.5)); /* At least 30% of VBV buffer size/2 */
+        pMP->counter_BTdst = PV_MIN(pMP->counter_BTdst, 20); /* Limit the target to be smaller than 3C */
+
+        pMP->target_bits = rc->T = rc->TMN_TH = (Int)(rc->TMN_TH * (1.0 + pMP->counter_BTdst * 0.1));
+        pMP->diff_counter = pMP->counter_BTdst;
+    }
+
+    /* collect the necessary data: target bits, actual bits, mad and QP */
+    pMP->target_bits = rc->T;
+    pMP->QP  = currVop->quantizer;
+
+    pMP->mad = video->sumMAD / (float)currVol->nTotalMB;
+    if (pMP->mad < MAD_MIN) pMP->mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+
+    pMP->bitrate = rc->bitrate; /* calculated in RCVopQPSetting */
+    pMP->framerate = rc->framerate;
+
+    /* first pass encoding */
+    pMP->nRe_Quantized = 0;
+
+    return  PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/*  Function : SaveRDSamples()                                              */
+/*  Date     : 08/29/2001                                                   */
+/*  History  :                                                              */
+/*  Purpose  : Save QP, actual_bits, mad and R_D of the current iteration   */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+Void SaveRDSamples(MultiPass *pMP, Int counter_samples)
+{
+    /* for pMP->pRDSamples */
+    pMP->pRDSamples[pMP->framePos][counter_samples].QP    = pMP->QP;
+    pMP->pRDSamples[pMP->framePos][counter_samples].actual_bits = pMP->actual_bits;
+    pMP->pRDSamples[pMP->framePos][counter_samples].mad   = pMP->mad;
+    pMP->pRDSamples[pMP->framePos][counter_samples].R_D = (float)(pMP->actual_bits / (pMP->mad + 0.0001));
+
+    return ;
+}
+/* ======================================================================== */
+/*  Function : RC_VopUpdateStat                                             */
+/*  Date     : 12/20/2000                                                   */
+/*  Purpose  : Update statistics for rate control after encoding each VOP.  */
+/*             No need to change anything in VideoEncData structure.        */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+PV_STATUS RC_VopUpdateStat(VideoEncData *video, rateControl *rc)
+{
+    Int currLayer = video->currLayer;
+    Vol *currVol = video->vol[currLayer];
+    MultiPass *pMP = video->pMP[currLayer];
+    Int diff_BTCounter;
+
+    switch (video->encParams->RC_Type)
+    {
+        case CONSTANT_Q:
+            break;
+
+        case CBR_1:
+        case CBR_2:
+        case VBR_1:
+        case VBR_2:
+        case CBR_LOWDELAY:
+
+            pMP->actual_bits = currVol->stream->byteCount << 3;
+
+            SaveRDSamples(pMP, 0);
+
+            pMP->encoded_frames++;
+
+            /* for pMP->samplesPerFrame */
+            pMP->samplesPerFrame[pMP->framePos] = 0;
+
+            pMP->sum_QP += pMP->QP;
+
+
+            /* update pMP->counter_BTsrc, pMP->counter_BTdst */
+            /* re-allocate the target bit again and then stop encoding */
+            diff_BTCounter = (Int)((float)(rc->TMN_TH - rc->TMN_W - pMP->actual_bits) /
+                                   (pMP->bitrate / (pMP->framerate + 0.0001) + 0.0001) / 0.1);
+            if (diff_BTCounter >= 0)
+                pMP->counter_BTsrc += diff_BTCounter; /* pMP->actual_bits is smaller */
+            else
+                pMP->counter_BTdst -= diff_BTCounter; /* pMP->actual_bits is bigger */
+
+            rc->TMN_TH -= (Int)((float)pMP->bitrate / (pMP->framerate + 0.0001) * (diff_BTCounter * 0.1));
+            rc->T = pMP->target_bits = rc->TMN_TH - rc->TMN_W;
+            pMP->diff_counter -= diff_BTCounter;
+
+            rc->Rc = currVol->stream->byteCount << 3;   /* Total Bits for current frame */
+            rc->Hc = video->header_bits;    /* Total Bits in Header and Motion Vector */
+
+            /* BX_RC */
+            updateRateControl(rc, video);
+
+            break;
+
+        default: /* for case CBR_1/2, VBR_1/2 */
+
+            return PV_FAIL;
+    }
+
+
+    return PV_SUCCESS;
+}
+
+/* ======================================================================== */
+/*  Function : RC_GetSkipNextFrame, RC_GetRemainingVops                     */
+/*  Date     : 2/20/2001                                                    */
+/*  Purpose  : To access RC parameters from other parts of the code.        */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+Int RC_GetSkipNextFrame(VideoEncData *video, Int currLayer)
+{
+    return video->rc[currLayer]->skip_next_frame;
+}
+
+void RC_ResetSkipNextFrame(VideoEncData *video, Int currLayer)
+{
+
+    video->rc[currLayer]->skip_next_frame = 0;
+    return ;
+}
+
+/* ======================================================================== */
+/*  Function : RC_UpdateBuffer                                      */
+/*  Date     : 2/20/2001                                                    */
+/*  Purpose  : Update RC in case of there are frames skipped (camera freeze)*/
+/*              from the application level in addition to what RC requested */
+/*  In/out   : Nr, B, Rr                                                    */
+/*  Return   : Void                                                         */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+
+PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip)
+{
+    rateControl *rc  = video->rc[currLayer];
+    MultiPass   *pMP = video->pMP[currLayer];
+
+    if (video == NULL || rc == NULL || pMP == NULL)
+        return PV_FAIL;
+
+    rc->VBV_fullness   -= (Int)(rc->bitrate / rc->framerate * num_skip); //rc[currLayer]->Rp;
+    pMP->counter_BTsrc += 10 * num_skip;
+
+    /* Check buffer underflow */
+    if (rc->VBV_fullness < rc->low_bound)
+    {
+        rc->VBV_fullness = rc->low_bound; // -rc->Bs/2;
+        rc->TMN_W = rc->VBV_fullness - rc->low_bound;
+        pMP->counter_BTsrc = pMP->counter_BTdst + (Int)((float)(rc->Bs / 2 - rc->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+    }
+
+    return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/*  Function : RC_UpdateBXRCParams                                          */
+/*  Date     : 4/08/2002                                                    */
+/*  Purpose  : Update RC parameters specifically for target bitrate or      */
+/*             framerate update during an encoding session                  */
+/*  In/out   :                                                              */
+/*  Return   : PV_TRUE if successed, PV_FALSE if failed.                    */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+PV_STATUS RC_UpdateBXRCParams(void *input)
+{
+    VideoEncData *video = (VideoEncData *) input;
+    VideoEncParams *encParams = video->encParams;
+    rateControl **rc = video->rc;
+    Int numLayers = encParams->nLayers;
+    Int *LayerBitRate = encParams->LayerBitRate;
+    float *LayerFrameRate = encParams->LayerFrameRate;
+    MultiPass **pMP = video->pMP;
+
+    Int n, VBV_fullness;
+    Int diff_counter;
+
+    extern Bool SetProfile_BufferSize(VideoEncData *video, float delay, Int bInitialized);
+
+
+    /* Reset video buffer size due to target bitrate change */
+    SetProfile_BufferSize(video, video->encParams->VBV_delay, 0); /* output: video->encParams->BufferSize[] */
+
+    for (n = 0; n < numLayers; n++)
+    {
+        /* Remaining stuff about frame dropping and underflow check in update RC */
+        updateRC_PostProc(rc[n], video);
+        rc[n]->skip_next_frame = 0; /* must be initialized */
+
+        /* New changes: bitrate and framerate, Bs, max_BitVariance_num, TMN_TH(optional), encoded_frames(optional) */
+        rc[n]->Bs = video->encParams->BufferSize[n];
+        VBV_fullness = (Int)(rc[n]->Bs * 0.5);
+
+        if (n == 0)
+        {
+            rc[n]->TMN_TH = (Int)((float)LayerBitRate[n] / LayerFrameRate[n]);
+            rc[n]->bitrate   = pMP[n]->bitrate   = LayerBitRate[n];
+            rc[n]->framerate = pMP[n]->framerate = LayerFrameRate[n];
+
+            // For h263 or short header mode, the bit variation is within (-2*Rmax*1001/3000, 2*Rmax*1001/3000)
+            if (video->encParams->H263_Enabled)
+            {
+                rc[n]->max_BitVariance_num = (Int)((rc[n]->Bs - video->encParams->maxFrameSize) / 2 / (rc[n]->bitrate / rc[n]->framerate / 10.0)) - 5;
+                //rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - rc[n]->VBV_fullness)/((float)LayerBitRate[n]/LayerFrameRate[n]/10.0))-5;
+            }
+            else   // MPEG-4 normal modes
+            {
+                rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - VBV_fullness) * 10 / ((float)LayerBitRate[n] / LayerFrameRate[n])) - 5;
+            }
+        }
+        else
+        {
+            if (LayerFrameRate[n] - LayerFrameRate[n-1] > 0) /*  7/31/03 */
+            {
+                rc[n]->TMN_TH = (Int)((float)(LayerBitRate[n] - LayerBitRate[n-1]) / (LayerFrameRate[n] - LayerFrameRate[n-1]));
+                rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - VBV_fullness) * 10 / ((float)rc[n]->TMN_TH)) - 5;
+                if (rc[n]->max_BitVariance_num < 0) rc[n]->max_BitVariance_num += 5;
+            }
+            else   /*  7/31/03 */
+            {
+                rc[n]->TMN_TH = 1 << 30;
+                rc[n]->max_BitVariance_num = 0;
+            }
+            rc[n]->bitrate   = pMP[n]->bitrate   = LayerBitRate[n] - LayerBitRate[n-1];
+            rc[n]->framerate = pMP[n]->framerate = LayerFrameRate[n] - LayerFrameRate[n-1];
+        }
+
+        pMP[n]->target_bits_per_frame_prev = pMP[n]->target_bits_per_frame;
+        pMP[n]->target_bits_per_frame = pMP[n]->bitrate / (float)(pMP[n]->framerate + 0.0001);  /*  7/31/03 */
+
+        /* rc[n]->VBV_fullness and rc[n]->TMN_W should be kept same */
+        /* update pMP[n]->counter_BTdst and pMP[n]->counter_BTsrc   */
+        diff_counter = (Int)((float)(rc[n]->VBV_fullness - rc[n]->TMN_W) /
+                             (pMP[n]->target_bits_per_frame / 10 + 0.0001)); /*  7/31/03 */
+
+        pMP[n]->counter_BTdst = pMP[n]->counter_BTsrc = 0;
+        if (diff_counter > 0)
+            pMP[n]->counter_BTdst = diff_counter;
+
+        else if (diff_counter < 0)
+            pMP[n]->counter_BTsrc = -diff_counter;
+
+        rc[n]->TMN_W = (Int)(rc[n]->VBV_fullness -      /* re-calculate rc[n]->TMN_W in order for higher accuracy */
+                             (pMP[n]->target_bits_per_frame / 10) * (pMP[n]->counter_BTdst - pMP[n]->counter_BTsrc));
+
+        /* Keep the current average mad */
+        if (pMP[n]->aver_mad != 0)
+        {
+            pMP[n]->aver_mad_prev = pMP[n]->aver_mad;
+            pMP[n]->encoded_frames_prev = pMP[n]->encoded_frames;
+        }
+
+        pMP[n]->aver_mad = 0;
+        pMP[n]->overlapped_win_size = 4;
+
+        /* Misc */
+        pMP[n]->sum_mad = pMP[n]->sum_QP = 0;
+        //pMP[n]->encoded_frames_prev = pMP[n]->encoded_frames;
+        pMP[n]->encoded_frames = pMP[n]->re_encoded_frames = pMP[n]->re_encoded_times = 0;
+
+    } /* end of: for(n=0; n<numLayers; n++) */
+
+    return PV_SUCCESS;
+
+}
+
+
+/* ================================================================================ */
+/*  Function : targetBitCalculation                                                 */
+/*  Date     : 10/01/2001                                                           */
+/*  Purpose  : quadratic bit allocation model: T(n) = C*sqrt(mad(n)/aver_mad(n-1))  */
+/*                                                                                  */
+/*  In/out   : rc->T                                                                */
+/*  Return   : Void                                                                 */
+/*  Modified :                                                                      */
+/* ================================================================================ */
+
+void targetBitCalculation(void *input)
+{
+    VideoEncData *video = (VideoEncData *) input;
+    MultiPass *pMP = video->pMP[video->currLayer];
+    Vol *currVol = video->vol[video->currLayer];
+    rateControl *rc = video->rc[video->currLayer];
+
+    float curr_mad;//, average_mad;
+    Int diff_counter_BTsrc, diff_counter_BTdst, prev_counter_diff, curr_counter_diff, bound;
+    /* BT = Bit Transfer, for pMP->counter_BTsrc, pMP->counter_BTdst */
+
+    if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+        return;
+
+    /* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/
+    updateRC_PostProc(rc, video);
+
+    /* update pMP->counter_BTsrc and pMP->counter_BTdst to avoid interger overflow */
+    if (pMP->counter_BTsrc > 1000 && pMP->counter_BTdst > 1000)
+    {
+        pMP->counter_BTsrc -= 1000;
+        pMP->counter_BTdst -= 1000;
+    }
+
+    /* ---------------------------------------------------------------------------------------------------*/
+    /* target calculation */
+    curr_mad = video->sumMAD / (float)currVol->nTotalMB;
+    if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+    diff_counter_BTsrc = diff_counter_BTdst = 0;
+    pMP->diff_counter = 0;
+
+
+    /*1.calculate average mad */
+    pMP->sum_mad += curr_mad;
+    //average_mad = (pMP->encoded_frames < 1 ? curr_mad : pMP->sum_mad/(float)(pMP->encoded_frames+1)); /* this function is called from the scond encoded frame*/
+    //pMP->aver_mad = average_mad;
+    if (pMP->encoded_frames >= 0) /* pMP->encoded_frames is set to -1 initially, so forget about the very first I frame */
+        pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames + curr_mad) / (pMP->encoded_frames + 1);
+
+    if (pMP->overlapped_win_size > 0 && pMP->encoded_frames_prev >= 0)  /*  7/31/03 */
+        pMP->aver_mad_prev = (pMP->aver_mad_prev * pMP->encoded_frames_prev + curr_mad) / (pMP->encoded_frames_prev + 1);
+
+    /*2.average_mad, mad ==> diff_counter_BTsrc, diff_counter_BTdst */
+    if (pMP->overlapped_win_size == 0)
+    {
+        /* original verison */
+        if (curr_mad > pMP->aver_mad*1.1)
+        {
+            if (curr_mad / (pMP->aver_mad + 0.0001) > 2)
+                diff_counter_BTdst = (Int)(M4VENC_SQRT(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.4) - 10;
+            //diff_counter_BTdst = (Int)((sqrt(curr_mad/pMP->aver_mad)*2+curr_mad/pMP->aver_mad)/(3*0.1) + 0.4) - 10;
+            else
+                diff_counter_BTdst = (Int)(curr_mad / (pMP->aver_mad + 0.0001) * 10 + 0.4) - 10;
+        }
+        else /* curr_mad <= average_mad*1.1 */
+            //diff_counter_BTsrc = 10 - (Int)((sqrt(curr_mad/pMP->aver_mad) + pow(curr_mad/pMP->aver_mad, 1.0/3.0))/(2.0*0.1) + 0.4);
+            diff_counter_BTsrc = 10 - (Int)(M4VENC_SQRT(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.5);
+        //diff_counter_BTsrc = 10 - (Int)(curr_mad/pMP->aver_mad/0.1 + 0.5)
+
+        /* actively fill in the possible gap */
+        if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
+                curr_mad <= pMP->aver_mad*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
+            diff_counter_BTsrc = 1;
+
+    }
+    else if (pMP->overlapped_win_size > 0)
+    {
+        /* transition time: use previous average mad "pMP->aver_mad_prev" instead of the current average mad "pMP->aver_mad" */
+        if (curr_mad > pMP->aver_mad_prev*1.1)
+        {
+            if (curr_mad / pMP->aver_mad_prev > 2)
+                diff_counter_BTdst = (Int)(M4VENC_SQRT(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.4) - 10;
+            //diff_counter_BTdst = (Int)((M4VENC_SQRT(curr_mad/pMP->aver_mad_prev)*2+curr_mad/pMP->aver_mad_prev)/(3*0.1) + 0.4) - 10;
+            else
+                diff_counter_BTdst = (Int)(curr_mad / (pMP->aver_mad_prev + 0.0001) * 10 + 0.4) - 10;
+        }
+        else /* curr_mad <= average_mad*1.1 */
+            //diff_counter_BTsrc = 10 - (Int)((sqrt(curr_mad/pMP->aver_mad_prev) + pow(curr_mad/pMP->aver_mad_prev, 1.0/3.0))/(2.0*0.1) + 0.4);
+            diff_counter_BTsrc = 10 - (Int)(M4VENC_SQRT(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.5);
+        //diff_counter_BTsrc = 10 - (Int)(curr_mad/pMP->aver_mad_prev/0.1 + 0.5)
+
+        /* actively fill in the possible gap */
+        if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
+                curr_mad <= pMP->aver_mad_prev*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
+            diff_counter_BTsrc = 1;
+
+        if (--pMP->overlapped_win_size <= 0)    pMP->overlapped_win_size = 0;
+    }
+
+
+    /* if difference is too much, do clipping */
+    /* First, set the upper bound for current bit allocation variance: 80% of available buffer */
+    bound = (Int)((rc->Bs / 2 - rc->VBV_fullness) * 0.6 / (pMP->target_bits_per_frame / 10)); /* rc->Bs */
+    diff_counter_BTsrc =  PV_MIN(diff_counter_BTsrc, bound);
+    diff_counter_BTdst =  PV_MIN(diff_counter_BTdst, bound);
+
+    /* Second, set another upper bound for current bit allocation: 4-5*bitrate/framerate */
+    bound = 50;
+//  if(video->encParams->RC_Type == CBR_LOWDELAY)
+//  not necessary       bound = 10;     /*  1/17/02 -- For Low delay */
+
+    diff_counter_BTsrc =  PV_MIN(diff_counter_BTsrc, bound);
+    diff_counter_BTdst =  PV_MIN(diff_counter_BTdst, bound);
+
+
+    /* Third, check the buffer */
+    prev_counter_diff = pMP->counter_BTdst - pMP->counter_BTsrc;
+    curr_counter_diff = prev_counter_diff + (diff_counter_BTdst - diff_counter_BTsrc);
+
+    if (PV_ABS(prev_counter_diff) >= rc->max_BitVariance_num || PV_ABS(curr_counter_diff) >= rc->max_BitVariance_num) // PV_ABS(curr_counter_diff) >= PV_ABS(prev_counter_diff) )
+    {   //diff_counter_BTsrc = diff_counter_BTdst = 0;
+
+        if (curr_counter_diff > rc->max_BitVariance_num && diff_counter_BTdst)
+        {
+            diff_counter_BTdst = (rc->max_BitVariance_num - prev_counter_diff) + diff_counter_BTsrc;
+            if (diff_counter_BTdst < 0) diff_counter_BTdst = 0;
+        }
+
+        else if (curr_counter_diff < -rc->max_BitVariance_num && diff_counter_BTsrc)
+        {
+            diff_counter_BTsrc = diff_counter_BTdst - (-rc->max_BitVariance_num - prev_counter_diff);
+            if (diff_counter_BTsrc < 0) diff_counter_BTsrc = 0;
+        }
+    }
+
+
+    /*3.diff_counter_BTsrc, diff_counter_BTdst ==> TMN_TH */
+    //rc->TMN_TH = (Int)((float)pMP->bitrate/pMP->framerate);
+    rc->TMN_TH = (Int)(pMP->target_bits_per_frame);
+    pMP->diff_counter = 0;
+
+    if (diff_counter_BTsrc)
+    {
+        rc->TMN_TH -= (Int)(pMP->target_bits_per_frame * diff_counter_BTsrc * 0.1);
+        pMP->diff_counter = -diff_counter_BTsrc;
+    }
+    else if (diff_counter_BTdst)
+    {
+        rc->TMN_TH += (Int)(pMP->target_bits_per_frame * diff_counter_BTdst * 0.1);
+        pMP->diff_counter = diff_counter_BTdst;
+    }
+
+
+    /*4.update pMP->counter_BTsrc, pMP->counter_BTdst */
+    pMP->counter_BTsrc += diff_counter_BTsrc;
+    pMP->counter_BTdst += diff_counter_BTdst;
+
+
+    /*5.target bit calculation */
+    rc->T = rc->TMN_TH - rc->TMN_W;
+    //rc->T = rc->TMN_TH - (Int)((float)rc->TMN_W/rc->frameRate);
+
+    if (video->encParams->H263_Enabled && rc->T > video->encParams->maxFrameSize)
+    {
+        rc->T = video->encParams->maxFrameSize;  //  added this 11/07/05
+    }
+
+}
+
+/* ================================================================================ */
+/*  Function : calculateQuantizer_Multipass                                         */
+/*  Date     : 10/01/2001                                                           */
+/*  Purpose  : variable rate bit allocation + new QP determination scheme           */
+/*                                                                                  */
+/*  In/out   : rc->T and rc->Qc                                                     */
+/*  Return   : Void                                                                 */
+/*  Modified :                                                                      */
+/* ================================================================================ */
+
+/* Mad based variable bit allocation + QP calculation with a new quadratic method */
+void calculateQuantizer_Multipass(void *input)
+{
+    VideoEncData *video = (VideoEncData *) input;
+    MultiPass *pMP = video->pMP[video->currLayer];
+    Vol *currVol = video->vol[video->currLayer];
+    rateControl *rc = video->rc[video->currLayer];
+
+    Int prev_QP, prev_actual_bits, curr_target, i, j;
+
+    float curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;
+
+
+    if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+        return;
+
+    /* Mad based variable bit allocation */
+    targetBitCalculation((void*) video);
+
+    if (rc->T <= 0 || video->sumMAD == 0)
+    {
+        if (rc->T < 0)  rc->Qc = 31;
+        return;
+    }
+
+    /* ---------------------------------------------------------------------------------------------------*/
+    /* current frame QP estimation */
+    curr_target = rc->T;
+    curr_mad = video->sumMAD / (float)currVol->nTotalMB;
+    if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+    curr_RD  = (float)curr_target / curr_mad;
+
+    /* Another version of search the optimal point */
+    prev_actual_bits = pMP->pRDSamples[0][0].actual_bits;
+    prev_mad = pMP->pRDSamples[0][0].mad;
+
+    for (i = 0, j = 0; i < pMP->frameRange; i++)
+    {
+        if (pMP->pRDSamples[i][0].mad != 0 && prev_mad != 0 &&
+                PV_ABS(prev_mad - curr_mad) > PV_ABS(pMP->pRDSamples[i][0].mad - curr_mad))
+        {
+            prev_mad = pMP->pRDSamples[i][0].mad;
+            prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
+            j = i;
+        }
+    }
+    prev_QP = pMP->pRDSamples[j][0].QP;
+    for (i = 1; i < pMP->samplesPerFrame[j]; i++)
+    {
+        if (PV_ABS(prev_actual_bits - curr_target) > PV_ABS(pMP->pRDSamples[j][i].actual_bits - curr_target))
+        {
+            prev_actual_bits = pMP->pRDSamples[j][i].actual_bits;
+            prev_QP = pMP->pRDSamples[j][i].QP;
+        }
+    }
+
+    // quadratic approximation
+    prev_RD = (float)prev_actual_bits / prev_mad;
+    //rc->Qc = (Int)(prev_QP * sqrt(prev_actual_bits/curr_target) + 0.4);
+    if (prev_QP == 1) // 11/14/05, added this to allow getting out of QP = 1 easily
+    {
+        rc->Qc = (Int)(prev_RD / curr_RD + 0.5);
+    }
+    else
+    {
+        rc->Qc = (Int)(prev_QP * M4VENC_SQRT(prev_RD / curr_RD) + 0.9);
+
+        if (prev_RD / curr_RD > 0.5 && prev_RD / curr_RD < 2.0)
+            rc->Qc = (Int)(prev_QP * (M4VENC_SQRT(prev_RD / curr_RD) + prev_RD / curr_RD) / 2.0 + 0.9); /* Quadratic and linear approximation */
+        else
+            rc->Qc = (Int)(prev_QP * (M4VENC_SQRT(prev_RD / curr_RD) + M4VENC_POW(prev_RD / curr_RD, 1.0 / 3.0)) / 2.0 + 0.9);
+    }
+    //rc->Qc =(Int)(prev_QP * sqrt(prev_RD/curr_RD) + 0.4);
+    // 11/08/05
+    // lower bound on Qc should be a function of curr_mad
+    // When mad is already low, lower bound on Qc doesn't have to be small.
+    // Note, this doesn't work well for low complexity clip encoded at high bit rate
+    // it doesn't hit the target bit rate due to this QP lower bound.
+/// if((curr_mad < 8) && (rc->Qc < 12)) rc->Qc = 12;
+//  else    if((curr_mad < 128) && (rc->Qc < 3)) rc->Qc = 3;
+
+    if (rc->Qc < 1) rc->Qc = 1;
+    if (rc->Qc > 31)    rc->Qc = 31;
+
+
+    /* active bit resource protection */
+    aver_QP = (pMP->encoded_frames == 0 ? 0 : pMP->sum_QP / (float)pMP->encoded_frames);
+    average_mad = (pMP->encoded_frames == 0 ? 0 : pMP->sum_mad / (float)pMP->encoded_frames); /* this function is called from the scond encoded frame*/
+    if (pMP->diff_counter == 0 &&
+            ((float)rc->Qc <= aver_QP*1.1 || curr_mad <= average_mad*1.1) &&
+            pMP->counter_BTsrc <= (pMP->counter_BTdst + (Int)(pMP->framerate*1.0 + 0.5)))
+    {
+        rc->TMN_TH -= (Int)(pMP->target_bits_per_frame / 10.0);
+        rc->T = rc->TMN_TH - rc->TMN_W;
+        pMP->counter_BTsrc++;
+        pMP->diff_counter--;
+    }
+
+}
+
+
+/* ======================================================================== */
+/*  Function : updateRateControl                                            */
+/*  Date     : 11/17/2000                                                   */
+/*  Purpose  :Update the RD Modal (After Encoding the Current Frame)        */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+void updateRateControl(rateControl *rc, VideoEncData *video)
+{
+    Int  frame_bits;
+
+
+    /* rate contro\l */
+    frame_bits = (Int)(rc->bitrate / rc->framerate);
+    rc->TMN_W += (rc->Rc - rc->TMN_TH);
+    rc->VBV_fullness += (rc->Rc - frame_bits); //rc->Rp);
+    //if(rc->VBV_fullness < 0) rc->VBV_fullness = -1;
+
+    rc->encoded_frames++;
+
+    /* frame dropping */
+    rc->skip_next_frame = 0;
+
+    if ((video->encParams->H263_Enabled && rc->Rc > video->encParams->maxFrameSize) || /*  For H263/short header mode, drop the frame if the actual frame size exceeds the bound */
+            (rc->VBV_fullness > rc->Bs / 2 && !rc->no_pre_skip)) /* skip the current frame */ /* rc->Bs */
+    {
+        rc->TMN_W -= (rc->Rc - rc->TMN_TH);
+        rc->VBV_fullness -= rc->Rc;
+        rc->skip_next_frame = -1;
+    }
+    else if ((float)(rc->VBV_fullness - rc->VBV_fullness_offset) > (rc->Bs / 2 - rc->VBV_fullness_offset)*0.95 &&
+             !rc->no_frame_skip) /* skip next frame */
+    {
+        rc->VBV_fullness -= frame_bits; //rc->Rp;
+        rc->skip_next_frame = 1;
+        /*  skip more than 1 frames  */
+        //while(rc->VBV_fullness > rc->Bs*0.475)
+        while ((rc->VBV_fullness - rc->VBV_fullness_offset) > (rc->Bs / 2 - rc->VBV_fullness_offset)*0.95)
+        {
+            rc->VBV_fullness -= frame_bits; //rc->Rp;
+            rc->skip_next_frame++;
+        }
+        /* END  */
+    }
+
+}
+
+/* ======================================================================== */
+/*  Function : updateRC_PostProc                                            */
+/*  Date     : 04/08/2002                                                   */
+/*  Purpose  : Remaing RC update stuff for frame skip and buffer underflow  */
+/*             check                                                        */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+void updateRC_PostProc(rateControl *rc, VideoEncData *video)
+{
+    MultiPass *pMP = video->pMP[video->currLayer];
+
+    if (rc->skip_next_frame == 1 && !rc->no_frame_skip) /* skip next frame */
+    {
+        pMP->counter_BTsrc += 10 * rc->skip_next_frame;
+
+    }
+    else if (rc->skip_next_frame == -1 && !rc->no_pre_skip) /* skip current frame */
+    {
+        pMP->counter_BTdst -= pMP->diff_counter;
+        pMP->counter_BTsrc += 10;
+
+        pMP->sum_mad -= pMP->mad;
+        pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames - pMP->mad) / (float)(pMP->encoded_frames - 1 + 0.0001);
+        pMP->sum_QP  -= pMP->QP;
+        pMP->encoded_frames --;
+    }
+    /* some stuff in update VBV_fullness remains here */
+    //if(rc->VBV_fullness < -rc->Bs/2) /* rc->Bs */
+    if (rc->VBV_fullness < rc->low_bound)
+    {
+        rc->VBV_fullness = rc->low_bound; // -rc->Bs/2;
+        rc->TMN_W = rc->VBV_fullness - rc->low_bound;
+        pMP->counter_BTsrc = pMP->counter_BTdst + (Int)((float)(rc->Bs / 2 - rc->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+    }
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h
new file mode 100644
index 0000000..ad29549
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h
@@ -0,0 +1,96 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _RATE_CONTROL_H_
+#define _RATE_CONTROL_H_
+
+#include "mp4def.h"
+
+typedef struct tagdataPointArray
+{
+    Int Qp;
+    Int Rp;
+    float Mp;   /* for MB-based RC, 3/14/01 */
+    struct tagdataPointArray *next;
+    struct tagdataPointArray *prev;
+} dataPointArray;
+
+
+typedef struct
+{
+    Int alpha;  /* weight for I frame */
+    Int Rs;     /*bit rate for the sequence (or segment) e.g., 24000 bits/sec */
+    Int Rc;     /*bits used for the current frame. It is the bit count obtained after encoding. */
+    Int Rp;     /*bits to be removed from the buffer per picture. */
+    /*? is this the average one, or just the bits coded for the previous frame */
+    Int Rps;    /*bit to be removed from buffer per src frame */
+    float Ts;   /*number of seconds for the sequence  (or segment). e.g., 10 sec */
+    float Ep;
+    float Ec;   /*mean absolute difference for the current frame after motion compensation.*/
+    /*If the macroblock is intra coded, the original spatial pixel values are summed.*/
+    Int Qc;     /*quantization level used for the current frame. */
+    Int Nr;     /*number of P frames remaining for encoding.*/
+    Int Rr; /*number of bits remaining for encoding this sequence (or segment).*/
+    Int Rr_Old;/* 12/24/00 */
+    Int T;      /*target bit to be used for the current frame.*/
+    Int S;      /*number of bits used for encoding the previous frame.*/
+    Int Hc; /*header and motion vector bits used in the current frame. It includes all the  information except to the residual information.*/
+    Int Hp; /*header and motion vector bits used in the previous frame. It includes all the     information except to the residual information.*/
+    Int Ql; /*quantization level used in the previous frame */
+    Int Bs; /*buffer size e.g., R/2 */
+    Int B;      /*current buffer level e.g., R/4 - start from the middle of the buffer */
+    float X1;
+    float X2;
+    float X11;
+    float M;            /*safe margin for the buffer */
+    float smTick;    /*ratio of src versus enc frame rate */
+    double remnant;  /*remainder frame of src/enc frame for fine frame skipping */
+    Int timeIncRes; /* vol->timeIncrementResolution */
+
+    dataPointArray   *end; /*quantization levels for the past (20) frames */
+
+    Int     frameNumber; /* ranging from 0 to 20 nodes*/
+    Int     w;
+    Int     Nr_Original;
+    Int     Nr_Old, Nr_Old2;
+    Int     skip_next_frame;
+    Int     Qdep;       /* smooth Q adjustment */
+    Int     fine_frame_skip;
+    Int     VBR_Enabled;
+    Int     no_frame_skip;
+    Int     no_pre_skip;
+
+    Int totalFrameNumber; /* total coded frames, for debugging!!*/
+
+    char    oFirstTime;
+
+    /* BX rate control */
+    Int     TMN_W;
+    Int     TMN_TH;
+    Int     VBV_fullness;
+    Int     max_BitVariance_num; /* the number of the maximum bit variance within the given buffer with the unit of 10% of bitrate/framerate*/
+    Int     encoded_frames; /* counter for all encoded frames */
+    float   framerate;
+    Int     bitrate;
+    Int     low_bound;              /* bound for underflow detection, usually low_bound=-Bs/2, but could be changed in H.263 mode */
+    Int     VBV_fullness_offset;    /* offset of VBV_fullness, usually is zero, but can be changed in H.263 mode*/
+    /* End BX */
+
+} rateControl;
+
+
+#endif /* _RATE_CONTROL_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp
new file mode 100644
index 0000000..8d18f45
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp
@@ -0,0 +1,375 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+
+#include "sad_inline.h"
+
+#define Cached_lx 176
+
+#ifdef _SAD_STAT
+ULong num_sad_MB = 0;
+ULong num_sad_Blk = 0;
+ULong num_sad_MB_call = 0;
+ULong num_sad_Blk_call = 0;
+
+#define NUM_SAD_MB_CALL()       num_sad_MB_call++
+#define NUM_SAD_MB()            num_sad_MB++
+#define NUM_SAD_BLK_CALL()      num_sad_Blk_call++
+#define NUM_SAD_BLK()           num_sad_Blk++
+
+#else
+
+#define NUM_SAD_MB_CALL()
+#define NUM_SAD_MB()
+#define NUM_SAD_BLK_CALL()
+#define NUM_SAD_BLK()
+
+#endif
+
+
+/* consist of
+Int SAD_Macroblock_C(UChar *ref,UChar *blk,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_HTFM_Collect(UChar *ref,UChar *blk,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_HTFM(UChar *ref,UChar *blk,Int dmin,Int lx,void *extra_info)
+Int SAD_Block_C(UChar *ref,UChar *blk,Int dmin,Int lx,void *extra_info)
+Int SAD_Blk_PADDING(UChar *ref,UChar *cur,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_PADDING(UChar *ref,UChar *cur,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_PAD1(UChar *ref,UChar *cur,Int dmin,Int lx,Int *rep);
+Int SAD_MB_PADDING_HTFM_Collect(UChar *ref,UChar *cur,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_PADDING_HTFM(UChar *ref,UChar *cur,Int dmin,Int lx,void *vptr)
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    Int SAD_MB_PAD1(UChar *ref, UChar *cur, Int dmin, Int lx, Int *rep);
+
+
+    /*==================================================================
+        Function:   SAD_Macroblock
+        Date:       09/07/2000
+        Purpose:    Compute SAD 16x16 between blk and ref.
+        To do:      Uniform subsampling will be inserted later!
+                    Hypothesis Testing Fast Matching to be used later!
+        Changes:
+    11/7/00:     implemented MMX
+    1/24/01:     implemented SSE
+    ==================================================================*/
+    /********** C ************/
+    Int SAD_Macroblock_C(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info)
+    {
+        int32 x10;
+        Int dmin = (ULong)dmin_lx >> 16;
+        Int lx = dmin_lx & 0xFFFF;
+
+        OSCL_UNUSED_ARG(extra_info);
+
+        NUM_SAD_MB_CALL();
+
+        x10 = simd_sad_mb(ref, blk, dmin, lx);
+
+        return x10;
+    }
+
+#ifdef HTFM   /* HTFM with uniform subsampling implementation, 2/28/01 */
+    /*===============================================================
+        Function:   SAD_MB_HTFM_Collect and SAD_MB_HTFM
+        Date:       3/2/1
+        Purpose:    Compute the SAD on a 16x16 block using
+                    uniform subsampling and hypothesis testing fast matching
+                    for early dropout. SAD_MB_HP_HTFM_Collect is to collect
+                    the statistics to compute the thresholds to be used in
+                    SAD_MB_HP_HTFM.
+        Input/Output:
+        Changes:
+      ===============================================================*/
+
+    Int SAD_MB_HTFM_Collect(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info)
+    {
+        Int i;
+        Int sad = 0;
+        UChar *p1;
+        Int lx4 = (dmin_lx << 2) & 0x3FFFC;
+        ULong cur_word;
+        Int saddata[16], tmp, tmp2;    /* used when collecting flag (global) is on */
+        Int difmad;
+        HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+        Int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+        UInt *countbreak = &(htfm_stat->countbreak);
+        Int *offsetRef = htfm_stat->offsetRef;
+
+        NUM_SAD_MB_CALL();
+
+        blk -= 4;
+        for (i = 0; i < 16; i++)
+        {
+            p1 = ref + offsetRef[i];
+            cur_word = *((ULong*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = (cur_word >> 24) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[8];
+            tmp2 = (cur_word >> 16) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[4];
+            tmp2 = (cur_word >> 8) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[0];
+            p1 += lx4;
+            tmp2 = (cur_word & 0xFF);
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            cur_word = *((ULong*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = (cur_word >> 24) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[8];
+            tmp2 = (cur_word >> 16) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[4];
+            tmp2 = (cur_word >> 8) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[0];
+            p1 += lx4;
+            tmp2 = (cur_word & 0xFF);
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            cur_word = *((ULong*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = (cur_word >> 24) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[8];
+            tmp2 = (cur_word >> 16) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[4];
+            tmp2 = (cur_word >> 8) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[0];
+            p1 += lx4;
+            tmp2 = (cur_word & 0xFF);
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            cur_word = *((ULong*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = (cur_word >> 24) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[8];
+            tmp2 = (cur_word >> 16) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[4];
+            tmp2 = (cur_word >> 8) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[0];
+            p1 += lx4;
+            tmp2 = (cur_word & 0xFF);
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            NUM_SAD_MB();
+
+            saddata[i] = sad;
+
+            if (i > 0)
+            {
+                if ((ULong)sad > ((ULong)dmin_lx >> 16))
+                {
+                    difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+                    (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+                    (*countbreak)++;
+                    return sad;
+                }
+            }
+        }
+
+        difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+        (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+        (*countbreak)++;
+        return sad;
+    }
+
+    Int SAD_MB_HTFM(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info)
+    {
+        Int sad = 0;
+        UChar *p1;
+
+        Int i;
+        Int tmp, tmp2;
+        Int lx4 = (dmin_lx << 2) & 0x3FFFC;
+        Int sadstar = 0, madstar;
+        Int *nrmlz_th = (Int*) extra_info;
+        Int *offsetRef = (Int*) extra_info + 32;
+        ULong cur_word;
+
+        madstar = (ULong)dmin_lx >> 20;
+
+        NUM_SAD_MB_CALL();
+
+        blk -= 4;
+        for (i = 0; i < 16; i++)
+        {
+            p1 = ref + offsetRef[i];
+            cur_word = *((ULong*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = (cur_word >> 24) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[8];
+            tmp2 = (cur_word >> 16) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[4];
+            tmp2 = (cur_word >> 8) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[0];
+            p1 += lx4;
+            tmp2 = (cur_word & 0xFF);
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            cur_word = *((ULong*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = (cur_word >> 24) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[8];
+            tmp2 = (cur_word >> 16) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[4];
+            tmp2 = (cur_word >> 8) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[0];
+            p1 += lx4;
+            tmp2 = (cur_word & 0xFF);
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            cur_word = *((ULong*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = (cur_word >> 24) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[8];
+            tmp2 = (cur_word >> 16) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[4];
+            tmp2 = (cur_word >> 8) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[0];
+            p1 += lx4;
+            tmp2 = (cur_word & 0xFF);
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            cur_word = *((ULong*)(blk += 4));
+            tmp = p1[12];
+            tmp2 = (cur_word >> 24) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[8];
+            tmp2 = (cur_word >> 16) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[4];
+            tmp2 = (cur_word >> 8) & 0xFF;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = p1[0];
+            p1 += lx4;
+            tmp2 = (cur_word & 0xFF);
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            NUM_SAD_MB();
+
+            sadstar += madstar;
+            if (((ULong)sad <= ((ULong)dmin_lx >> 16)) && (sad <= (sadstar - *nrmlz_th++)))
+                ;
+            else
+                return 65536;
+        }
+
+        return sad;
+    }
+#endif /* HTFM */
+
+#ifndef NO_INTER4V
+    /*==================================================================
+        Function:   SAD_Block
+        Date:       09/07/2000
+        Purpose:    Compute SAD 16x16 between blk and ref.
+        To do:      Uniform subsampling will be inserted later!
+                    Hypothesis Testing Fast Matching to be used later!
+        Changes:
+    11/7/00:     implemented MMX
+    1/24/01:     implemented SSE
+      ==================================================================*/
+    /********** C ************/
+    Int SAD_Block_C(UChar *ref, UChar *blk, Int dmin, Int lx, void *)
+    {
+        Int sad = 0;
+
+        Int i;
+        UChar *ii;
+        Int *kk;
+        Int tmp, tmp2, tmp3, mask = 0xFF;
+        Int width = (lx - 32);
+
+        NUM_SAD_BLK_CALL();
+
+        ii = ref;
+        kk  = (Int*)blk; /* assuming word-align for blk */
+        for (i = 0; i < 8; i++)
+        {
+            tmp3 = kk[1];
+            tmp = ii[7];
+            tmp2 = (UInt)tmp3 >> 24;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = ii[6];
+            tmp2 = (tmp3 >> 16) & mask;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = ii[5];
+            tmp2 = (tmp3 >> 8) & mask;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = ii[4];
+            tmp2 = tmp3 & mask;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp3 = *kk;
+            kk += (width >> 2);
+            tmp = ii[3];
+            tmp2 = (UInt)tmp3 >> 24;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = ii[2];
+            tmp2 = (tmp3 >> 16) & mask;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = ii[1];
+            tmp2 = (tmp3 >> 8) & mask;
+            sad = SUB_SAD(sad, tmp, tmp2);
+            tmp = *ii;
+            ii += lx;
+            tmp2 = tmp3 & mask;
+            sad = SUB_SAD(sad, tmp, tmp2);
+
+            NUM_SAD_BLK();
+
+            if (sad > dmin)
+                return sad;
+        }
+
+        return sad;
+    }
+
+#endif /* NO_INTER4V */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp
new file mode 100644
index 0000000..f05697c
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp
@@ -0,0 +1,855 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/* contains
+Int HalfPel1_SAD_MB(UChar *ref,UChar *blk,Int dmin,Int width,Int ih,Int jh)
+Int HalfPel2_SAD_MB(UChar *ref,UChar *blk,Int dmin,Int width)
+Int HalfPel1_SAD_Blk(UChar *ref,UChar *blk,Int dmin,Int width,Int ih,Int jh)
+Int HalfPel2_SAD_Blk(UChar *ref,UChar *blk,Int dmin,Int width)
+
+Int SAD_MB_HalfPel_C(UChar *ref,UChar *blk,Int dmin,Int width,Int rx,Int xh,Int yh,void *extra_info)
+Int SAD_MB_HP_HTFM_Collect(UChar *ref,UChar *blk,Int dmin,Int width,Int rx,Int xh,Int yh,void *extra_info)
+Int SAD_MB_HP_HTFM(UChar *ref,UChar *blk,Int dmin,Int width,Int rx,Int xh,Int yh,void *extra_info)
+Int SAD_Blk_HalfPel_C(UChar *ref,UChar *blk,Int dmin,Int width,Int rx,Int xh,Int yh,void *extra_info)
+*/
+
+//#include <stdlib.h> /* for RAND_MAX */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "sad_halfpel_inline.h"
+
+#ifdef _SAD_STAT
+ULong num_sad_HP_MB = 0;
+ULong num_sad_HP_Blk = 0;
+ULong num_sad_HP_MB_call = 0;
+ULong num_sad_HP_Blk_call = 0;
+#define NUM_SAD_HP_MB_CALL()    num_sad_HP_MB_call++
+#define NUM_SAD_HP_MB()         num_sad_HP_MB++
+#define NUM_SAD_HP_BLK_CALL()   num_sad_HP_Blk_call++
+#define NUM_SAD_HP_BLK()        num_sad_HP_Blk++
+#else
+#define NUM_SAD_HP_MB_CALL()
+#define NUM_SAD_HP_MB()
+#define NUM_SAD_HP_BLK_CALL()
+#define NUM_SAD_HP_BLK()
+#endif
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    /*==================================================================
+        Function:   HalfPel1_SAD_MB
+        Date:       03/27/2001
+        Purpose:    Compute SAD 16x16 between blk and ref in halfpel
+                    resolution,
+        Changes:
+      ==================================================================*/
+    /* One component is half-pel */
+    Int HalfPel1_SAD_MB(UChar *ref, UChar *blk, Int dmin, Int width, Int ih, Int jh)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *kk, *p1, *p2;
+        Int temp;
+
+        OSCL_UNUSED_ARG(jh);
+
+        p1 = ref;
+        if (ih) p2 = ref + 1;
+        else p2 = ref + width;
+        kk  = blk;
+
+        for (i = 0; i < 16; i++)
+        {
+            for (j = 0; j < 16; j++)
+            {
+
+                temp = ((p1[j] + p2[j] + 1) >> 1) - *kk++;
+                sad += PV_ABS(temp);
+            }
+
+            if (sad > dmin)
+                return sad;
+            p1 += width;
+            p2 += width;
+        }
+        return sad;
+    }
+
+    /* Two components need half-pel */
+    Int HalfPel2_SAD_MB(UChar *ref, UChar *blk, Int dmin, Int width)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *kk, *p1, *p2, *p3, *p4;
+        Int temp;
+
+        p1 = ref;
+        p2 = ref + 1;
+        p3 = ref + width;
+        p4 = ref + width + 1;
+        kk  = blk;
+
+        for (i = 0; i < 16; i++)
+        {
+            for (j = 0; j < 16; j++)
+            {
+
+                temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - *kk++;
+                sad += PV_ABS(temp);
+            }
+
+            if (sad > dmin)
+                return sad;
+
+            p1 += width;
+            p3 += width;
+            p2 += width;
+            p4 += width;
+        }
+        return sad;
+    }
+
+#ifndef NO_INTER4V
+    /*==================================================================
+        Function:   HalfPel1_SAD_Blk
+        Date:       03/27/2001
+        Purpose:    Compute SAD 8x8 between blk and ref in halfpel
+                    resolution.
+        Changes:
+      ==================================================================*/
+    /* One component needs half-pel */
+    Int HalfPel1_SAD_Blk(UChar *ref, UChar *blk, Int dmin, Int width, Int ih, Int jh)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *kk, *p1, *p2;
+        Int temp;
+
+        OSCL_UNUSED_ARG(jh);
+
+        p1 = ref;
+        if (ih) p2 = ref + 1;
+        else p2 = ref + width;
+        kk  = blk;
+
+        for (i = 0; i < 8; i++)
+        {
+            for (j = 0; j < 8; j++)
+            {
+
+                temp = ((p1[j] + p2[j] + 1) >> 1) - *kk++;
+                sad += PV_ABS(temp);
+            }
+
+            if (sad > dmin)
+                return sad;
+            p1 += width;
+            p2 += width;
+            kk += 8;
+        }
+        return sad;
+    }
+    /* Two components need half-pel */
+    Int HalfPel2_SAD_Blk(UChar *ref, UChar *blk, Int dmin, Int width)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *kk, *p1, *p2, *p3, *p4;
+        Int temp;
+
+        p1 = ref;
+        p2 = ref + 1;
+        p3 = ref + width;
+        p4 = ref + width + 1;
+        kk  = blk;
+
+        for (i = 0; i < 8; i++)
+        {
+            for (j = 0; j < 8; j++)
+            {
+
+                temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - *kk++;
+                sad += PV_ABS(temp);
+            }
+
+            if (sad > dmin)
+                return sad;
+
+            p1 += width;
+            p3 += width;
+            p2 += width;
+            p4 += width;
+            kk += 8;
+        }
+        return sad;
+    }
+#endif // NO_INTER4V
+    /*===============================================================
+        Function:   SAD_MB_HalfPel
+        Date:       09/17/2000
+        Purpose:    Compute the SAD on the half-pel resolution
+        Input/Output:   hmem is assumed to be a pointer to the starting
+                    point of the search in the 33x33 matrix search region
+        Changes:
+    11/7/00:     implemented MMX
+      ===============================================================*/
+    /*==================================================================
+        Function:   SAD_MB_HalfPel_C
+        Date:       04/30/2001
+        Purpose:    Compute SAD 16x16 between blk and ref in halfpel
+                    resolution,
+        Changes:
+      ==================================================================*/
+    /* One component is half-pel */
+    Int SAD_MB_HalfPel_Cxhyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *kk, *p1, *p2, *p3, *p4;
+//  Int sumref=0;
+        Int temp;
+        Int rx = dmin_rx & 0xFFFF;
+
+        OSCL_UNUSED_ARG(extra_info);
+
+        NUM_SAD_HP_MB_CALL();
+
+        p1 = ref;
+        p2 = ref + 1;
+        p3 = ref + rx;
+        p4 = ref + rx + 1;
+        kk  = blk;
+
+        for (i = 0; i < 16; i++)
+        {
+            for (j = 0; j < 16; j++)
+            {
+
+                temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - *kk++;
+                sad += PV_ABS(temp);
+            }
+
+            NUM_SAD_HP_MB();
+
+            if (sad > (Int)((ULong)dmin_rx >> 16))
+                return sad;
+
+            p1 += rx;
+            p3 += rx;
+            p2 += rx;
+            p4 += rx;
+        }
+        return sad;
+    }
+
+    Int SAD_MB_HalfPel_Cyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *kk, *p1, *p2;
+//  Int sumref=0;
+        Int temp;
+        Int rx = dmin_rx & 0xFFFF;
+
+        OSCL_UNUSED_ARG(extra_info);
+
+        NUM_SAD_HP_MB_CALL();
+
+        p1 = ref;
+        p2 = ref + rx; /* either left/right or top/bottom pixel */
+        kk  = blk;
+
+        for (i = 0; i < 16; i++)
+        {
+            for (j = 0; j < 16; j++)
+            {
+
+                temp = ((p1[j] + p2[j] + 1) >> 1) - *kk++;
+                sad += PV_ABS(temp);
+            }
+
+            NUM_SAD_HP_MB();
+
+            if (sad > (Int)((ULong)dmin_rx >> 16))
+                return sad;
+            p1 += rx;
+            p2 += rx;
+        }
+        return sad;
+    }
+
+    Int SAD_MB_HalfPel_Cxh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *kk, *p1;
+//  Int sumref=0;
+        Int temp;
+        Int rx = dmin_rx & 0xFFFF;
+
+        OSCL_UNUSED_ARG(extra_info);
+
+        NUM_SAD_HP_MB_CALL();
+
+        p1 = ref;
+        kk  = blk;
+
+        for (i = 0; i < 16; i++)
+        {
+            for (j = 0; j < 16; j++)
+            {
+
+                temp = ((p1[j] + p1[j+1] + 1) >> 1) - *kk++;
+                sad += PV_ABS(temp);
+            }
+
+            NUM_SAD_HP_MB();
+
+            if (sad > (Int)((ULong)dmin_rx >> 16))
+                return sad;
+            p1 += rx;
+        }
+        return sad;
+    }
+
+#ifdef HTFM  /* HTFM with uniform subsampling implementation, 2/28/01 */
+
+//Checheck here
+    Int SAD_MB_HP_HTFM_Collectxhyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *p1, *p2;
+        Int rx = dmin_rx & 0xFFFF;
+        Int refwx4 = rx << 2;
+        Int saddata[16];      /* used when collecting flag (global) is on */
+        Int difmad, tmp, tmp2;
+        HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+        Int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+        UInt *countbreak = &(htfm_stat->countbreak);
+        Int *offsetRef = htfm_stat->offsetRef;
+        ULong cur_word;
+
+        NUM_SAD_HP_MB_CALL();
+
+        blk -= 4;
+
+        for (i = 0; i < 16; i++) /* 16 stages */
+        {
+            p1 = ref + offsetRef[i];
+            p2 = p1 + rx;
+
+            j = 4;/* 4 lines */
+            do
+            {
+                cur_word = *((ULong*)(blk += 4));
+                tmp = p1[12] + p2[12];
+                tmp2 = p1[13] + p2[13];
+                tmp += tmp2;
+                tmp2 = (cur_word >> 24) & 0xFF;
+                tmp += 2;
+                sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[8] + p2[8];
+                tmp2 = p1[9] + p2[9];
+                tmp += tmp2;
+                tmp2 = (cur_word >> 16) & 0xFF;
+                tmp += 2;
+                sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[4] + p2[4];
+                tmp2 = p1[5] + p2[5];
+                tmp += tmp2;
+                tmp2 = (cur_word >> 8) & 0xFF;
+                tmp += 2;
+                sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+                tmp2 = p1[1] + p2[1];
+                tmp = p1[0] + p2[0];
+                p1 += refwx4;
+                p2 += refwx4;
+                tmp += tmp2;
+                tmp2 = (cur_word & 0xFF);
+                tmp += 2;
+                sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+            }
+            while (--j);
+
+            NUM_SAD_HP_MB();
+
+            saddata[i] = sad;
+
+            if (i > 0)
+            {
+                if (sad > (Int)((ULong)dmin_rx >> 16))
+                {
+                    difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+                    (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+                    (*countbreak)++;
+                    return sad;
+                }
+            }
+        }
+        difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+        (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+        (*countbreak)++;
+
+        return sad;
+    }
+
+    Int SAD_MB_HP_HTFM_Collectyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *p1, *p2;
+        Int rx = dmin_rx & 0xFFFF;
+        Int refwx4 = rx << 2;
+        Int saddata[16];      /* used when collecting flag (global) is on */
+        Int difmad, tmp, tmp2;
+        HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+        Int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+        UInt *countbreak = &(htfm_stat->countbreak);
+        Int *offsetRef = htfm_stat->offsetRef;
+        ULong cur_word;
+
+        NUM_SAD_HP_MB_CALL();
+
+        blk -= 4;
+
+        for (i = 0; i < 16; i++) /* 16 stages */
+        {
+            p1 = ref + offsetRef[i];
+            p2 = p1 + rx;
+            j = 4;
+            do
+            {
+                cur_word = *((ULong*)(blk += 4));
+                tmp = p1[12];
+                tmp2 = p2[12];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 24) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[8];
+                tmp2 = p2[8];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 16) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[4];
+                tmp2 = p2[4];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 8) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[0];
+                p1 += refwx4;
+                tmp2 = p2[0];
+                p2 += refwx4;
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word & 0xFF);
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            }
+            while (--j);
+
+            NUM_SAD_HP_MB();
+
+            saddata[i] = sad;
+
+            if (i > 0)
+            {
+                if (sad > (Int)((ULong)dmin_rx >> 16))
+                {
+                    difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+                    (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+                    (*countbreak)++;
+                    return sad;
+                }
+            }
+        }
+        difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+        (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+        (*countbreak)++;
+
+        return sad;
+    }
+
+    Int SAD_MB_HP_HTFM_Collectxh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *p1;
+        Int rx = dmin_rx & 0xFFFF;
+        Int refwx4 = rx << 2;
+        Int saddata[16];      /* used when collecting flag (global) is on */
+        Int difmad, tmp, tmp2;
+        HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+        Int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+        UInt *countbreak = &(htfm_stat->countbreak);
+        Int *offsetRef = htfm_stat->offsetRef;
+        ULong cur_word;
+
+        NUM_SAD_HP_MB_CALL();
+
+        blk -= 4;
+
+        for (i = 0; i < 16; i++) /* 16 stages */
+        {
+            p1 = ref + offsetRef[i];
+
+            j = 4; /* 4 lines */
+            do
+            {
+                cur_word = *((ULong*)(blk += 4));
+                tmp = p1[12];
+                tmp2 = p1[13];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 24) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[8];
+                tmp2 = p1[9];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 16) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[4];
+                tmp2 = p1[5];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 8) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[0];
+                tmp2 = p1[1];
+                p1 += refwx4;
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word & 0xFF);
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            }
+            while (--j);
+
+            NUM_SAD_HP_MB();
+
+            saddata[i] = sad;
+
+            if (i > 0)
+            {
+                if (sad > (Int)((ULong)dmin_rx >> 16))
+                {
+                    difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+                    (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+                    (*countbreak)++;
+                    return sad;
+                }
+            }
+        }
+        difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+        (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+        (*countbreak)++;
+
+        return sad;
+    }
+
+    Int SAD_MB_HP_HTFMxhyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0, tmp, tmp2;
+        UChar *p1, *p2;
+        Int rx = dmin_rx & 0xFFFF;
+        Int refwx4 = rx << 2;
+        Int sadstar = 0, madstar;
+        Int *nrmlz_th = (Int*) extra_info;
+        Int *offsetRef = nrmlz_th + 32;
+        ULong cur_word;
+
+        madstar = (ULong)dmin_rx >> 20;
+
+        NUM_SAD_HP_MB_CALL();
+
+        blk -= 4;
+
+        for (i = 0; i < 16; i++) /* 16 stages */
+        {
+            p1 = ref + offsetRef[i];
+            p2 = p1 + rx;
+
+            j = 4; /* 4 lines */
+            do
+            {
+                cur_word = *((ULong*)(blk += 4));
+                tmp = p1[12] + p2[12];
+                tmp2 = p1[13] + p2[13];
+                tmp += tmp2;
+                tmp2 = (cur_word >> 24) & 0xFF;
+                tmp += 2;
+                sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[8] + p2[8];
+                tmp2 = p1[9] + p2[9];
+                tmp += tmp2;
+                tmp2 = (cur_word >> 16) & 0xFF;
+                tmp += 2;
+                sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[4] + p2[4];
+                tmp2 = p1[5] + p2[5];
+                tmp += tmp2;
+                tmp2 = (cur_word >> 8) & 0xFF;
+                tmp += 2;
+                sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+                tmp2 = p1[1] + p2[1];
+                tmp = p1[0] + p2[0];
+                p1 += refwx4;
+                p2 += refwx4;
+                tmp += tmp2;
+                tmp2 = (cur_word & 0xFF);
+                tmp += 2;
+                sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+            }
+            while (--j);
+
+            NUM_SAD_HP_MB();
+
+            sadstar += madstar;
+            if (sad > sadstar - nrmlz_th[i] || sad > (Int)((ULong)dmin_rx >> 16))
+            {
+                return 65536;
+            }
+        }
+
+        return sad;
+    }
+
+    Int SAD_MB_HP_HTFMyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0, tmp, tmp2;
+        UChar *p1, *p2;
+        Int rx = dmin_rx & 0xFFFF;
+        Int refwx4 = rx << 2;
+        Int sadstar = 0, madstar;
+        Int *nrmlz_th = (Int*) extra_info;
+        Int *offsetRef = nrmlz_th + 32;
+        ULong cur_word;
+
+        madstar = (ULong)dmin_rx >> 20;
+
+        NUM_SAD_HP_MB_CALL();
+
+        blk -= 4;
+
+        for (i = 0; i < 16; i++) /* 16 stages */
+        {
+            p1 = ref + offsetRef[i];
+            p2 = p1 + rx;
+            j = 4;
+            do
+            {
+                cur_word = *((ULong*)(blk += 4));
+                tmp = p1[12];
+                tmp2 = p2[12];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 24) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[8];
+                tmp2 = p2[8];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 16) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[4];
+                tmp2 = p2[4];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 8) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[0];
+                p1 += refwx4;
+                tmp2 = p2[0];
+                p2 += refwx4;
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word & 0xFF);
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            }
+            while (--j);
+
+            NUM_SAD_HP_MB();
+            sadstar += madstar;
+            if (sad > sadstar - nrmlz_th[i] || sad > (Int)((ULong)dmin_rx >> 16))
+            {
+                return 65536;
+            }
+        }
+
+        return sad;
+    }
+
+    Int SAD_MB_HP_HTFMxh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0, tmp, tmp2;
+        UChar *p1;
+        Int rx = dmin_rx & 0xFFFF;
+        Int refwx4 = rx << 2;
+        Int sadstar = 0, madstar;
+        Int *nrmlz_th = (Int*) extra_info;
+        Int *offsetRef = nrmlz_th + 32;
+        ULong cur_word;
+
+        madstar = (ULong)dmin_rx >> 20;
+
+        NUM_SAD_HP_MB_CALL();
+
+        blk -= 4;
+
+        for (i = 0; i < 16; i++) /* 16 stages */
+        {
+            p1 = ref + offsetRef[i];
+
+            j = 4;/* 4 lines */
+            do
+            {
+                cur_word = *((ULong*)(blk += 4));
+                tmp = p1[12];
+                tmp2 = p1[13];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 24) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[8];
+                tmp2 = p1[9];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 16) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[4];
+                tmp2 = p1[5];
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word >> 8) & 0xFF;
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+                tmp = p1[0];
+                tmp2 = p1[1];
+                p1 += refwx4;
+                tmp++;
+                tmp2 += tmp;
+                tmp = (cur_word & 0xFF);
+                sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+            }
+            while (--j);
+
+            NUM_SAD_HP_MB();
+
+            sadstar += madstar;
+            if (sad > sadstar - nrmlz_th[i] || sad > (Int)((ULong)dmin_rx >> 16))
+            {
+                return 65536;
+            }
+        }
+
+        return sad;
+    }
+
+#endif /* HTFM */
+
+#ifndef NO_INTER4V
+    /*==================================================================
+        Function:   SAD_Blk_HalfPel_C
+        Date:       04/30/2001
+        Purpose:    Compute SAD 16x16 between blk and ref in halfpel
+                    resolution,
+        Changes:
+      ==================================================================*/
+    /* One component is half-pel */
+    Int SAD_Blk_HalfPel_C(UChar *ref, UChar *blk, Int dmin, Int width, Int rx, Int xh, Int yh, void *extra_info)
+    {
+        Int i, j;
+        Int sad = 0;
+        UChar *kk, *p1, *p2, *p3, *p4;
+        Int temp;
+
+        OSCL_UNUSED_ARG(extra_info);
+
+        NUM_SAD_HP_BLK_CALL();
+
+        if (xh && yh)
+        {
+            p1 = ref;
+            p2 = ref + xh;
+            p3 = ref + yh * rx;
+            p4 = ref + yh * rx + xh;
+            kk  = blk;
+
+            for (i = 0; i < 8; i++)
+            {
+                for (j = 0; j < 8; j++)
+                {
+
+                    temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - kk[j];
+                    sad += PV_ABS(temp);
+                }
+
+                NUM_SAD_HP_BLK();
+
+                if (sad > dmin)
+                    return sad;
+
+                p1 += rx;
+                p3 += rx;
+                p2 += rx;
+                p4 += rx;
+                kk += width;
+            }
+            return sad;
+        }
+        else
+        {
+            p1 = ref;
+            p2 = ref + xh + yh * rx; /* either left/right or top/bottom pixel */
+
+            kk  = blk;
+
+            for (i = 0; i < 8; i++)
+            {
+                for (j = 0; j < 8; j++)
+                {
+
+                    temp = ((p1[j] + p2[j] + 1) >> 1) - kk[j];
+                    sad += PV_ABS(temp);
+                }
+
+                NUM_SAD_HP_BLK();
+
+                if (sad > dmin)
+                    return sad;
+                p1 += rx;
+                p2 += rx;
+                kk += width;
+            }
+            return sad;
+        }
+    }
+#endif /* NO_INTER4V */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
new file mode 100644
index 0000000..d55778f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
@@ -0,0 +1,130 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/*  Filename: sad_halfpel_inline.h                                                      */
+/*  Description: Implementation for in-line functions used in dct.cpp           */
+/*  Modified:                                                                   */
+/*********************************************************************************/
+
+#ifndef _SAD_HALFPEL_INLINE_H_
+#define _SAD_HALFPEL_INLINE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) /* ARM GNU COMPILER  */
+
+    __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        tmp = (tmp2 >> 1) - tmp;
+        if (tmp > 0) sad += tmp;
+        else sad -= tmp;
+
+        return sad;
+    }
+
+    __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        tmp = (tmp >> 2) - tmp2;
+        if (tmp > 0) sad += tmp;
+        else sad -= tmp;
+
+        return sad;
+    }
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+    __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        __asm
+        {
+            rsbs    tmp, tmp, tmp2, asr #1 ;
+            rsbmi   tmp, tmp, #0 ;
+            add     sad, sad, tmp ;
+        }
+
+        return sad;
+    }
+
+    __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        __asm
+        {
+            rsbs    tmp, tmp2, tmp, asr #2 ;
+            rsbmi   tmp, tmp, #0 ;
+            add     sad, sad, tmp ;
+        }
+
+        return sad;
+    }
+
+#elif ( defined(PV_ARM_GCC_V5) || defined(PV_ARM_GCC_V4) ) /* ARM GNU COMPILER  */
+
+
+    __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        register int32 out;
+        register int32 temp1;
+        register int32 ss = sad;
+        register int32 tt = tmp;
+        register int32 uu = tmp2;
+
+        asm volatile("rsbs	%1, %3, %4, asr #1\n\t"
+                     "rsbmi %1, %1, #0\n\t"
+                     "add  %0, %2, %1"
+             : "=&r"(out),
+                     "=&r"(temp1)
+                             : "r"(ss),
+                             "r"(tt),
+                             "r"(uu));
+        return out;
+    }
+
+
+    __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+{
+        register int32 out;
+        register int32 temp1;
+        register int32 ss = sad;
+        register int32 tt = tmp;
+        register int32 uu = tmp2;
+
+        asm volatile("rsbs      %1, %4, %3, asr #2\n\t"
+                     "rsbmi %1, %1, #0\n\t"
+                     "add  %0, %2, %1"
+             : "=&r"(out),
+                     "=&r"(temp1)
+                             : "r"(ss),
+                             "r"(tt),
+                             "r"(uu));
+        return out;
+    }
+
+
+#endif // Diff OS
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_SAD_HALFPEL_INLINE_H_
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h
new file mode 100644
index 0000000..ba77dfd
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h
@@ -0,0 +1,539 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/*  Filename: sad_inline.h                                                      */
+/*  Description: Implementation for in-line functions used in dct.cpp           */
+/*  Modified:                                                                   */
+/*********************************************************************************/
+#ifndef _SAD_INLINE_H_
+#define _SAD_INLINE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) /* ARM GNU COMPILER  */
+
+    __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        tmp = tmp - tmp2;
+        if (tmp > 0) sad += tmp;
+        else sad -= tmp;
+
+        return sad;
+    }
+
+    __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+    {
+        int32 x7;
+
+        x7 = src2 ^ src1;       /* check odd/even combination */
+        if ((uint32)src2 >= (uint32)src1)
+        {
+            src1 = src2 - src1;     /* subs */
+        }
+        else
+        {
+            src1 = src1 - src2;
+        }
+        x7 = x7 ^ src1;     /* only odd bytes need to add carry */
+        x7 = mask & ((uint32)x7 >> 1);
+        x7 = (x7 << 8) - x7;
+        src1 = src1 + (x7 >> 7); /* add 0xFF to the negative byte, add back carry */
+        src1 = src1 ^(x7 >> 7);   /* take absolute value of negative byte */
+
+        return src1;
+    }
+
+#define NUMBER 3
+#define SHIFT 24
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#include "sad_mb_offset.h"
+
+
+    __inline int32 simd_sad_mb(UChar *ref, UChar *blk, Int dmin, Int lx)
+    {
+        int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+        x9 = 0x80808080; /* const. */
+
+        x8 = (uint32)ref & 0x3;
+        if (x8 == 3)
+            goto SadMBOffset3;
+        if (x8 == 2)
+            goto SadMBOffset2;
+        if (x8 == 1)
+            goto SadMBOffset1;
+
+//  x5 = (x4<<8)-x4; /* x5 = x4*255; */
+        x4 = x5 = 0;
+
+        x6 = 0xFFFF00FF;
+
+        ref -= lx;
+        blk -= 16;
+
+        x8 = 16;
+
+LOOP_SAD0:
+        /****** process 8 pixels ******/
+        x10 = *((uint32*)(ref += lx));
+        x11 = *((uint32*)(ref + 4));
+        x12 = *((uint32*)(blk += 16));
+        x14 = *((uint32*)(blk + 4));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10; /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8);  /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****** process 8 pixels ******/
+        x10 = *((uint32*)(ref + 8));
+        x11 = *((uint32*)(ref + 12));
+        x12 = *((uint32*)(blk + 8));
+        x14 = *((uint32*)(blk + 12));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****************/
+        x10 = x5 - (x4 << 8); /* extract low bytes */
+        x10 = x10 + x4;     /* add with high bytes */
+        x10 = x10 + (x10 << 16); /* add with lower half word */
+
+        if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+        {
+            if (--x8)
+            {
+                goto LOOP_SAD0;
+            }
+
+        }
+
+        return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+        return sad_mb_offset3(ref, blk, lx, dmin);
+
+SadMBOffset2:
+
+        return sad_mb_offset2(ref, blk, lx, dmin);
+
+SadMBOffset1:
+
+        return sad_mb_offset1(ref, blk, lx, dmin);
+
+    }
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+    __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        __asm
+        {
+            rsbs    tmp, tmp, tmp2 ;
+            rsbmi   tmp, tmp, #0 ;
+            add     sad, sad, tmp ;
+        }
+
+        return sad;
+    }
+
+    __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+    {
+        int32 x7;
+
+        __asm
+        {
+            EOR     x7, src2, src1;     /* check odd/even combination */
+            SUBS    src1, src2, src1;
+            EOR     x7, x7, src1;
+            AND     x7, mask, x7, lsr #1;
+            ORRCC   x7, x7, #0x80000000;
+            RSB     x7, x7, x7, lsl #8;
+            ADD     src1, src1, x7, asr #7;   /* add 0xFF to the negative byte, add back carry */
+            EOR     src1, src1, x7, asr #7;   /* take absolute value of negative byte */
+        }
+
+        return src1;
+    }
+
+    __inline int32 sad_4pixelN(int32 src1, int32 src2, int32 mask)
+    {
+        int32 x7;
+
+        __asm
+        {
+            EOR      x7, src2, src1;        /* check odd/even combination */
+            ADDS     src1, src2, src1;
+            EOR      x7, x7, src1;      /* only odd bytes need to add carry */
+            ANDS     x7, mask, x7, rrx;
+            RSB      x7, x7, x7, lsl #8;
+            SUB      src1, src1, x7, asr #7;  /* add 0xFF to the negative byte, add back carry */
+            EOR      src1, src1, x7, asr #7; /* take absolute value of negative byte */
+        }
+
+        return src1;
+    }
+
+#define sum_accumulate  __asm{      SBC      x5, x5, x10;  /* accumulate low bytes */ \
+        BIC      x10, x6, x10;   /* x10 & 0xFF00FF00 */ \
+        ADD      x4, x4, x10,lsr #8;   /* accumulate high bytes */ \
+        SBC      x5, x5, x11;    /* accumulate low bytes */ \
+        BIC      x11, x6, x11;   /* x11 & 0xFF00FF00 */ \
+        ADD      x4, x4, x11,lsr #8; } /* accumulate high bytes */
+
+
+#define NUMBER 3
+#define SHIFT 24
+#define INC_X8 0x08000001
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#undef INC_X8
+#define INC_X8 0x10000001
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#undef INC_X8
+#define INC_X8 0x08000001
+#include "sad_mb_offset.h"
+
+
+    __inline int32 simd_sad_mb(UChar *ref, UChar *blk, Int dmin, Int lx)
+    {
+        int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+        x9 = 0x80808080; /* const. */
+        x4 = x5 = 0;
+
+        __asm
+        {
+            MOVS    x8, ref, lsl #31 ;
+            BHI     SadMBOffset3;
+            BCS     SadMBOffset2;
+            BMI     SadMBOffset1;
+
+            MVN     x6, #0xFF00;
+        }
+LOOP_SAD0:
+        /****** process 8 pixels ******/
+        x11 = *((int32*)(ref + 12));
+        x10 = *((int32*)(ref + 8));
+        x14 = *((int32*)(blk + 12));
+        x12 = *((int32*)(blk + 8));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        __asm
+        {
+            /****** process 8 pixels ******/
+            LDR     x11, [ref, #4];
+            LDR     x10, [ref], lx ;
+            LDR     x14, [blk, #4];
+            LDR     x12, [blk], #16 ;
+        }
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****************/
+        x10 = x5 - (x4 << 8); /* extract low bytes */
+        x10 = x10 + x4;     /* add with high bytes */
+        x10 = x10 + (x10 << 16); /* add with lower half word */
+
+        __asm
+        {
+            /****************/
+            RSBS    x11, dmin, x10, lsr #16;
+            ADDLSS  x8, x8, #0x10000001;
+            BLS     LOOP_SAD0;
+        }
+
+        return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+        return sad_mb_offset3(ref, blk, lx, dmin, x8);
+
+SadMBOffset2:
+
+        return sad_mb_offset2(ref, blk, lx, dmin, x8);
+
+SadMBOffset1:
+
+        return sad_mb_offset1(ref, blk, lx, dmin, x8);
+    }
+
+
+#elif ( defined(PV_ARM_GCC_V5) || defined(PV_ARM_GCC_V4) ) /* ARM GNU COMPILER  */
+
+    __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+    {
+        register int32 out;
+        register int32 temp1;
+        register int32 ss = sad;
+        register int32 tt = tmp;
+        register int32 uu = tmp2;
+
+        asm volatile("rsbs  %1, %4, %3\n\t"
+                     "rsbmi %1, %1, #0\n\t"
+                     "add   %0, %2, %1"
+             : "=&r"(out),
+                     "=&r"(temp1)
+                             : "r"(ss),
+                             "r"(tt),
+                             "r"(uu));
+        return out;
+    }
+
+    __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+{
+        register int32 out;
+        register int32 temp1;
+        register int32 s1 = src1;
+        register int32 s2 = src2;
+        register int32 mm = mask;
+
+        asm volatile("eor   %0, %3, %2\n\t"
+                     "subs  %1, %3, %2\n\t"
+                     "eor   %0, %0, %1\n\t"
+                     "and   %0, %4, %0, lsr #1\n\t"
+                     "orrcc %0, %0, #0x80000000\n\t"
+                     "rsb   %0, %0, %0, lsl #8\n\t"
+                     "add   %1, %1, %0, asr #7\n\t"
+                     "eor   %1, %1, %0, asr #7"
+             : "=&r"(out),
+                     "=&r"(temp1)
+                             : "r"(s1),
+                             "r"(s2),
+                             "r"(mm));
+
+        return temp1;
+    }
+
+    __inline int32 sad_4pixelN(int32 src1, int32 src2, int32 mask)
+{
+        register int32 out;
+        register int32 temp1;
+        register int32 s1 = src1;
+        register int32 s2 = src2;
+        register int32 mm = mask;
+
+        asm volatile("eor    %1, %3, %2\n\t"
+                     "adds   %0, %3, %2\n\t"
+                     "eor    %1, %1, %0\n\t"
+                     "ands   %1, %4, %1,rrx\n\t"
+                     "rsb    %1, %1, %1, lsl #8\n\t"
+                     "sub    %0, %0, %1, asr #7\n\t"
+                     "eor    %0, %0, %1, asr #7"
+             : "=&r"(out),
+                     "=&r"(temp1)
+                             : "r"(s1),
+                             "r"(s2),
+                             "r"(mm));
+
+        return (out);
+    }
+
+#define sum_accumulate asm volatile("sbc  %0, %0, %1\n\t" \
+                                "bic  %1, %4, %1\n\t" \
+                                "add  %2, %2, %1, lsr #8\n\t" \
+                                "sbc  %0, %0, %3\n\t" \
+                                "bic  %3, %4, %3\n\t" \
+                                "add  %2, %2, %3, lsr #8" \
+                                :"+r"(x5), "+r"(x10), "+r"(x4), "+r"(x11) \
+                                :"r"(x6));
+
+#define NUMBER 3
+#define SHIFT 24
+#define INC_X8 0x08000001
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#undef INC_X8
+#define INC_X8 0x10000001
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#undef INC_X8
+#define INC_X8 0x08000001
+#include "sad_mb_offset.h"
+
+
+    __inline int32 simd_sad_mb(UChar *ref, UChar *blk, Int dmin, Int lx)
+{
+        int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+        x9 = 0x80808080; /* const. */
+        x4 = x5 = 0;
+
+        x8 = (uint32)ref & 0x3;
+        if (x8 == 3)
+            goto SadMBOffset3;
+        if (x8 == 2)
+            goto SadMBOffset2;
+        if (x8 == 1)
+            goto SadMBOffset1;
+
+asm volatile("mvn %0, #0xFF00": "=r"(x6));
+
+LOOP_SAD0:
+        /****** process 8 pixels ******/
+        x11 = *((int32*)(ref + 12));
+        x10 = *((int32*)(ref + 8));
+        x14 = *((int32*)(blk + 12));
+        x12 = *((int32*)(blk + 8));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        asm volatile("ldr  %0, [%4, #4]\n\t"
+                     "ldr  %1, [%4], %6\n\t"
+                     "ldr  %2, [%5, #4]\n\t"
+                     "ldr  %3, [%5], #16"
+             : "=r"(x11), "=r"(x10), "=r"(x14), "=r"(x12), "+r"(ref), "+r"(blk)
+                             : "r"(lx));
+
+        /* process x11 & x14 */
+        x11 = sad_4pixel(x11, x14, x9);
+
+        /* process x12 & x10 */
+        x10 = sad_4pixel(x10, x12, x9);
+
+        x5 = x5 + x10;  /* accumulate low bytes */
+        x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+        x5 = x5 + x11;  /* accumulate low bytes */
+        x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+        x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+        /****************/
+        x10 = x5 - (x4 << 8); /* extract low bytes */
+        x10 = x10 + x4;     /* add with high bytes */
+        x10 = x10 + (x10 << 16); /* add with lower half word */
+
+        if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+        {
+            if (--x8)
+            {
+                goto LOOP_SAD0;
+            }
+
+        }
+
+        return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+        return sad_mb_offset3(ref, blk, lx, dmin);
+
+SadMBOffset2:
+
+        return sad_mb_offset2(ref, blk, lx, dmin);
+
+SadMBOffset1:
+
+        return sad_mb_offset1(ref, blk, lx, dmin);
+    }
+
+#endif // OS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _SAD_INLINE_H_
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h b/media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h
new file mode 100644
index 0000000..4c7b929
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h
@@ -0,0 +1,317 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/*  Filename: sad_mb_offset.h                                                       */
+/*  Description: Implementation for in-line functions used in dct.cpp           */
+/*  Modified:                                                                   */
+/*********************************************************************************/
+
+#if !defined(PV_ARM_GCC_V4) && !defined(PV_ARM_GCC_V5) /* ARM GNU COMPILER  */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(UChar *ref, UChar *blk, Int lx, Int dmin)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(UChar *ref, UChar *blk, Int lx, Int dmin)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(UChar *ref, UChar *blk, Int lx, Int dmin)
+#endif
+{
+    int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+    //  x5 = (x4<<8) - x4;
+    x4 = x5 = 0;
+    x6 = 0xFFFF00FF;
+    x9 = 0x80808080; /* const. */
+    ref -= NUMBER; /* bic ref, ref, #3 */
+    ref -= lx;
+    blk -= 16;
+    x8 = 16;
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+    /****** process 8 pixels ******/
+    x10 = *((uint32*)(ref += lx)); /* D C B A */
+    x11 = *((uint32*)(ref + 4));    /* H G F E */
+    x12 = *((uint32*)(ref + 8));    /* L K J I */
+
+    x10 = ((uint32)x10 >> SHIFT); /* 0 0 0 D */
+    x10 = x10 | (x11 << (32 - SHIFT));        /* G F E D */
+    x11 = ((uint32)x11 >> SHIFT); /* 0 0 0 H */
+    x11 = x11 | (x12 << (32 - SHIFT));        /* K J I H */
+
+    x12 = *((uint32*)(blk += 16));
+    x14 = *((uint32*)(blk + 4));
+
+    /* process x11 & x14 */
+    x11 = sad_4pixel(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixel(x10, x12, x9);
+
+    x5 = x5 + x10; /* accumulate low bytes */
+    x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+    x4 = x4 + ((uint32)x10 >> 8);  /* accumulate high bytes */
+    x5 = x5 + x11;  /* accumulate low bytes */
+    x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+    x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+    /****** process 8 pixels ******/
+    x10 = *((uint32*)(ref + 8)); /* D C B A */
+    x11 = *((uint32*)(ref + 12));   /* H G F E */
+    x12 = *((uint32*)(ref + 16));   /* L K J I */
+
+    x10 = ((uint32)x10 >> SHIFT); /* mvn x10, x10, lsr #24  = 0xFF 0xFF 0xFF ~D */
+    x10 = x10 | (x11 << (32 - SHIFT));        /* bic x10, x10, x11, lsl #8 = ~G ~F ~E ~D */
+    x11 = ((uint32)x11 >> SHIFT); /* 0xFF 0xFF 0xFF ~H */
+    x11 = x11 | (x12 << (32 - SHIFT));        /* ~K ~J ~I ~H */
+
+    x12 = *((uint32*)(blk + 8));
+    x14 = *((uint32*)(blk + 12));
+
+    /* process x11 & x14 */
+    x11 = sad_4pixel(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixel(x10, x12, x9);
+
+    x5 = x5 + x10; /* accumulate low bytes */
+    x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+    x4 = x4 + ((uint32)x10 >> 8);  /* accumulate high bytes */
+    x5 = x5 + x11;  /* accumulate low bytes */
+    x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+    x4 = x4 + ((uint32)x11 >> 8);  /* accumulate high bytes */
+
+    /****************/
+    x10 = x5 - (x4 << 8); /* extract low bytes */
+    x10 = x10 + x4;     /* add with high bytes */
+    x10 = x10 + (x10 << 16); /* add with lower half word */
+
+    if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+    {
+        if (--x8)
+        {
+#if (NUMBER==3)
+            goto         LOOP_SAD3;
+#elif (NUMBER==2)
+            goto         LOOP_SAD2;
+#elif (NUMBER==1)
+            goto         LOOP_SAD1;
+#endif
+        }
+
+    }
+
+    return ((uint32)x10 >> 16);
+}
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(UChar *ref, UChar *blk, Int lx, Int dmin, int32 x8)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(UChar *ref, UChar *blk, Int lx, Int dmin, int32 x8)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(UChar *ref, UChar *blk, Int lx, Int dmin, int32 x8)
+#endif
+{
+    int32 x4, x5, x6, x9, x10, x11, x12, x14;
+
+    x9 = 0x80808080; /* const. */
+    x4 = x5 = 0;
+
+    __asm{
+        MVN      x6, #0xff0000;
+        BIC      ref, ref, #3;
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+    }
+    /****** process 8 pixels ******/
+    x11 = *((int32*)(ref + 12));
+    x12 = *((int32*)(ref + 16));
+    x10 = *((int32*)(ref + 8));
+    x14 = *((int32*)(blk + 12));
+
+    __asm{
+        MVN      x10, x10, lsr #SHIFT;
+        BIC      x10, x10, x11, lsl #(32-SHIFT);
+        MVN      x11, x11, lsr #SHIFT;
+        BIC      x11, x11, x12, lsl #(32-SHIFT);
+
+        LDR      x12, [blk, #8];
+    }
+
+    /* process x11 & x14 */
+    x11 = sad_4pixelN(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixelN(x10, x12, x9);
+
+    sum_accumulate;
+
+    __asm{
+        /****** process 8 pixels ******/
+        LDR      x11, [ref, #4];
+        LDR      x12, [ref, #8];
+        LDR  x10, [ref], lx ;
+        LDR  x14, [blk, #4];
+
+        MVN      x10, x10, lsr #SHIFT;
+        BIC      x10, x10, x11, lsl #(32-SHIFT);
+        MVN      x11, x11, lsr #SHIFT;
+        BIC      x11, x11, x12, lsl #(32-SHIFT);
+
+        LDR      x12, [blk], #16;
+    }
+
+    /* process x11 & x14 */
+    x11 = sad_4pixelN(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixelN(x10, x12, x9);
+
+    sum_accumulate;
+
+    /****************/
+    x10 = x5 - (x4 << 8); /* extract low bytes */
+    x10 = x10 + x4;     /* add with high bytes */
+    x10 = x10 + (x10 << 16); /* add with lower half word */
+
+    __asm{
+        RSBS     x11, dmin, x10, lsr #16
+        ADDLSS   x8, x8, #INC_X8
+#if (NUMBER==3)
+        BLS      LOOP_SAD3;
+#elif (NUMBER==2)
+BLS      LOOP_SAD2;
+#elif (NUMBER==1)
+BLS      LOOP_SAD1;
+#endif
+    }
+
+    return ((uint32)x10 >> 16);
+}
+
+#elif ( defined(PV_ARM_GCC_V5) || defined(PV_ARM_GCC_V4) ) /* ARM GNU COMPILER  */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(UChar *ref, UChar *blk, Int lx, Int dmin)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(UChar *ref, UChar *blk, Int lx, Int dmin)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(UChar *ref, UChar *blk, Int lx, Int dmin)
+#endif
+{
+    int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+    //  x5 = (x4<<8) - x4;
+    x4 = x5 = 0;
+    x6 = 0xFFFF00FF;
+    x9 = 0x80808080; /* const. */
+    ref -= NUMBER; /* bic ref, ref, #3 */
+    ref -= lx;
+    x8 = 16;
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+    /****** process 8 pixels ******/
+    x10 = *((uint32*)(ref += lx)); /* D C B A */
+    x11 = *((uint32*)(ref + 4));    /* H G F E */
+    x12 = *((uint32*)(ref + 8));    /* L K J I */
+
+    int32 shift = SHIFT;
+    int32 shift2 = 32 - SHIFT;
+    asm volatile("ldr  %3, [%4, #4]\n\t"
+                 "mvn  %0, %0, lsr %5\n\t"
+                 "bic  %0, %0, %1, lsl %6\n\t"
+                 "mvn  %1, %1, lsr %5\n\t"
+                 "bic  %1, %1, %2, lsl %6\n\t"
+                 "ldr  %2, [%4, #8]"
+             : "+r"(x10), "+r"(x11), "+r"(x12), "=r"(x14)
+                         : "r"(blk), "r"(shift), "r"(shift2));
+
+    /* process x11 & x14 */
+    x11 = sad_4pixel(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixel(x10, x12, x9);
+
+    sum_accumulate;
+
+    /****** process 8 pixels ******/
+    x10 = *((uint32*)(ref + 8)); /* D C B A */
+    x11 = *((uint32*)(ref + 12));   /* H G F E */
+    x12 = *((uint32*)(ref + 16));   /* L K J I */
+
+    asm volatile("ldr  %3, [%4, #4]\n\t"
+                 "mvn  %0, %0, lsr %5\n\t"
+                 "bic  %0, %0, %1, lsl %6\n\t"
+                 "mvn  %1, %1, lsr %5\n\t"
+                 "bic  %1, %1, %2, lsl %6\n\t"
+                 "ldr  %2, [%4, #8]"
+             : "+r"(x10), "+r"(x11), "+r"(x12), "=r"(x14)
+                         : "r"(blk), "r"(shift), "r"(shift2));
+
+    /* process x11 & x14 */
+    x11 = sad_4pixel(x11, x14, x9);
+
+    /* process x12 & x10 */
+    x10 = sad_4pixel(x10, x12, x9);
+
+    sum_accumulate;
+
+    /****************/
+    x10 = x5 - (x4 << 8); /* extract low bytes */
+    x10 = x10 + x4;     /* add with high bytes */
+    x10 = x10 + (x10 << 16); /* add with lower half word */
+
+    if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+    {
+        if (--x8)
+        {
+#if (NUMBER==3)
+            goto         LOOP_SAD3;
+#elif (NUMBER==2)
+goto         LOOP_SAD2;
+#elif (NUMBER==1)
+goto         LOOP_SAD1;
+#endif
+        }
+
+    }
+
+    return ((uint32)x10 >> 16);
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h
new file mode 100644
index 0000000..79d62e4
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h
@@ -0,0 +1,1146 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/******************************************************************************
+ *
+ * This software module was originally developed by
+ *
+ * Robert Danielsen (Telenor / ACTS-MoMuSys).
+ *
+ * and edited by
+ *
+ * Minhua Zhou (HHI / ACTS-MoMuSys).
+ * Luis Ducla-Soares (IST / ACTS-MoMuSys).
+ *
+ * in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
+ * This software module is an implementation of a part of one or more MPEG-4
+ * Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
+ * 14496-2) standard.
+ *
+ * ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
+ * license to this software module or modifications thereof for use in hardware
+ * or software products claiming conformance to the MPEG-4 Video (ISO/IEC
+ * 14496-2) standard.
+ *
+ * Those intending to use this software module in hardware or software products
+ * are advised that its use may infringe existing patents. The original
+ * developer of this software module and his/her company, the subsequent
+ * editors and their companies, and ISO/IEC have no liability for use of this
+ * software module or modifications thereof in an implementation. Copyright is
+ * not released for non MPEG-4 Video (ISO/IEC 14496-2) standard conforming
+ * products.
+ *
+ * ACTS-MoMuSys partners retain full right to use the code for his/her own
+ * purpose, assign or donate the code to a third party and to inhibit third
+ * parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) standard
+ * conforming products. This copyright notice must be included in all copies or
+ * derivative works.
+ *
+ * Copyright (c) 1997
+ *
+ *****************************************************************************/
+
+
+/***********************************************************HeaderBegin*******
+ *
+ * File:    vlc.h
+ *
+ * Author:  Robert Danielsen
+ * Created: 07.06.96
+ *
+ * Description: vlc tables for encoder
+ *
+ * Notes:   Idea taken from MPEG-2 software simulation group
+ *
+ * Modified:
+ *  28.10.96 Robert Danielsen: Added tables for Intra luminance
+ *          coefficients
+ *      01.05.97 Luis Ducla-Soares: added VM7.0 Reversible VLC tables (RVLC).
+ *      13.05.97 Minhua Zhou: added cbpy_tab3,cbpy_tab2
+ *
+ ***********************************************************HeaderEnd*********/
+
+/************************    INCLUDE FILES    ********************************/
+
+#ifndef _VLC_ENC_TAB_H_
+#define _VLC_ENC_TAB_H_
+
+
+#include "mp4def.h"
+/* type definitions for variable length code table entries */
+
+
+
+static const Int intra_max_level[2][64] =
+{
+    {27, 10,  5,  4,  3,  3,  3,  3,
+        2,  2,  1,  1,  1,  1,  1,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+    },
+
+    {8,  3,  2,  2,  2,  2,  2,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0
+    }
+};
+
+
+static const Int inter_max_level[2][64] =
+{
+    {12,  6,  4,  3,  3,  3,  3,  2,
+        2,  2,  2,  1,  1,  1,  1,  1,
+        1,  1,  1,  1,  1,  1,  1,  1,
+        1,  1,  1,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0,
+        0,  0,  0,  0,  0,  0,  0,  0},
+
+    {3,  2,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  1,  1,  1,  1,  1,  1,  1,
+     1,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0,
+     0,  0,  0,  0,  0,  0,  0,  0}
+};
+
+
+static const Int intra_max_run0[28] = { 999, 14,  9,  7,  3,  2,  1,
+                                        1,  1,  1,  1,  0,  0,  0,
+                                        0,  0,  0,  0,  0,  0,  0,
+                                        0,  0,  0,  0,  0,  0,  0
+                                      };
+
+
+static const Int intra_max_run1[9] = { 999, 20,  6,
+                                       1,  0,  0,
+                                       0,  0,  0
+                                     };
+
+static const Int inter_max_run0[13] = { 999,
+                                        26, 10,  6,  2,  1,  1,
+                                        0,  0,  0,  0,  0,  0
+                                      };
+
+
+static const Int inter_max_run1[4] = { 999, 40,  1,  0 };
+
+
+
+/* DC prediction sizes */
+
+static const VLCtable DCtab_lum[13] =
+{
+    {3, 3}, {3, 2}, {2, 2}, {2, 3}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7},
+    {1, 8}, {1, 9}, {1, 10}, {1, 11}
+};
+
+static const VLCtable DCtab_chrom[13] =
+{
+    {3, 2}, {2, 2}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8},
+    {1, 9}, {1, 10}, {1, 11}, {1, 12}
+};
+
+/* Motion vectors */
+
+static const VLCtable mvtab[33] =
+{
+    {1, 1}, {1, 2}, {1, 3}, {1, 4}, {3, 6}, {5, 7}, {4, 7}, {3, 7},
+    {11, 9}, {10, 9}, {9, 9}, {17, 10}, {16, 10}, {15, 10}, {14, 10}, {13, 10},
+    {12, 10}, {11, 10}, {10, 10}, {9, 10}, {8, 10}, {7, 10}, {6, 10}, {5, 10},
+    {4, 10}, {7, 11}, {6, 11}, {5, 11}, {4, 11}, {3, 11}, {2, 11}, {3, 12},
+    {2, 12}
+};
+
+
+/* MCBPC Indexing by cbpc in first two bits, mode in last two.
+ CBPC as in table 4/H.263, MB type (mode): 3 = 01, 4 = 10.
+ Example: cbpc = 01 and mode = 4 gives index = 0110 = 6. */
+
+static const VLCtable mcbpc_intra_tab[15] =
+{
+    {0x01, 9}, {0x01, 1}, {0x01, 4}, {0x00, 0},
+    {0x00, 0}, {0x01, 3}, {0x01, 6}, {0x00, 0},
+    {0x00, 0}, {0x02, 3}, {0x02, 6}, {0x00, 0},
+    {0x00, 0}, {0x03, 3}, {0x03, 6}
+};
+
+
+/* MCBPC inter.
+   Addressing: 5 bit ccmmm (cc = CBPC, mmm = mode (1-4 binary)) */
+
+static const VLCtable mcbpc_inter_tab[29] =
+{
+    {1, 1}, {3, 3}, {2, 3}, {3, 5}, {4, 6}, {1, 9}, {0, 0}, {0, 0},
+    {3, 4}, {7, 7}, {5, 7}, {4, 8}, {4, 9}, {0, 0}, {0, 0}, {0, 0},
+    {2, 4}, {6, 7}, {4, 7}, {3, 8}, {3, 9}, {0, 0}, {0, 0}, {0, 0},
+    {5, 6}, {5, 9}, {5, 8}, {3, 7}, {2, 9}
+};
+
+
+
+/* CBPY. Straightforward indexing */
+
+static const VLCtable cbpy_tab[16] =
+{
+    {3, 4}, {5, 5}, {4, 5}, {9, 4}, {3, 5}, {7, 4}, {2, 6}, {11, 4},
+    {2, 5}, {3, 6}, {5, 4}, {10, 4}, {4, 4}, {8, 4}, {6, 4}, {3, 2}
+};
+
+static const VLCtable cbpy_tab3[8] =
+{
+    {3, 3}, {1, 6}, {1, 5}, {2, 3}, {2, 5}, {3, 5}, {1, 3}, {1, 1}
+};
+static const VLCtable cbpy_tab2[4] =
+{
+    {1, 4}, {1, 3}, {1, 2}, {1, 1}
+};
+
+/* DCT coefficients. Four tables, two for last = 0, two for last = 1.
+   the sign bit must be added afterwards. */
+
+/* first part of coeffs for last = 0. Indexed by [run][level-1] */
+
+static const VLCtable coeff_tab0[2][12] =
+{
+    /* run = 0 */
+    {
+        {0x02, 2}, {0x0f, 4}, {0x15, 6}, {0x17, 7},
+        {0x1f, 8}, {0x25, 9}, {0x24, 9}, {0x21, 10},
+        {0x20, 10}, {0x07, 11}, {0x06, 11}, {0x20, 11}
+    },
+    /* run = 1 */
+    {
+        {0x06, 3}, {0x14, 6}, {0x1e, 8}, {0x0f, 10},
+        {0x21, 11}, {0x50, 12}, {0x00, 0}, {0x00, 0},
+        {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    }
+};
+
+/* rest of coeffs for last = 0. indexing by [run-2][level-1] */
+
+static const VLCtable coeff_tab1[25][4] =
+{
+    /* run = 2 */
+    {
+        {0x0e, 4}, {0x1d, 8}, {0x0e, 10}, {0x51, 12}
+    },
+    /* run = 3 */
+    {
+        {0x0d, 5}, {0x23, 9}, {0x0d, 10}, {0x00, 0}
+    },
+    /* run = 4-26 */
+    {
+        {0x0c, 5}, {0x22, 9}, {0x52, 12}, {0x00, 0}
+    },
+    {
+        {0x0b, 5}, {0x0c, 10}, {0x53, 12}, {0x00, 0}
+    },
+    {
+        {0x13, 6}, {0x0b, 10}, {0x54, 12}, {0x00, 0}
+    },
+    {
+        {0x12, 6}, {0x0a, 10}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x11, 6}, {0x09, 10}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x10, 6}, {0x08, 10}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x16, 7}, {0x55, 12}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x15, 7}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x14, 7}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x1c, 8}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x1b, 8}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x21, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x20, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x1f, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x1e, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x1d, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x1c, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x1b, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x1a, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x22, 11}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x23, 11}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x56, 12}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    },
+    {
+        {0x57, 12}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+    }
+};
+
+/* first coeffs of last = 1. indexing by [run][level-1] */
+
+static const VLCtable coeff_tab2[2][3] =
+{
+    /* run = 0 */
+    {
+        {0x07, 4}, {0x19, 9}, {0x05, 11}
+    },
+    /* run = 1 */
+    {
+        {0x0f, 6}, {0x04, 11}, {0x00, 0}
+    }
+};
+
+/* rest of coeffs for last = 1. indexing by [run-2] */
+
+static const VLCtable coeff_tab3[40] =
+{
+    {0x0e, 6}, {0x0d, 6}, {0x0c, 6},
+    {0x13, 7}, {0x12, 7}, {0x11, 7}, {0x10, 7},
+    {0x1a, 8}, {0x19, 8}, {0x18, 8}, {0x17, 8},
+    {0x16, 8}, {0x15, 8}, {0x14, 8}, {0x13, 8},
+    {0x18, 9}, {0x17, 9}, {0x16, 9}, {0x15, 9},
+    {0x14, 9}, {0x13, 9}, {0x12, 9}, {0x11, 9},
+    {0x07, 10}, {0x06, 10}, {0x05, 10}, {0x04, 10},
+    {0x24, 11}, {0x25, 11}, {0x26, 11}, {0x27, 11},
+    {0x58, 12}, {0x59, 12}, {0x5a, 12}, {0x5b, 12},
+    {0x5c, 12}, {0x5d, 12}, {0x5e, 12}, {0x5f, 12},
+    {0x00, 0}
+};
+
+/* New tables for Intra luminance coefficients. Same codewords,
+   different meaning */
+
+/* Coeffs for last = 0, run = 0. Indexed by [level-1] */
+
+static const VLCtable coeff_tab4[27] =
+{
+    /* run = 0 */
+    {0x02, 2}, {0x06, 3}, {0x0f, 4}, {0x0d, 5},
+    {0x0c, 5}, {0x15, 6}, {0x13, 6}, {0x12, 6},
+    {0x17, 7}, {0x1f, 8}, {0x1e, 8}, {0x1d, 8},
+    {0x25, 9}, {0x24, 9}, {0x23, 9}, {0x21, 9},
+    {0x21, 10}, {0x20, 10}, {0x0f, 10}, {0x0e, 10},
+    {0x07, 11}, {0x06, 11}, {0x20, 11}, {0x21, 11},
+    {0x50, 12}, {0x51, 12}, {0x52, 12}
+};
+
+/* Coeffs for last = 0, run = 1. Indexed by [level-1] */
+
+static const VLCtable coeff_tab5[10] =
+{
+    {0x0e, 4}, {0x14, 6}, {0x16, 7}, {0x1c, 8},
+    {0x20, 9}, {0x1f, 9}, {0x0d, 10}, {0x22, 11},
+    {0x53, 12}, {0x55, 12}
+};
+
+/* Coeffs for last = 0, run = 2 -> 9. Indexed by [run-2][level-1] */
+
+static const VLCtable coeff_tab6[8][5] =
+{
+    /* run = 2 */
+    {
+        {0x0b, 5}, {0x15, 7}, {0x1e, 9}, {0x0c, 10},
+        {0x56, 12}
+    },
+    /* run = 3 */
+    {
+        {0x11, 6}, {0x1b, 8}, {0x1d, 9}, {0x0b, 10},
+        {0x00, 0}
+    },
+    /* run = 4 */
+    {
+        {0x10, 6}, {0x22, 9}, {0x0a, 10}, {0x00, 0},
+        {0x00, 0}
+    },
+    /* run = 5 */
+    {
+        {0x0d, 6}, {0x1c, 9}, {0x08, 10}, {0x00, 0},
+        {0x00, 0}
+    },
+    /* run = 6 */
+    {
+        {0x12, 7}, {0x1b, 9}, {0x54, 12}, {0x00, 0},
+        {0x00, 0}
+    },
+    /* run = 7 */
+    {
+        {0x14, 7}, {0x1a, 9}, {0x57, 12}, {0x00, 0},
+        {0x00, 0}
+    },
+    /* run = 8 */
+    {
+        {0x19, 8}, {0x09, 10}, {0x00, 0}, {0x00, 0},
+        {0x00, 0}
+    },
+    /* run = 9 */
+    {
+        {0x18, 8}, {0x23, 11}, {0x00, 0}, {0x00, 0},
+        {0x00, 0}
+    }
+};
+
+/* Coeffs for last = 0, run = 10 -> 14. Indexed by [run-10] */
+
+static const VLCtable coeff_tab7[5] =
+{
+    {0x17, 8}, {0x19, 9}, {0x18, 9}, {0x07, 10},
+    {0x58, 12}
+};
+
+/* Coeffs for last = 1, run = 0. Indexed by [level-1] */
+
+static const VLCtable coeff_tab8[8] =
+{
+    {0x07, 4}, {0x0c, 6}, {0x16, 8}, {0x17, 9},
+    {0x06, 10}, {0x05, 11}, {0x04, 11}, {0x59, 12}
+};
+
+/* Coeffs for last = 1, run = 1 -> 6. Indexed by [run-1][level-1] */
+
+static const VLCtable coeff_tab9[6][3] =
+{
+    /* run = 1 */
+    {
+        {0x0f, 6}, {0x16, 9}, {0x05, 10}
+    },
+    /* run = 2 */
+    {
+        {0x0e, 6}, {0x04, 10}, {0x00, 0}
+    },
+    /* run = 3 */
+    {
+        {0x11, 7}, {0x24, 11}, {0x00, 0}
+    },
+    /* run = 4 */
+    {
+        {0x10, 7}, {0x25, 11}, {0x00, 0}
+    },
+    /* run = 5 */
+    {
+        {0x13, 7}, {0x5a, 12}, {0x00, 0}
+    },
+    /* run = 6 */
+    {
+        {0x15, 8}, {0x5b, 12}, {0x00, 0}
+    }
+};
+
+/* Coeffs for last = 1, run = 7 -> 20. Indexed by [run-7] */
+
+static const VLCtable coeff_tab10[14] =
+{
+    {0x14, 8}, {0x13, 8}, {0x1a, 8}, {0x15, 9},
+    {0x14, 9}, {0x13, 9}, {0x12, 9}, {0x11, 9},
+    {0x26, 11}, {0x27, 11}, {0x5c, 12}, {0x5d, 12},
+    {0x5e, 12}, {0x5f, 12}
+};
+
+
+#ifndef NO_RVLC
+/* RVLC tables */
+/* DCT coefficients. Four tables, two for last = 0, two for last = 1.
+   the sign bit must be added afterwards. */
+
+/* DCT  coeffs (intra) for last = 0.  */
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab1[27] =
+{
+    /* run = 0 */
+    {     0x6,  3},
+    {     0x7,  3},
+    {     0xa,  4},
+    {     0x9,  5},
+    {    0x14,  6},
+    {    0x15,  6},
+    {    0x34,  7},
+    {    0x74,  8},
+    {    0x75,  8},
+    {    0xdd,  9},
+    {    0xec,  9},
+    {   0x1ec, 10},
+    {   0x1ed, 10},
+    {   0x1f4, 10},
+    {   0x3ec, 11},
+    {   0x3ed, 11},
+    {   0x3f4, 11},
+    {   0x77d, 12},
+    {   0x7bc, 12},
+    {   0xfbd, 13},
+    {   0xfdc, 13},
+    {   0x7bd, 12},
+    {   0xfdd, 13},
+    {  0x1fbd, 14},
+    {  0x1fdc, 14},
+    {  0x1fdd, 14},
+    {  0x1ffc, 15}
+};
+
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab2[13] =
+{
+    /* run = 1 */
+    {     0x1,  4},
+    {     0x8,  5},
+    {    0x2d,  7},
+    {    0x6c,  8},
+    {    0x6d,  8},
+    {    0xdc,  9},
+    {   0x1dd, 10},
+    {   0x3dc, 11},
+    {   0x3dd, 11},
+    {   0x77c, 12},
+    {   0xfbc, 13},
+    {  0x1f7d, 14},
+    {  0x1fbc, 14}
+};
+
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab3[11] =
+{
+    /* run = 2 */
+
+    {     0x4,  5},
+    {    0x2c,  7},
+    {    0xbc,  9},
+    {   0x1dc, 10},
+    {   0x3bc, 11},
+    {   0x3bd, 11},
+    {   0xefd, 13},
+    {   0xf7c, 13},
+    {   0xf7d, 13},
+    {  0x1efd, 14},
+    {  0x1f7c, 14}
+};
+
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab4[9] =
+{
+    /* run = 3 */
+    {     0x5,  5},
+    {    0x5c,  8},
+    {    0xbd,  9},
+    {   0x37d, 11},
+    {   0x6fc, 12},
+    {   0xefc, 13},
+    {  0x1dfd, 14},
+    {  0x1efc, 14},
+    {  0x1ffd, 15}
+};
+
+
+/* Indexed by [run-4][level-1] */
+
+static const VLCtable coeff_RVLCtab5[2][6] =
+{
+    /* run = 4 */
+    {
+        {     0xc,  6},
+        {    0x5d,  8},
+        {   0x1bd, 10},
+        {   0x3fd, 12},
+        {   0x6fd, 12},
+        {  0x1bfd, 14}
+    },
+    /* run = 5 */
+    {
+        {     0xd,  6},
+        {    0x7d,  9},
+        {   0x2fc, 11},
+        {   0x5fc, 12},
+        {  0x1bfc, 14},
+        {  0x1dfc, 14}
+    }
+};
+
+
+/* Indexed by [run-6][level-1]       */
+
+static const VLCtable coeff_RVLCtab6[2][5] =
+{
+
+    /* run = 6 */
+    {
+        {    0x1c,  7},
+        {   0x17c, 10},
+        {   0x2fd, 11},
+        {   0x5fd, 12},
+        {  0x2ffc, 15}
+    },
+    /* run = 7 */
+    {
+        {    0x1d,  7},
+        {   0x17d, 10},
+        {   0x37c, 11},
+        {   0xdfd, 13},
+        {  0x2ffd, 15}
+    }
+
+};
+/* Indexed by [run-8][level-1] */
+
+static const VLCtable coeff_RVLCtab7[2][4] =
+{
+    /* run = 8 */
+    {
+        {    0x3c,  8},
+        {   0x1bc, 10},
+        {   0xbfd, 13},
+        {  0x17fd, 14}
+    },
+    /* run = 9 */
+    {
+        {    0x3d,  8},
+        {   0x1fd, 11},
+        {   0xdfc, 13},
+        {  0x37fc, 15},
+    }
+};
+
+
+
+/* Indexed by [run-10][level-1] */
+
+static const VLCtable coeff_RVLCtab8[3][2] =
+{
+    /* run = 10 */
+    {
+        {    0x7c,  9},
+        {   0x3fc, 12}
+    },
+    /* run = 11 */
+    {
+        {    0xfc, 10},
+        {   0xbfc, 13}
+    },
+    /* run = 12 */
+    {
+        {    0xfd, 10},
+        {  0x37fd, 15}
+    }
+};
+
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab9[7] =
+{
+    /* run = 13 -> 19 */
+    {   0x1fc, 11},
+    {   0x7fc, 13},
+    {   0x7fd, 13},
+    {   0xffc, 14},
+    {   0xffd, 14},
+    {  0x17fc, 14},
+    {  0x3bfc, 15}
+};
+
+
+
+/* first coeffs of last = 1. indexing by [run][level-1] */
+
+static const VLCtable coeff_RVLCtab10[2][5] =
+{
+    /* run = 0 */
+    {
+        {     0xb,  4},
+        {    0x78,  8},
+        {   0x3f5, 11},
+        {   0xfec, 13},
+        {  0x1fec, 14}
+    },
+    /* run = 1 */
+    {
+        {    0x12,  5},
+        {    0xed,  9},
+        {   0x7dc, 12},
+        {  0x1fed, 14},
+        {  0x3bfd, 15}
+    }
+
+};
+
+static const VLCtable coeff_RVLCtab11[3] =
+{
+    /* run = 2 */
+    {    0x13,  5},
+    {   0x3f8, 11},
+    {  0x3dfc, 15}
+
+};
+
+static const VLCtable coeff_RVLCtab12[11][2] =
+{
+    /* run = 3 */
+    {
+        {    0x18,  6},
+        {   0x7dd, 12}
+    },
+    /* run = 4 */
+    {
+        {    0x19,  6},
+        {   0x7ec, 12}
+    },
+    /* run = 5 */
+    {
+        {    0x22,  6},
+        {   0xfed, 13}
+    },
+    /* run = 6 */
+    {
+        {    0x23,  6},
+        {   0xff4, 13}
+    },
+    /* run = 7 */
+    {
+        {    0x35,  7},
+        {   0xff5, 13}
+    },
+    /* run = 8 */
+    {
+        {    0x38,  7},
+        {   0xff8, 13}
+    },
+    /* run = 9 */
+    {
+        {    0x39,  7},
+        {   0xff9, 13}
+    },
+    /* run = 10 */
+    {
+        {    0x42,  7},
+        {  0x1ff4, 14}
+    },
+    /* run = 11 */
+    {
+        {    0x43,  7},
+        {  0x1ff5, 14}
+    },
+    /* run = 12 */
+    {
+        {    0x79,  8},
+        {  0x1ff8, 14}
+    },
+    /* run = 13 */
+    {
+        {    0x82,  8},
+        {  0x3dfd, 15}
+    }
+
+};
+
+static const VLCtable coeff_RVLCtab13[32] =
+{
+    /* run = 14 -> 44 */
+    {    0x83,  8},
+    {    0xf4,  9},
+    {    0xf5,  9},
+    {    0xf8,  9},
+    {    0xf9,  9},
+    {   0x102,  9},
+    {   0x103,  9},
+    {   0x1f5, 10},
+    {   0x1f8, 10},
+    {   0x1f9, 10},
+    {   0x202, 10},
+    {   0x203, 10},
+    {   0x3f9, 11},
+    {   0x402, 11},
+    {   0x403, 11},
+    {   0x7ed, 12},
+    {   0x7f4, 12},
+    {   0x7f5, 12},
+    {   0x7f8, 12},
+    {   0x7f9, 12},
+    {   0x802, 12},
+    {   0x803, 12},
+    {  0x1002, 13},
+    {  0x1003, 13},
+    {  0x1ff9, 14},
+    {  0x2002, 14},
+    {  0x2003, 14},
+    {  0x3efc, 15},
+    {  0x3efd, 15},
+    {  0x3f7c, 15},
+    {  0x3f7d, 15}
+};
+
+
+
+/* Coeffs for last = 0, run = 0. Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab14[19] =
+{
+    /* run = 0 */
+    {     0x6,  3},
+    {     0x1,  4},
+    {     0x4,  5},
+    {    0x1c,  7},
+    {    0x3c,  8},
+    {    0x3d,  8},
+    {    0x7c,  9},
+    {    0xfc, 10},
+    {    0xfd, 10},
+    {   0x1fc, 11},
+    {   0x1fd, 11},
+    {   0x3fc, 12},
+    {   0x7fc, 13},
+    {   0x7fd, 13},
+    {   0xbfc, 13},
+    {   0xbfd, 13},
+    {   0xffc, 14},
+    {   0xffd, 14},
+    {  0x1ffc, 15}
+};
+
+static const VLCtable coeff_RVLCtab15[10] =
+{
+    /* run = 1 */
+    {     0x7,  3},
+    {     0xc,  6},
+    {    0x5c,  8},
+    {    0x7d,  9},
+    {   0x17c, 10},
+    {   0x2fc, 11},
+    {   0x3fd, 12},
+    {   0xdfc, 13},
+    {  0x17fc, 14},
+    {  0x17fd, 14}
+};
+
+static const VLCtable coeff_RVLCtab16[2][7] =
+{
+    /* run = 2 */
+    {
+        {     0xa,  4},
+        {    0x1d,  7},
+        {    0xbc,  9},
+        {   0x2fd, 11},
+        {   0x5fc, 12},
+        {  0x1bfc, 14},
+        {  0x1bfd, 14}
+    },
+    /* run = 3 */
+    {
+        {     0x5,  5},
+        {    0x5d,  8},
+        {   0x17d, 10},
+        {   0x5fd, 12},
+        {   0xdfd, 13},
+        {  0x1dfc, 14},
+        {  0x1ffd, 15}
+    }
+};
+
+static const VLCtable coeff_RVLCtab17[5] =
+{
+    /* run = 4 */
+    {     0x8,  5},
+    {    0x6c,  8},
+    {   0x37c, 11},
+    {   0xefc, 13},
+    {  0x2ffc, 15}
+};
+
+static const VLCtable coeff_RVLCtab18[3][4] =
+{
+    /* run = 5 */
+    {
+        {     0x9,  5},
+        {    0xbd,  9},
+        {   0x37d, 11},
+        {   0xefd, 13}
+    },
+    /* run = 6 */
+    {
+        {     0xd,  6},
+        {   0x1bc, 10},
+        {   0x6fc, 12},
+        {  0x1dfd, 14}
+    },
+    /* run = 7 */
+    {
+        {    0x14,  6},
+        {   0x1bd, 10},
+        {   0x6fd, 12},
+        {  0x2ffd, 15}
+    }
+};
+
+static const VLCtable coeff_RVLCtab19[2][3] =
+{
+    /* run = 8 */
+    {
+        {    0x15,  6},
+        {   0x1dc, 10},
+        {   0xf7c, 13}
+    },
+    /* run = 9 */
+    {
+        {    0x2c,  7},
+        {   0x1dd, 10},
+        {  0x1efc, 14}
+    }
+};
+
+static const VLCtable coeff_RVLCtab20[8][2] =
+{
+    /* run = 10 */
+    {
+        {    0x2d,  7},
+        {   0x3bc, 11}
+    },
+    /* run = 11 */
+    {
+        {    0x34,  7},
+        {   0x77c, 12}
+    },
+    /* run = 12 */
+    {
+        {    0x6d,  8},
+        {   0xf7d, 13}
+    },
+    /* run = 13 */
+    {
+        {    0x74,  8},
+        {  0x1efd, 14}
+    },
+    /* run = 14 */
+    {
+        {    0x75,  8},
+        {  0x1f7c, 14}
+    },
+    /* run = 15 */
+    {
+        {    0xdc,  9},
+        {  0x1f7d, 14}
+    },
+    /* run = 16 */
+    {
+        {    0xdd,  9},
+        {  0x1fbc, 14}
+    },
+    /* run = 17 */
+    {
+        {    0xec,  9},
+        {  0x37fc, 15}
+    }
+};
+
+static const VLCtable coeff_RVLCtab21[21] =
+{
+    /* run = 18 -> 38 */
+    {   0x1ec, 10},
+    {   0x1ed, 10},
+    {   0x1f4, 10},
+    {   0x3bd, 11},
+    {   0x3dc, 11},
+    {   0x3dd, 11},
+    {   0x3ec, 11},
+    {   0x3ed, 11},
+    {   0x3f4, 11},
+    {   0x77d, 12},
+    {   0x7bc, 12},
+    {   0x7bd, 12},
+    {   0xfbc, 13},
+    {   0xfbd, 13},
+    {   0xfdc, 13},
+    {   0xfdd, 13},
+    {  0x1fbd, 14},
+    {  0x1fdc, 14},
+    {  0x1fdd, 14},
+    {  0x37fd, 15},
+    {  0x3bfc, 15}
+};
+
+
+/* first coeffs of last = 1. indexing by [run][level-1] */
+
+static const VLCtable coeff_RVLCtab22[2][5] =
+{
+    /* run = 0 */
+    {
+        {     0xb,  4},
+        {    0x78,  8},
+        {   0x3f5, 11},
+        {   0xfec, 13},
+        {  0x1fec, 14}
+    },
+    /* run = 1 */
+    {
+        {    0x12,  5},
+        {    0xed,  9},
+        {   0x7dc, 12},
+        {  0x1fed, 14},
+        {  0x3bfd, 15}
+    }
+
+};
+
+static const VLCtable coeff_RVLCtab23[3] =
+{
+    /* run = 2 */
+    {    0x13,  5},
+    {   0x3f8, 11},
+    {  0x3dfc, 15}
+
+};
+
+static const VLCtable coeff_RVLCtab24[11][2] =
+{
+    /* run = 3 */
+    {
+        {    0x18,  6},
+        {   0x7dd, 12}
+    },
+    /* run = 4 */
+    {
+        {    0x19,  6},
+        {   0x7ec, 12}
+    },
+    /* run = 5 */
+    {
+        {    0x22,  6},
+        {   0xfed, 13}
+    },
+    /* run = 6 */
+    {
+        {    0x23,  6},
+        {   0xff4, 13}
+    },
+    /* run = 7 */
+    {
+        {    0x35,  7},
+        {   0xff5, 13}
+    },
+    /* run = 8 */
+    {
+        {    0x38,  7},
+        {   0xff8, 13}
+    },
+    /* run = 9 */
+    {
+        {    0x39,  7},
+        {   0xff9, 13}
+    },
+    /* run = 10 */
+    {
+        {    0x42,  7},
+        {  0x1ff4, 14}
+    },
+    /* run = 11 */
+    {
+        {    0x43,  7},
+        {  0x1ff5, 14}
+    },
+    /* run = 12 */
+    {
+        {    0x79,  8},
+        {  0x1ff8, 14}
+    },
+    /* run = 13 */
+    {
+        {    0x82,  8},
+        {  0x3dfd, 15}
+    }
+
+};
+
+static const VLCtable coeff_RVLCtab25[32] =
+{
+    /* run = 14 -> 44 */
+    {    0x83,  8},
+    {    0xf4,  9},
+    {    0xf5,  9},
+    {    0xf8,  9},
+    {    0xf9,  9},
+    {   0x102,  9},
+    {   0x103,  9},
+    {   0x1f5, 10},
+    {   0x1f8, 10},
+    {   0x1f9, 10},
+    {   0x202, 10},
+    {   0x203, 10},
+    {   0x3f9, 11},
+    {   0x402, 11},
+    {   0x403, 11},
+    {   0x7ed, 12},
+    {   0x7f4, 12},
+    {   0x7f5, 12},
+    {   0x7f8, 12},
+    {   0x7f9, 12},
+    {   0x802, 12},
+    {   0x803, 12},
+    {  0x1002, 13},
+    {  0x1003, 13},
+    {  0x1ff9, 14},
+    {  0x2002, 14},
+    {  0x2003, 14},
+    {  0x3efc, 15},
+    {  0x3efd, 15},
+    {  0x3f7c, 15},
+    {  0x3f7d, 15}
+};
+
+#endif /* NO_RVLC */
+
+#endif /* _VLC_ENC_TAB_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
new file mode 100644
index 0000000..7ea5dc4
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
@@ -0,0 +1,2799 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+/******************************************************************************
+*
+* This software module was originally developed by
+*
+* Robert Danielsen (Telenor / ACTS-MoMuSys).
+*
+* and edited by
+*
+* Luis Ducla-Soares (IST / ACTS-MoMuSys).
+* Cor Quist (KPN / ACTS-MoMuSys).
+*
+* in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
+* This software module is an implementation of a part of one or more MPEG-4
+* Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
+* 14496-2) standard.
+*
+* ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
+* license to this software module or modifications thereof for use in hardware
+* or software products claiming conformance to the MPEG-4 Video (ISO/IEC
+* 14496-2) standard.
+*
+* Those intending to use this software module in hardware or software products
+* are advised that its use may infringe existing patents. The original
+* developer of this software module and his/her company, the subsequent
+* editors and their companies, and ISO/IEC have no liability for use of this
+* software module or modifications thereof in an implementation. Copyright is
+* not released for non MPEG-4 Video (ISO/IEC 14496-2) standard conforming
+* products.
+*
+* ACTS-MoMuSys partners retain full right to use the code for his/her own
+* purpose, assign or donate the code to a third party and to inhibit third
+* parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) standard
+* conforming products. This copyright notice must be included in all copies or
+* derivative works.
+*
+* Copyright (c) 1997
+*
+*****************************************************************************/
+
+/***********************************************************HeaderBegin*******
+*
+* File: putvlc.c
+*
+* Author:   Robert Danielsen, Telenor R&D
+* Created:  07.07.96
+*
+* Description: Functions for writing to bitstream
+*
+* Notes:    Same kind of tables as in the MPEG-2 software simulation
+*       group software.
+*
+* Modified:
+*   28.10.96 Robert Danielsen: Added PutCoeff_Intra(), renamed
+*           PutCoeff() to PutCoeff_Inter().
+*   06.11.96 Robert Danielsen: Added PutMCBPC_sep()
+*      01.05.97 Luis Ducla-Soares: added PutCoeff_Intra_RVLC() and
+*                                  PutCoeff_Inter_RVLC().
+*
+***********************************************************HeaderEnd*********/
+
+/************************    INCLUDE FILES    ********************************/
+
+
+#include "mp4lib_int.h"
+#include "mp4enc_lib.h"
+#include "vlc_enc_tab.h"
+#include "bitstream_io.h"
+#include "m4venc_oscl.h"
+#include "vlc_encode_inline.h"
+
+typedef void (*BlockCodeCoeffPtr)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar) ;
+
+const static Int mode_MBtype[] =
+{
+    3,
+    0,
+    4,
+    1,
+    2,
+};
+
+const static Int zigzag_inv[NCOEFF_BLOCK] =
+{
+    0,  1,  8, 16,  9,  2,  3, 10,
+    17, 24, 32, 25, 18, 11,  4,  5,
+    12, 19, 26, 33, 40, 48, 41, 34,
+    27, 20, 13,  6,  7, 14, 21, 28,
+    35, 42, 49, 56, 57, 50, 43, 36,
+    29, 22, 15, 23, 30, 37, 44, 51,
+    58, 59, 52, 45, 38, 31, 39, 46,
+    53, 60, 61, 54, 47, 55, 62, 63
+};
+
+/* Horizontal zigzag inverse */
+const static Int zigzag_h_inv[NCOEFF_BLOCK] =
+{
+    0, 1, 2, 3, 8, 9, 16, 17,
+    10, 11, 4, 5, 6, 7, 15, 14,
+    13, 12, 19, 18, 24, 25, 32, 33,
+    26, 27, 20, 21, 22, 23, 28, 29,
+    30, 31, 34, 35, 40, 41, 48, 49,
+    42, 43, 36, 37, 38, 39, 44, 45,
+    46, 47, 50, 51, 56, 57, 58, 59,
+    52, 53, 54, 55, 60, 61, 62, 63
+};
+
+/* Vertical zigzag inverse */
+const static Int zigzag_v_inv[NCOEFF_BLOCK] =
+{
+    0, 8, 16, 24, 1, 9, 2, 10,
+    17, 25, 32, 40, 48, 56, 57, 49,
+    41, 33, 26, 18, 3, 11, 4, 12,
+    19, 27, 34, 42, 50, 58, 35, 43,
+    51, 59, 20, 28, 5, 13, 6, 14,
+    21, 29, 36, 44, 52, 60, 37, 45,
+    53, 61, 22, 30, 7, 15, 23, 31,
+    38, 46, 54, 62, 39, 47, 55, 63
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    Int PutCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutCBPY(Int cbpy, Char intra, BitstreamEncVideo *bitstream);
+    Int PutMCBPC_Inter(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
+    Int PutMCBPC_Intra(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
+    Int PutMV(Int mvint, BitstreamEncVideo *bitstream);
+    Int PutDCsize_chrom(Int size, BitstreamEncVideo *bitstream);
+    Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
+    Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
+#ifndef NO_RVLC
+    Int PutCoeff_Inter_RVLC(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutCoeff_Inter_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutCoeff_Intra_RVLC(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutCoeff_Intra_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+#endif
+    Int PutRunCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutRunCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutRunCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutRunCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutLevelCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutLevelCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutLevelCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
+    Int PutLevelCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+
+    void RunLevel(VideoEncData *video, Int intra, Int intraDC_decision, Int ncoefblck[]);
+    Int IntraDC_dpcm(Int val, Int lum, BitstreamEncVideo *bitstream);
+    Void DCACPred(VideoEncData *video, UChar Mode, Int *intraDC_decision, Int intraDCVlcQP);
+    Void find_pmvs(VideoEncData *video, Int block, Int *mvx, Int *mvy);
+    Void  WriteMVcomponent(Int f_code, Int dmv, BitstreamEncVideo *bs);
+    static Bool IntraDCSwitch_Decision(Int Mode, Int intra_dc_vlc_threshold, Int intraDCVlcQP);
+
+    Void ScaleMVD(Int  f_code, Int  diff_vector, Int  *residual, Int  *vlc_code_mag);
+
+#ifdef __cplusplus
+}
+#endif
+
+Int
+PutDCsize_lum(Int size, BitstreamEncVideo *bitstream)
+{
+    Int length;
+
+    if (!(size >= 0 && size < 13))
+        return -1;
+
+    length = DCtab_lum[size].len;
+    if (length)
+        BitstreamPutBits(bitstream, length, DCtab_lum[size].code);
+
+    return length;
+}
+
+Int
+PutDCsize_chrom(Int size, BitstreamEncVideo *bitstream)
+{
+    Int length;
+
+    if (!(size >= 0 && size < 13))
+        return -1;
+    length = DCtab_chrom[size].len;
+    if (length)
+        BitstreamPutBits(bitstream, length, DCtab_chrom[size].code);
+
+    return length;
+}
+
+Int
+PutMV(Int mvint, BitstreamEncVideo *bitstream)
+{
+    Int sign = 0;
+    Int absmv;
+    Int length;
+
+    if (mvint > 32)
+    {
+        absmv = -mvint + 65;
+        sign = 1;
+    }
+    else
+        absmv = mvint;
+
+    length = mvtab[absmv].len;
+    if (length)
+        BitstreamPutBits(bitstream, length, mvtab[absmv].code);
+
+    if (mvint != 0)
+    {
+        BitstreamPut1Bits(bitstream, sign);
+        return (length + 1);
+    }
+    else
+        return length;
+}
+
+Int
+PutMCBPC_Intra(Int cbp, Int mode, BitstreamEncVideo *bitstream)
+{
+    Int ind;
+    Int length;
+
+    ind = ((mode_MBtype[mode] >> 1) & 3) | ((cbp & 3) << 2);
+
+    length = mcbpc_intra_tab[ind].len;
+    if (length)
+        BitstreamPutBits(bitstream, length, mcbpc_intra_tab[ind].code);
+
+    return length;
+}
+
+Int
+PutMCBPC_Inter(Int cbp, Int mode, BitstreamEncVideo *bitstream)
+{
+    Int ind;
+    Int length;
+
+    ind = (mode_MBtype[mode] & 7) | ((cbp & 3) << 3);
+
+    length = mcbpc_inter_tab[ind].len;
+    if (length)
+        BitstreamPutBits(bitstream, length, mcbpc_inter_tab[ind].code);
+
+    return length;
+}
+
+Int
+PutCBPY(Int cbpy, Char intra, BitstreamEncVideo *bitstream)
+{
+    Int ind;
+    Int length;
+
+    if ((intra == 0))
+        cbpy = 15 - cbpy;
+
+    ind = cbpy;
+
+    length = cbpy_tab[ind].len;
+    if (length)
+        BitstreamPutBits(bitstream, length, (UInt)cbpy_tab[ind].code);
+
+    return length;
+}
+
+/* 5/16/01, break up function for last and not-last coefficient */
+/* Note:::: I checked the ARM assembly for if( run > x && run < y) type
+    of code, they do a really good job compiling it to if( (UInt)(run-x) < y-x).
+    No need to hand-code it!!!!!, 6/1/2001 */
+
+Int PutCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run < 2 && level < 13)
+    {
+        length = coeff_tab0[run][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
+    }
+    else if (run > 1 && run < 27 && level < 5)
+    {
+        length = coeff_tab1[run-2][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
+    }
+
+    return length;
+}
+
+Int PutCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run < 2 && level < 4)
+    {
+        length = coeff_tab2[run][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
+    }
+    else if (run > 1 && run < 42 && level == 1)
+    {
+        length = coeff_tab3[run-2].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
+    }
+
+    return length;
+}
+
+/* 5/16/01, break up function for last and not-last coefficient */
+
+Int PutCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run == 0 && level < 28)
+    {
+        length = coeff_tab4[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
+    }
+    else if (run == 1 && level < 11)
+    {
+        length = coeff_tab5[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
+    }
+    else if (run > 1 && run < 10 && level < 6)
+    {
+        length = coeff_tab6[run-2][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
+    }
+    else if (run > 9 && run < 15 && level == 1)
+    {
+        length = coeff_tab7[run-10].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
+    }
+
+    return length;
+}
+
+Int PutCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run == 0 && level < 9)
+    {
+        length = coeff_tab8[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
+    }
+    else if (run > 0 && run < 7 && level < 4)
+    {
+        length = coeff_tab9[run-1][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
+    }
+    else if (run > 6 && run < 21 && level == 1)
+    {
+        length = coeff_tab10[run-7].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
+    }
+
+    return length;
+}
+
+/* 5/16/01, break up function for last and not-last coefficient */
+#ifndef NO_RVLC
+Int PutCoeff_Inter_RVLC(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run == 0 && level < 20)
+    {
+        length =  coeff_RVLCtab14[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab14[level-1].code);
+    }
+    else if (run == 1 && level < 11)
+    {
+        length = coeff_RVLCtab15[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab15[level-1].code);
+    }
+    else if (run > 1 && run < 4 && level < 8)
+    {
+        length = coeff_RVLCtab16[run-2][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab16[run-2][level-1].code);
+    }
+    else if (run == 4 && level < 6)
+    {
+        length = coeff_RVLCtab17[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab17[level-1].code);
+    }
+    else if (run > 4 && run < 8 && level < 5)
+    {
+        length = coeff_RVLCtab18[run-5][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab18[run-5][level-1].code);
+    }
+    else if (run > 7 && run < 10 && level < 4)
+    {
+        length = coeff_RVLCtab19[run-8][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab19[run-8][level-1].code);
+    }
+    else if (run > 9 && run < 18 && level < 3)
+    {
+        length = coeff_RVLCtab20[run-10][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab20[run-10][level-1].code);
+    }
+    else if (run > 17 && run < 39 && level == 1)
+    {
+        length = coeff_RVLCtab21[run-18].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab21[run-18].code);
+    }
+
+    return length;
+}
+
+Int PutCoeff_Inter_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run >= 0 && run < 2 && level < 6)
+    {
+        length = coeff_RVLCtab22[run][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab22[run][level-1].code);
+    }
+    else if (run == 2 && level < 4)
+    {
+        length = coeff_RVLCtab23[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab23[level-1].code);
+    }
+    else if (run > 2 && run < 14 && level < 3)
+    {
+        length = coeff_RVLCtab24[run-3][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab24[run-3][level-1].code);
+    }
+    else if (run > 13 && run < 45 && level == 1)
+    {
+        length = coeff_RVLCtab25[run-14].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab25[run-14].code);
+    }
+
+    return length;
+}
+
+/* 5/16/01, break up function for last and not-last coefficient */
+
+Int PutCoeff_Intra_RVLC(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run == 0 && level < 28)
+    {
+        length = coeff_RVLCtab1[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab1[level-1].code);
+    }
+    else if (run == 1 && level < 14)
+    {
+        length = coeff_RVLCtab2[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab2[level-1].code);
+    }
+    else if (run == 2 && level < 12)
+    {
+        length = coeff_RVLCtab3[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab3[level-1].code);
+    }
+    else if (run == 3 && level < 10)
+    {
+        length = coeff_RVLCtab4[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab4[level-1].code);
+    }
+    else if (run > 3 && run < 6 && level < 7)
+    {
+        length = coeff_RVLCtab5[run-4][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab5[run-4][level-1].code);
+    }
+    else if (run > 5 && run < 8 && level < 6)
+    {
+        length = coeff_RVLCtab6[run-6][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab6[run-6][level-1].code);
+    }
+    else if (run > 7 && run < 10 && level < 5)
+    {
+        length = coeff_RVLCtab7[run-8][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab7[run-8][level-1].code);
+
+    }
+    else if (run > 9 && run < 13 && level < 3)
+    {
+        length = coeff_RVLCtab8[run-10][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab8[run-10][level-1].code);
+    }
+    else if (run > 12 && run < 20 && level == 1)
+    {
+        length = coeff_RVLCtab9[run-13].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab9[run-13].code);
+    }
+    return length;
+}
+
+Int PutCoeff_Intra_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run >= 0 && run < 2 && level < 6)
+    {
+        length = coeff_RVLCtab10[run][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab10[run][level-1].code);
+    }
+    else if (run == 2 && level < 4)
+    {
+        length = coeff_RVLCtab11[level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab11[level-1].code);
+    }
+    else if (run > 2 && run < 14 && level < 3)
+    {
+        length = coeff_RVLCtab12[run-3][level-1].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab12[run-3][level-1].code);
+    }
+    else if (run > 13 && run < 45 && level == 1)
+    {
+        length = coeff_RVLCtab13[run-14].len;
+        if (length)
+            BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab13[run-14].code);
+    }
+    return length;
+}
+#endif
+
+/* The following is for 3-mode VLC */
+
+Int
+PutRunCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run < 2 && level < 13)
+    {
+        length = coeff_tab0[run][level-1].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
+            length += 9;
+        }
+    }
+    else if (run > 1 && run < 27 && level < 5)
+    {
+        length = coeff_tab1[run-2][level-1].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
+            length += 9;
+        }
+    }
+    return length;
+}
+
+Int PutRunCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run < 2 && level < 4)
+    {
+        length = coeff_tab2[run][level-1].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
+            length += 9;
+        }
+    }
+    else if (run > 1 && run < 42 && level == 1)
+    {
+        length = coeff_tab3[run-2].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
+            length += 9;
+        }
+    }
+    return length;
+}
+
+Int PutRunCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run == 0 && level < 28)
+    {
+        length = coeff_tab4[level-1].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
+            length += 9;
+        }
+    }
+    else if (run == 1 && level < 11)
+    {
+        length = coeff_tab5[level-1].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
+            length += 9;
+        }
+    }
+    else if (run > 1 && run < 10 && level < 6)
+    {
+        length = coeff_tab6[run-2][level-1].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
+            length += 9;
+        }
+    }
+    else if (run > 9 && run < 15 && level == 1)
+    {
+        length = coeff_tab7[run-10].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
+            length += 9;
+        }
+    }
+    return length;
+}
+Int PutRunCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run == 0 && level < 9)
+    {
+        length = coeff_tab8[level-1].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
+            length += 9;
+        }
+    }
+    else if (run > 0 && run < 7 && level < 4)
+    {
+        length = coeff_tab9[run-1][level-1].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
+            length += 9;
+        }
+    }
+    else if (run > 6 && run < 21 && level == 1)
+    {
+        length = coeff_tab10[run-7].len;
+        if (length)
+        {
+            BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+            //BitstreamPutBits(bitstream, 2, 2);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
+            length += 9;
+        }
+    }
+    return length;
+}
+
+Int
+PutLevelCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run < 2 && level < 13)
+    {
+        length = coeff_tab0[run][level-1].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
+            length += 8;
+        }
+    }
+    else if (run > 1 && run < 27 && level < 5)
+    {
+        length = coeff_tab1[run-2][level-1].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
+            length += 8;
+        }
+    }
+    return length;
+}
+
+Int PutLevelCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run < 2 && level < 4)
+    {
+        length = coeff_tab2[run][level-1].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
+            length += 8;
+        }
+    }
+    else if (run > 1 && run < 42 && level == 1)
+    {
+        length = coeff_tab3[run-2].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
+            length += 8;
+        }
+    }
+    return length;
+}
+
+Int PutLevelCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run == 0 && level < 28)
+    {
+        length = coeff_tab4[level-1].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
+            length += 8;
+        }
+    }
+    else if (run == 1 && level < 11)
+    {
+        length = coeff_tab5[level-1].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
+            length += 8;
+        }
+    }
+    else if (run > 1 && run < 10 && level < 6)
+    {
+        length = coeff_tab6[run-2][level-1].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
+            length += 8;
+        }
+    }
+    else if (run > 9 && run < 15 && level == 1)
+    {
+        length = coeff_tab7[run-10].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
+            length += 8;
+        }
+    }
+    return length;
+}
+Int PutLevelCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+    Int length = 0;
+
+    if (run == 0 && level < 9)
+    {
+        length = coeff_tab8[level-1].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
+            length += 8;
+        }
+    }
+    else if (run > 0 && run < 7 && level < 4)
+    {
+        length = coeff_tab9[run-1][level-1].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
+            length += 8;
+        }
+    }
+    else if (run > 6 && run < 21 && level == 1)
+    {
+        length = coeff_tab10[run-7].len;
+        if (length)
+        {
+            BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+            BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
+            length += 8;
+        }
+    }
+    return length;
+}
+
+
+
+/* ======================================================================== */
+/*  Function : MBVlcEncode()                                                */
+/*  Date     : 09/10/2000                                                   */
+/*  Purpose  : Encode GOV Header                                            */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified : 5/21/01, break up into smaller functions                     */
+/* ======================================================================== */
+#ifndef H263_ONLY
+/**************************************/
+/* Data Partitioning I-VOP Encoding   */
+/**************************************/
+
+void MBVlcEncodeDataPar_I_VOP(
+    VideoEncData *video,
+    Int ncoefblck[],
+    void *blkCodePtr)
+{
+
+    BitstreamEncVideo *bs1 = video->bitstream1;
+    BitstreamEncVideo *bs2 = video->bitstream2;
+    BitstreamEncVideo *bs3 = video->bitstream3;
+    int i;
+    UChar Mode = video->headerInfo.Mode[video->mbnum];
+    UChar CBP;
+//  MacroBlock *MB=video->outputMB;
+    Int mbnum = video->mbnum;
+    Int intraDC_decision, DC;
+//  int temp;
+    Int dquant; /* 3/15/01 */
+    RunLevelBlock *RLB = video->RLB;
+    BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
+
+    /* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
+    DCACPred(video, Mode, &intraDC_decision, video->QP_prev);
+
+    /* CBP, Run, Level, and Sign */
+    RunLevel(video, 1, intraDC_decision, ncoefblck);
+    CBP = video->headerInfo.CBP[mbnum];
+
+    /* Compute DQuant */
+    dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
+
+    video->QP_prev = video->QPMB[mbnum];
+
+    if (dquant && Mode == MODE_INTRA)
+    {
+        Mode = MODE_INTRA_Q;
+    }
+
+    if (dquant >= 0)
+        dquant = (PV_ABS(dquant) + 1);
+    else
+        dquant = (PV_ABS(dquant) - 1);
+
+    /* FIRST PART: ALL TO BS1 */
+
+    PutMCBPC_Intra(CBP, Mode, bs1); /* MCBPC */
+
+    if (Mode == MODE_INTRA_Q)
+        /*  MAY NEED TO CHANGE DQUANT HERE  */
+        BitstreamPutBits(bs1, 2, dquant);  /* dquant*/
+
+
+    if (intraDC_decision == 0)
+    {
+        for (i = 0; i < 6; i++)
+        {
+            DC = video->RLB[i].level[0];
+            if (video->RLB[i].s[0])
+                DC = -DC;
+            if (i < 4)
+                /*temp =*/ IntraDC_dpcm(DC, 1, bs1);        /* dct_dc_size_luminance, */
+            else                                    /* dct_dc_differential, and */
+                /*temp =*/ IntraDC_dpcm(DC, 0, bs1);        /* marker bit */
+        }
+    }
+
+    /* SECOND PART: ALL TO BS2*/
+
+    BitstreamPut1Bits(bs2, video->acPredFlag[video->mbnum]);    /* ac_pred_flag */
+
+    /*temp=*/
+    PutCBPY(CBP >> 2, (Char)(1), bs2); /* cbpy */
+
+
+    /* THIRD PART:  ALL TO BS3*/
+    /* MB_CodeCoeff(video,bs3); */ /* 5/22/01, replaced with below */
+    for (i = 0; i < 6; i++)
+    {
+        if (CBP&(1 << (5 - i)))
+            (*BlockCodeCoeff)(&(RLB[i]), bs3, 1 - intraDC_decision, ncoefblck[i], Mode);/* Code Intra AC*/
+    }
+
+    return ;
+}
+
+/************************************/
+/* Data Partitioning P-VOP Encoding */
+/************************************/
+
+void MBVlcEncodeDataPar_P_VOP(
+    VideoEncData *video,
+    Int ncoefblck[],
+    void *blkCodePtr)
+{
+
+    BitstreamEncVideo *bs1 = video->bitstream1;
+    BitstreamEncVideo *bs2 = video->bitstream2;
+    BitstreamEncVideo *bs3 = video->bitstream3;
+    int i;
+    Int mbnum = video->mbnum;
+    UChar Mode = video->headerInfo.Mode[mbnum];
+    Int QP_tmp = video->QPMB[mbnum];
+    UChar CBP;
+//  MacroBlock *MB=video->outputMB;
+    Int intra, intraDC_decision, DC;
+    Int pmvx, pmvy;
+//  int temp;
+    Int dquant; /* 3/15/01 */
+    RunLevelBlock *RLB = video->RLB;
+    BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
+
+    intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+
+    /* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
+
+    if (intra)
+    {
+        if (video->usePrevQP)
+        {
+            QP_tmp = video->QPMB[mbnum-1];
+        }
+
+        DCACPred(video, Mode, &intraDC_decision, QP_tmp);
+    }
+    else
+        intraDC_decision = 0; /* used in RunLevel */
+
+    /* CBP, Run, Level, and Sign */
+    RunLevel(video, intra, intraDC_decision, ncoefblck);
+    CBP = video->headerInfo.CBP[mbnum];
+
+    /* Compute DQuant */
+    dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
+
+    if (dquant && (Mode == MODE_INTRA || Mode == MODE_INTER))
+    {
+        Mode += 2;  /* make it MODE_INTRA_Q and MODE_INTER_Q */
+    }
+
+    if (dquant >= 0)
+        dquant = (PV_ABS(dquant) + 1);
+    else
+        dquant = (PV_ABS(dquant) - 1);
+
+    /* FIRST PART: ALL TO BS1 */
+
+    if (CBP == 0 && intra == 0)  /* Determine if Skipped MB */
+    {
+        if ((Mode == MODE_INTER) && (video->mot[mbnum][0].x == 0) && (video->mot[mbnum][0].y == 0))
+            Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
+        else if ((Mode == MODE_INTER4V) && (video->mot[mbnum][1].x == 0) && (video->mot[mbnum][1].y == 0)
+                 && (video->mot[mbnum][2].x == 0) && (video->mot[mbnum][2].y == 0)
+                 && (video->mot[mbnum][3].x == 0) && (video->mot[mbnum][3].y == 0)
+                 && (video->mot[mbnum][4].x == 0) && (video->mot[mbnum][4].y == 0))
+            Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
+    }
+
+
+    if (Mode == MODE_SKIPPED)
+    {
+        BitstreamPut1Bits(bs1, 1); /* not_coded = 1 */
+        return;
+    }
+    else
+        BitstreamPut1Bits(bs1, 0); /* not_coded =0 */
+
+    video->QP_prev = video->QPMB[mbnum];
+    video->usePrevQP = 1;
+
+    PutMCBPC_Inter(CBP, Mode, bs1); /* MCBPC */
+
+    video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+
+    if (Mode == MODE_INTER || Mode == MODE_INTER_Q)
+    {
+        find_pmvs(video, 0, &pmvx, &pmvy); /* Get predicted motion vectors */
+        WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].x - pmvx, bs1); /* Write x to bitstream */
+        WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].y - pmvy, bs1);     /* Write y to bitstream */
+    }
+    else if (Mode == MODE_INTER4V)
+    {
+        for (i = 1; i < 5; i++)
+        {
+            find_pmvs(video, i, &pmvx, &pmvy);
+            WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].x - pmvx, bs1);
+            WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].y - pmvy, bs1);
+        }
+    }
+    video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+
+    /* SECOND PART: ALL TO BS2 */
+
+
+    if (intra)
+    {
+        BitstreamPut1Bits(bs2, video->acPredFlag[video->mbnum]);    /* ac_pred_flag */
+        /*temp=*/
+        PutCBPY(CBP >> 2, (Char)(Mode == MODE_INTRA || Mode == MODE_INTRA_Q), bs2); /* cbpy */
+
+        if (Mode == MODE_INTRA_Q)
+            BitstreamPutBits(bs2, 2, dquant);  /* dquant, 3/15/01*/
+
+        if (intraDC_decision == 0)
+        {
+            for (i = 0; i < 6; i++)
+            {
+                DC = video->RLB[i].level[0];
+                if (video->RLB[i].s[0])
+                    DC = -DC;
+                if (i < 4)
+                    /*temp =*/ IntraDC_dpcm(DC, 1, bs2);        /* dct_dc_size_luminance, */
+                else                                    /* dct_dc_differential, and */
+                    /*temp =*/ IntraDC_dpcm(DC, 0, bs2);        /* marker bit */
+            }
+        }
+
+        /****************************/  /* THIRD PART: ALL TO BS3 */
+        for (i = 0; i < 6; i++)
+        {
+            if (CBP&(1 << (5 - i)))
+                (*BlockCodeCoeff)(&(RLB[i]), bs3, 1 - intraDC_decision, ncoefblck[i], Mode);/* Code Intra AC*/
+        }
+    }
+    else
+    {
+        /*temp=*/
+        PutCBPY(CBP >> 2, (Char)(Mode == MODE_INTRA || Mode == MODE_INTRA_Q), bs2); /* cbpy */
+        if (Mode == MODE_INTER_Q)
+            /*  MAY NEED TO CHANGE DQUANT HERE  */
+            BitstreamPutBits(bs2, 2, dquant);  /* dquant, 3/15/01*/
+
+        /****************************/  /* THIRD PART: ALL TO BS3 */
+        for (i = 0; i < 6; i++)
+        {
+            if (CBP&(1 << (5 - i)))
+                (*BlockCodeCoeff)(&(RLB[i]), bs3, 0, ncoefblck[i], Mode);/* Code Intra AC*/
+        }
+    }
+
+    return ;
+}
+#endif /* H263_ONLY */
+/****************************************************************************************/
+/* Short Header/Combined Mode with or without Error Resilience I-VOP and P-VOP Encoding */
+/* 5/21/01, B-VOP is not implemented yet!!!!                                            */
+/****************************************************************************************/
+
+void MBVlcEncodeCombined_I_VOP(
+    VideoEncData *video,
+    Int ncoefblck[],
+    void *blkCodePtr)
+{
+
+    BitstreamEncVideo *bs1 = video->bitstream1;
+//  BitstreamEncVideo *bs2 = video->bitstream2;
+//  BitstreamEncVideo *bs3 = video->bitstream3;
+    int i;
+    UChar Mode = video->headerInfo.Mode[video->mbnum];
+    UChar CBP = video->headerInfo.CBP[video->mbnum];
+//  MacroBlock *MB=video->outputMB;
+    Int mbnum = video->mbnum;
+    Int intraDC_decision;
+//  int temp;
+    Int dquant; /* 3/15/01 */
+    RunLevelBlock *RLB = video->RLB;
+    Int DC;
+    Int shortVideoHeader = video->vol[video->currLayer]->shortVideoHeader;
+    BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
+
+    /* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
+
+#ifndef H263_ONLY
+    if (!shortVideoHeader)
+        DCACPred(video, Mode, &intraDC_decision, video->QP_prev);
+    else
+#endif
+    {
+        intraDC_decision = 0;
+    }
+
+    /* CBP, Run, Level, and Sign */
+
+    RunLevel(video, 1, intraDC_decision, ncoefblck);
+    CBP = video->headerInfo.CBP[mbnum];
+
+    /* Compute DQuant */
+    dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
+
+    video->QP_prev = video->QPMB[mbnum];
+
+    if (dquant && Mode == MODE_INTRA)
+    {
+        Mode = MODE_INTRA_Q;
+    }
+
+    if (dquant >= 0)
+        dquant = (PV_ABS(dquant) + 1);
+    else
+        dquant = (PV_ABS(dquant) - 1);
+
+    PutMCBPC_Intra(CBP, Mode, bs1); /* mcbpc I_VOP */
+
+    if (!video->vol[video->currLayer]->shortVideoHeader)
+    {
+        BitstreamPut1Bits(bs1, video->acPredFlag[video->mbnum]);    /* ac_pred_flag */
+    }
+
+    /*temp=*/
+    PutCBPY(CBP >> 2, (Char)(1), bs1); /* cbpy */
+
+    if (Mode == MODE_INTRA_Q)
+        /*  MAY NEED TO CHANGE DQUANT HERE */
+        BitstreamPutBits(bs1, 2, dquant);  /* dquant, 3/15/01*/
+
+    /*MB_CodeCoeff(video,bs1); 5/21/01, replaced by below */
+    /*******************/
+#ifndef H263_ONLY
+    if (shortVideoHeader) /* Short Header DC coefficients */
+    {
+#endif
+        for (i = 0; i < 6; i++)
+        {
+            DC = RLB[i].level[0];
+            if (RLB[i].s[0])
+                DC = -DC;
+            if (DC != 128)
+                BitstreamPutBits(bs1, 8, DC);   /* intra_dc_size_luminance */
+            else
+                BitstreamPutBits(bs1, 8, 255);          /* intra_dc_size_luminance */
+            if (CBP&(1 << (5 - i)))
+                (*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode); /* Code short header Intra AC*/
+        }
+#ifndef H263_ONLY
+    }
+    else if (intraDC_decision == 0)   /* Combined Intra Mode DC and AC coefficients */
+    {
+        for (i = 0; i < 6; i++)
+        {
+            DC = RLB[i].level[0];
+            if (RLB[i].s[0])
+                DC = -DC;
+
+            if (i < 4)
+                /*temp =*/ IntraDC_dpcm(DC, 1, bs1);        /* dct_dc_size_luminance, */
+            else                                                /* dct_dc_differential, and */
+                /*temp =*/ IntraDC_dpcm(DC, 0, bs1);        /* marker bit */
+            if (CBP&(1 << (5 - i)))
+                (*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode);/* Code Intra AC */
+        }
+    }
+    else   /* Combined Mode Intra DC/AC coefficients */
+    {
+        for (i = 0; i < 6; i++)
+        {
+            if (CBP&(1 << (5 - i)))
+                (*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Intra AC */
+        }
+    }
+#endif
+    /*******************/
+    return ;
+}
+
+void MBVlcEncodeCombined_P_VOP(
+    VideoEncData *video,
+    Int ncoefblck[],
+    void *blkCodePtr)
+{
+
+    BitstreamEncVideo *bs1 = video->bitstream1;
+//  BitstreamEncVideo *bs2 = video->bitstream2;
+//  BitstreamEncVideo *bs3 = video->bitstream3;
+    int i;
+    Int mbnum = video->mbnum;
+    UChar Mode = video->headerInfo.Mode[mbnum];
+    Int QP_tmp = video->QPMB[mbnum];
+    UChar CBP ;
+//  MacroBlock *MB=video->outputMB;
+    Int intra, intraDC_decision;
+    Int pmvx, pmvy;
+//  int temp;
+    Int dquant; /* 3/15/01 */
+    RunLevelBlock *RLB = video->RLB;
+    Int DC;
+    Int shortVideoHeader = video->vol[video->currLayer]->shortVideoHeader;
+    BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
+
+    intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+
+    /* DC and AC Prediction, 5/28/01, compute intraDC_decision*/
+#ifndef H263_ONLY
+    if (!shortVideoHeader && intra)
+    {
+        if (video->usePrevQP)
+        {
+            QP_tmp = video->QPMB[mbnum-1];
+        }
+        DCACPred(video, Mode, &intraDC_decision, QP_tmp);
+    }
+    else
+#endif
+        intraDC_decision = 0;
+
+    /* CBP, Run, Level, and Sign */
+
+    RunLevel(video, intra, intraDC_decision, ncoefblck);
+    CBP = video->headerInfo.CBP[mbnum];
+
+    /* Compute DQuant */
+    dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
+    if (dquant && (Mode == MODE_INTRA || Mode == MODE_INTER))
+    {
+        Mode += 2;  /* make it MODE_INTRA_Q and MODE_INTER_Q */
+    }
+
+    if (dquant >= 0)
+        dquant = (PV_ABS(dquant) + 1);
+    else
+        dquant = (PV_ABS(dquant) - 1);
+
+    if (CBP == 0 && intra == 0)  /* Determine if Skipped MB */
+    {
+        if ((Mode == MODE_INTER) && (video->mot[mbnum][0].x == 0) && (video->mot[mbnum][0].y == 0))
+            Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
+        else if ((Mode == MODE_INTER4V) && (video->mot[mbnum][1].x == 0) && (video->mot[mbnum][1].y == 0)
+                 && (video->mot[mbnum][2].x == 0) && (video->mot[mbnum][2].y == 0)
+                 && (video->mot[mbnum][3].x == 0) && (video->mot[mbnum][3].y == 0)
+                 && (video->mot[mbnum][4].x == 0) && (video->mot[mbnum][4].y == 0))
+            Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
+    }
+
+    if (Mode == MODE_SKIPPED)
+    {
+        BitstreamPut1Bits(bs1, 1); /* not_coded = 1 */
+        return;
+    }
+    else
+        BitstreamPut1Bits(bs1, 0); /* not_coded =0 */
+
+    video->QP_prev = video->QPMB[mbnum];
+    video->usePrevQP = 1;
+
+    PutMCBPC_Inter(CBP, Mode, bs1); /* mcbpc P_VOP */
+
+    if (!video->vol[video->currLayer]->shortVideoHeader && intra)
+    {
+        BitstreamPut1Bits(bs1, video->acPredFlag[video->mbnum]);    /* ac_pred_flag */
+    }
+
+    /*temp=*/
+    PutCBPY(CBP >> 2, (Char)(intra), bs1); /* cbpy */
+
+    if (Mode == MODE_INTRA_Q || Mode == MODE_INTER_Q)
+        /*  MAY NEED TO CHANGE DQUANT HERE  */
+        BitstreamPutBits(bs1, 2, dquant);  /* dquant, 3/15/01*/
+
+    video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+
+    if (!((video->vol[video->currLayer]->scalability) && (video->currVop->refSelectCode == 3)))
+    {
+        if (Mode == MODE_INTER || Mode == MODE_INTER_Q)
+        {
+            find_pmvs(video, 0, &pmvx, &pmvy); /* Get predicted motion vectors */
+            WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].x - pmvx, bs1); /* Write x to bitstream */
+            WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].y - pmvy, bs1);     /* Write y to bitstream */
+        }
+        else if (Mode == MODE_INTER4V)
+        {
+            for (i = 1; i < 5; i++)
+            {
+                find_pmvs(video, i, &pmvx, &pmvy);
+                WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].x - pmvx, bs1);
+                WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].y - pmvy, bs1);
+            }
+        }
+    }
+    video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+
+    /* MB_CodeCoeff(video,bs1); */ /* 5/22/01, replaced with below */
+    /****************************/
+    if (intra)
+    {
+#ifndef H263_ONLY
+        if (shortVideoHeader) /* Short Header DC coefficients */
+        {
+#endif
+            for (i = 0; i < 6; i++)
+            {
+                DC = RLB[i].level[0];
+                if (RLB[i].s[0])
+                    DC = -DC;
+                if (DC != 128)
+                    BitstreamPutBits(bs1, 8, DC);   /* intra_dc_size_luminance */
+                else
+                    BitstreamPutBits(bs1, 8, 255);          /* intra_dc_size_luminance */
+                if (CBP&(1 << (5 - i)))
+                    (*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode); /* Code short header Intra AC*/
+            }
+#ifndef H263_ONLY
+        }
+        else if (intraDC_decision == 0)   /* Combined Intra Mode DC and AC coefficients */
+        {
+            for (i = 0; i < 6; i++)
+            {
+                DC = RLB[i].level[0];
+                if (RLB[i].s[0])
+                    DC = -DC;
+
+                if (i < 4)
+                    /*temp =*/ IntraDC_dpcm(DC, 1, bs1);        /* dct_dc_size_luminance, */
+                else                                                /* dct_dc_differential, and */
+                    /*temp =*/ IntraDC_dpcm(DC, 0, bs1);        /* marker bit */
+                if (CBP&(1 << (5 - i)))
+                    (*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode);/* Code Intra AC */
+            }
+        }
+        else   /* Combined Mode Intra DC/AC coefficients */
+        {
+            for (i = 0; i < 6; i++)
+            {
+                if (CBP&(1 << (5 - i)))
+                    (*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Intra AC */
+            }
+        }
+#endif
+    }
+    else   /* Shortheader or Combined INTER Mode AC coefficients */
+    {
+        for (i = 0; i < 6; i++)
+        {
+            if (CBP&(1 << (5 - i)))
+                (*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Inter AC*/
+        }
+    }
+    /****************************/
+
+    return ;
+}
+
+/* ======================================================================== */
+/*  Function : BlockCodeCoeff()                                         */
+/*  Date     : 09/18/2000                                                   */
+/*  Purpose  : VLC Encode  AC/DC coeffs                                     */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :  5/16/01  grouping BitstreamPutBits calls                    */
+/*              5/22/01  break up function                              */
+/* ======================================================================== */
+#ifndef NO_RVLC
+/*****************/
+/* RVLC ENCODING */
+/*****************/
+Void BlockCodeCoeff_RVLC(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
+{
+    int length = 0;
+    int i;
+    Int level;
+    Int run;
+    Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+
+    /* Not Last Coefficient */
+    for (i = j_start; i < j_stop - 1; i++)
+    {
+        run = RLB->run[i];
+        level = RLB->level[i];
+        //if(i==63||RLB->run[i+1] == -1)    /* Don't Code Last Coefficient Here */
+        //  break;
+        /*ENCODE RUN LENGTH */
+        if (level < 28 && run < 39)
+        {
+            if (intra)
+                length = PutCoeff_Intra_RVLC(run, level, bs);
+            else
+                length = PutCoeff_Inter_RVLC(run, level, bs);
+        }
+        else
+            length = 0;
+        /* ESCAPE CODING */
+        if (length == 0)
+        {
+            BitstreamPutBits(bs, 5 + 1, 2); /* ESCAPE + Not Last Coefficient */
+            //BitstreamPutBits(bs,1,0); /* Not Last Coefficient */
+            BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* RUN + MARKER BIT*/
+            //BitstreamPutBits(bs,1,1);  /* MARKER BIT */
+            BitstreamPutGT8Bits(bs, 11, level); /* LEVEL */
+            BitstreamPutBits(bs, 1 + 4, 16); /* MARKER BIT */
+            //BitstreamPutBits(bs,4,0);  /* RVLC TRAILING ESCAPE */
+        }
+        BitstreamPutBits(bs, 1, RLB->s[i]); /* SIGN BIT */
+    }
+    /* Last Coefficient!!! */
+    run = RLB->run[i];
+    level = RLB->level[i];
+
+    /*ENCODE RUN LENGTH */
+    if (level < 6 && run < 45)
+    {
+        if (intra)
+            length = PutCoeff_Intra_RVLC_Last(run, level, bs);
+        else
+            length = PutCoeff_Inter_RVLC_Last(run, level, bs);
+    }
+    else
+        length = 0;
+    /* ESCAPE CODING */
+    if (length == 0)
+    {
+        BitstreamPutBits(bs, 5 + 1, 3); /* ESCAPE CODE + Last Coefficient*/
+        //BitstreamPutBits(bs,1,1); /* Last Coefficient !*/
+        BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* RUN + MARKER BIT*/
+        //BitstreamPutBits(bs,1,1);  /* MARKER BIT */
+        BitstreamPutGT8Bits(bs, 11, level); /* LEVEL */
+        BitstreamPutBits(bs, 1 + 4, 16); /* MARKER BIT + RVLC TRAILING ESCAPE */
+        //BitstreamPutBits(bs,4,0);  /* */
+    }
+    BitstreamPut1Bits(bs, RLB->s[i]); /* SIGN BIT */
+
+    return ;
+}
+#endif
+/*******************************/
+/* SHORT VIDEO HEADER ENCODING */
+/*******************************/
+
+Void BlockCodeCoeff_ShortHeader(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
+{
+    int length = 0;
+    int i;
+//  int temp;
+    Int level;
+    Int run;
+
+    OSCL_UNUSED_ARG(Mode);
+
+    /* Not Last Coefficient */
+    for (i = j_start; i < j_stop - 1; i++)
+    {
+        run = RLB->run[i];
+        level = RLB->level[i];
+//      if(i==63 ||RLB->run[i+1] == -1) /* Don't Code Last Coefficient Here */
+//          break;
+        /*ENCODE RUN LENGTH */
+        if (level < 13)
+        {
+            length = PutCoeff_Inter(run, level, bs);
+            if (length != 0)
+                /*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
+        }
+        else
+            length = 0;
+        /* ESCAPE CODING */
+        if (length == 0)
+        {
+            if (RLB->s[i])
+                level = -level;
+            BitstreamPutBits(bs, 7 + 1, 6); /* ESCAPE CODE + Not Last Coefficient */
+            //BitstreamPutBits(bs,1,0); /* Not Last Coefficient */
+            BitstreamPutBits(bs, 6, run); /* RUN */
+            BitstreamPutBits(bs, 8, level&0xFF); /* LEVEL, mask to make sure length 8 */
+        }
+    }
+    /* Last Coefficient!!! */
+    run = RLB->run[i];
+    level = RLB->level[i];
+
+    /*ENCODE RUN LENGTH */
+    if (level < 13)
+    {
+        length = PutCoeff_Inter_Last(run, level, bs);
+        if (length != 0)
+            /*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
+    }
+    else
+        length = 0;
+    /* ESCAPE CODING */
+    if (length == 0)
+    {
+        if (RLB->s[i])
+            level = -level;
+        BitstreamPutBits(bs, 7 + 1, 7); /* ESCAPE CODE + Last Coefficient */
+        //BitstreamPutBits(bs,1,1); /* Last Coefficient !!!*/
+        BitstreamPutBits(bs, 6, run); /* RUN */
+        BitstreamPutBits(bs, 8, level&0xFF); /* LEVEL, mask to make sure length 8  */
+    }
+
+    return ;
+
+}
+
+#ifndef H263_ONLY
+/****************/
+/* VLC ENCODING */
+/****************/
+Void BlockCodeCoeff_Normal(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
+{
+    int length = 0;
+    int i;
+    //int temp;
+    Int level;
+    Int run;
+    Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+    Int level_minus_max;
+    Int run_minus_max;
+    Int(*PutCoeff)(Int, Int, BitstreamEncVideo *); /* pointer to functions, 5/28/01 */
+
+    /* Not Last Coefficient!!! */
+
+    if (intra)
+        PutCoeff = &PutCoeff_Intra;
+    else
+        PutCoeff = &PutCoeff_Inter;
+
+    for (i = j_start; i < j_stop - 1; i++)
+    {
+        run = RLB->run[i];
+        level = RLB->level[i];
+
+        /* Encode Run Length */
+        if (level < 28)
+        {
+            length = (*PutCoeff)(run, level, bs); /* 5/28/01 replaces above */
+        }
+        else
+        {
+            length = 0;
+        }
+
+        /* First escape mode: LEVEL OFFSET */
+        if (length == 0)
+        {
+            if (intra)
+            {
+                level_minus_max = level - intra_max_level[0][run];
+                if (level_minus_max < 28)
+                    length = PutLevelCoeff_Intra(run, level_minus_max, bs);
+                else
+                    length = 0;
+            }
+            else
+            {
+                level_minus_max = level - inter_max_level[0][run];
+                if (level_minus_max < 13)
+                    length = PutLevelCoeff_Inter(run, level_minus_max, bs);
+                else
+                    length = 0;
+            }
+
+            /* Second escape mode: RUN OFFSET */
+            if (length == 0)
+            {
+                if (level < 28)
+                {
+                    if (intra)
+                    {
+                        run_minus_max = run - (intra_max_run0[level] + 1);
+                        length = PutRunCoeff_Intra(run_minus_max, level, bs);
+                    }
+                    else if (level < 13)
+                    {
+                        run_minus_max = run - (inter_max_run0[level] + 1);
+                        length = PutRunCoeff_Inter(run_minus_max, level, bs);
+                    }
+                    else
+                    {
+                        length = 0;
+                    }
+                }
+                else
+                {
+                    length = 0;
+                }
+
+                /* Third escape mode: FIXED LENGTH CODE */
+                if (length == 0)
+                {
+                    if (RLB->s[i])
+                        level = -level;
+                    /*temp =*/
+                    BitstreamPutBits(bs, 7 + 2 + 1, 30); /* ESCAPE CODE + Followed by 11 + Not Last Coefficient*/
+                    //temp = BitstreamPutBits(bs,2,3); /* Followed by 11 */
+                    //temp = BitstreamPutBits(bs, 1, 0); /* Not Last Coefficient*/
+                    /*temp =*/
+                    BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* Encode Run + Marker Bit */
+                    //temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
+                    /*temp =*/
+                    BitstreamPutGT8Bits(bs, 12 + 1, ((level << 1) | 1)&0x1FFF); /* Encode Level, mask to make sure length 12  */
+                    //temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
+                }
+            }
+        }
+
+        /* Encode Sign Bit */
+        if (length != 0)
+            /*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
+
+    }
+    /* Last Coefficient */
+    run = RLB->run[i];
+    level = RLB->level[i];
+
+    /* Encode Run Length */
+    if (level < 9)
+    {
+        if (intra)
+        {
+            length = PutCoeff_Intra_Last(run, level, bs);
+        }
+        else if (level < 4)
+        {
+            length = PutCoeff_Inter_Last(run, level, bs);
+        }
+        else
+        {
+            length = 0;
+        }
+    }
+    else
+    {
+        length = 0;
+    }
+
+    /* First escape mode: LEVEL OFFSET */
+    if (length == 0)
+    {
+        if (intra)
+        {
+            level_minus_max = level - intra_max_level[1][run];
+            if (level_minus_max < 9)
+                length = PutLevelCoeff_Intra_Last(run, level_minus_max, bs);
+            else
+                length = 0;
+        }
+        else
+        {
+            level_minus_max = level - inter_max_level[1][run];
+            if (level_minus_max < 4)
+                length = PutLevelCoeff_Inter_Last(run, level_minus_max, bs);
+            else
+                length = 0;
+        }
+        /* Second escape mode: RUN OFFSET */
+        if (length == 0)
+        {
+            if (level < 9)
+            {
+                if (intra)
+                {
+                    run_minus_max = run - (intra_max_run1[level] + 1);
+                    length = PutRunCoeff_Intra_Last(run_minus_max, level, bs);
+                }
+                else if (level < 4)
+                {
+                    run_minus_max = run - (inter_max_run1[level] + 1);
+                    length = PutRunCoeff_Inter_Last(run_minus_max, level, bs);
+                }
+                else
+                {
+                    length = 0;
+                }
+            }
+            else
+            {
+                length = 0;
+            }
+            /* Third escape mode: FIXED LENGTH CODE */
+            if (length == 0)
+            {
+                if (RLB->s[i])
+                    level = -level;
+                /*temp =*/
+                BitstreamPutGT8Bits(bs, 7 + 2 + 1, 31); /* ESCAPE CODE + Followed by 11 + Last Coefficient*/
+                //temp = BitstreamPutBits(bs,2,3); /* Followed by 11 */
+                //temp = BitstreamPutBits(bs, 1, 1); /* Last Coefficient!!!*/
+                /*temp =*/
+                BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* Encode Run + Marker Bit */
+                //temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
+                /*temp =*/
+                BitstreamPutGT8Bits(bs, 12 + 1, ((level << 1) | 1)&0x1FFF); /* Encode Level, mask to make sure length 8 */
+                //temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
+            }
+        }
+    }
+
+    /* Encode Sign Bit */
+    if (length != 0)
+        /*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]);
+
+
+    return ;
+}
+
+#endif /* H263_ONLY */
+/* ======================================================================== */
+/*  Function : RUNLevel                                                     */
+/*  Date     : 09/20/2000                                                   */
+/*  Purpose  : Get the Coded Block Pattern for each block                   */
+/*  In/out   :                                                              */
+/*      Int* qcoeff     Quantized DCT coefficients
+        Int Mode        Coding Mode
+        Int ncoeffs     Number of coefficients                              */
+/*  Return   :                                                              */
+/*      Int CBP         Coded Block Pattern                                 */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+void RunLevel(VideoEncData *video, Int intra, Int intraDC_decision, Int ncoefblck[])
+{
+    Int i, j;
+    Int CBP = video->headerInfo.CBP[video->mbnum];
+    Int ShortNacNintra = (!(video->vol[video->currLayer]->shortVideoHeader) && video->acPredFlag[video->mbnum] && intra);
+    MacroBlock *MB = video->outputMB;
+    Short *dataBlock;
+    Int level;
+    RunLevelBlock *RLB;
+    Int run, idx;
+    Int *zz, nc, zzorder;
+    UChar imask[6] = {0x1F, 0x2F, 0x37, 0x3B, 0x3D, 0x3E};
+    UInt *bitmapzz;
+
+    /* Set Run, Level and CBP for this Macroblock */
+    /* ZZ scan is done here.  */
+
+    if (intra)
+    {
+
+        if (intraDC_decision != 0)
+            intra = 0;              /* DC/AC in Run/Level */
+
+        for (i = 0; i < 6 ; i++)
+        {
+
+            zz = (Int *) zigzag_inv;
+
+            RLB = video->RLB + i;
+
+            dataBlock = MB->block[i];
+
+            if (intra)
+            {
+                RLB->run[0] = 0;
+                level = dataBlock[0];
+                dataBlock[0] = 0; /* reset to zero */
+                if (level < 0)
+                {
+                    RLB->level[0] = -level;
+                    RLB->s[0] = 1;
+                }
+                else
+                {
+                    RLB->level[0] = level;
+                    RLB->s[0] = 0;
+                }
+            }
+
+            idx = intra;
+
+            if ((CBP >> (5 - i)) & 1)
+            {
+                if (ShortNacNintra)
+                {
+                    switch ((video->zz_direction >> (5 - i))&1)
+                    {
+                        case 0:
+                            zz = (Int *)zigzag_v_inv;
+                            break;
+                        case 1:
+                            zz = (Int *)zigzag_h_inv;
+                            break;
+                    }
+                }
+                run = 0;
+                nc = ncoefblck[i];
+                for (j = intra, zz += intra; j < nc; j++, zz++)
+                {
+                    zzorder = *zz;
+                    level = dataBlock[zzorder];
+                    if (level == 0)
+                        run++;
+                    else
+                    {
+                        dataBlock[zzorder] = 0; /* reset output */
+                        if (level < 0)
+                        {
+                            RLB->level[idx] = -level;
+                            RLB->s[idx] = 1;
+                            RLB->run[idx] = run;
+                            run = 0;
+                            idx++;
+                        }
+                        else
+                        {
+                            RLB->level[idx] = level;
+                            RLB->s[idx] = 0;
+                            RLB->run[idx] = run;
+                            run = 0;
+                            idx++;
+                        }
+                    }
+                }
+            }
+
+            ncoefblck[i] = idx; /* 5/22/01, reuse ncoefblck */
+
+            if (idx == intra) /* reset CBP, nothing to be coded */
+                CBP &= imask[i];
+        }
+
+        video->headerInfo.CBP[video->mbnum] = CBP;
+
+        return ;
+    }
+    else
+    {
+//      zz = (Int *) zigzag_inv;  no need to use it, default
+
+        if (CBP)
+        {
+            for (i = 0; i < 6 ; i++)
+            {
+                RLB = video->RLB + i;
+                idx = 0;
+
+                if ((CBP >> (5 - i)) & 1)
+                {   /* 7/30/01 */
+                    /* Use bitmapzz to find the Run,Level,Sign symbols */
+                    bitmapzz = video->bitmapzz[i];
+                    dataBlock = MB->block[i];
+                    nc  = ncoefblck[i];
+
+                    idx = zero_run_search(bitmapzz, dataBlock, RLB, nc);
+                }
+                ncoefblck[i] = idx; /* 5/22/01, reuse ncoefblck */
+                if (idx == 0) /* reset CBP, nothing to be coded */
+                    CBP &= imask[i];
+            }
+            video->headerInfo.CBP[video->mbnum] = CBP;
+        }
+        return ;
+    }
+}
+
+#ifndef H263_ONLY
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    static Bool IntraDCSwitch_Decision(Int Mode, Int intra_dc_vlc_thr, Int intraDCVlcQP)
+    {
+        Bool switched = FALSE;
+
+        if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
+        {
+            if (intra_dc_vlc_thr != 0)
+            {
+                switched = (intra_dc_vlc_thr == 7 || intraDCVlcQP >= intra_dc_vlc_thr * 2 + 11);
+            }
+        }
+
+        return switched;
+    }
+#ifdef __cplusplus
+}
+#endif
+
+Int IntraDC_dpcm(Int val, Int lum, BitstreamEncVideo *bitstream)
+{
+    Int n_bits;
+    Int absval, size = 0;
+
+    absval = (val < 0) ? -val : val;    /* abs(val) */
+
+
+    /* compute dct_dc_size */
+
+    size = 0;
+    while (absval)
+    {
+        absval >>= 1;
+        size++;
+    }
+
+    if (lum)
+    {   /* luminance */
+        n_bits = PutDCsize_lum(size, bitstream);
+    }
+    else
+    {   /* chrominance */
+        n_bits = PutDCsize_chrom(size, bitstream);
+    }
+
+    if (size != 0)
+    {
+        if (val >= 0)
+        {
+            ;
+        }
+        else
+        {
+            absval = -val; /* set to "-val" MW 14-NOV-1996 */
+            val = absval ^((1 << size) - 1);
+        }
+        BitstreamPutBits(bitstream, (size), (UInt)(val));
+        n_bits += size;
+
+        if (size > 8)
+            BitstreamPut1Bits(bitstream, 1);
+    }
+
+    return n_bits;  /* # bits for intra_dc dpcm */
+
+}
+
+/* ======================================================================== */
+/*  Function : DC_AC_PRED                                                   */
+/*  Date     : 09/24/2000                                                   */
+/*  Purpose  : DC and AC encoding of Intra Blocks                           */
+/*  In/out   :                                                              */
+/*      VideoEncData    *video
+        UChar           Mode                                                */
+/*  Return   :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+Int cal_dc_scalerENC(Int QP, Int type) ;
+
+
+#define PREDICT_AC  for (m = 0; m < 7; m++){ \
+                        tmp = DCAC[0]*QPtmp;\
+                        if(tmp<0)   tmp = (tmp-(QP/2))/QP;\
+                        else        tmp = (tmp+(QP/2))/QP;\
+                        pred[m] = tmp;\
+                        DCAC++;\
+                    }
+
+
+Void DCACPred(VideoEncData *video, UChar Mode, Int *intraDC_decision, Int intraDCVlcQP)
+{
+    MacroBlock *MB = video->outputMB;
+    Int mbnum = video->mbnum;
+    typeDCStore *DC_store = video->predDC + mbnum;
+    typeDCACStore *DCAC_row = video->predDCAC_row;
+    typeDCACStore *DCAC_col = video->predDCAC_col;
+    Short   *DCAC;
+    UChar Mode_top, Mode_left;
+
+    Vol *currVol = video->vol[video->currLayer];
+    Int nMBPerRow = currVol->nMBPerRow;
+    Int x_pos = video->outputMB->mb_x; /* 5/28/01 */
+    Int y_pos = video->outputMB->mb_y;
+    UChar QP = video->QPMB[mbnum];
+    UChar *QPMB = video->QPMB;
+    UChar *slice_nb = video->sliceNo;
+    Bool bACPredEnable = video->encParams->ACDCPrediction;
+    Int *ACpred_flag = video->acPredFlag;
+    Int mid_grey = 128 << 3;
+    Int m;
+    Int comp;
+    Int dc_scale = 8, tmp;
+
+    static const Int Xpos[6] = { -1, 0, -1, 0, -1, -1};
+    static const Int Ypos[6] = { -1, -1, 0, 0, -1, -1};
+    static const Int Xtab[6] = {1, 0, 3, 2, 4, 5};
+    static const Int Ytab[6] = {2, 3, 0, 1, 4, 5};
+    static const Int Ztab[6] = {3, 2, 1, 0, 4, 5};
+
+    /* I added these to speed up comparisons */
+    static const Int Pos0[6] = { 1, 1, 0, 0, 1, 1};
+    static const Int Pos1[6] = { 1, 0, 1, 0, 1, 1};
+    static const Int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
+    static const Int B_Ytab[6] = {0, 0, 1, 1, 2, 3};
+
+    Int direction[6];       /* 0: HORIZONTAL, 1: VERTICAL */
+    Int block_A, block_B, block_C;
+    Int grad_hor, grad_ver, DC_pred;
+    Short pred[7], *predptr;
+    Short pcoeff[42];
+    Short *qcoeff;
+    Int S = 0, S1, S2;
+    Int diff, QPtmp;
+    Int newCBP[6];
+    UChar mask1[6] = {0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
+//  UChar mask2[6] = {0x1f,0x2f,0x37,0x3b,0x3d,0x3e};
+
+    Int y_offset, x_offset, x_tab, y_tab, z_tab;    /* speedup coefficients */
+    Int b_xtab, b_ytab;
+
+    video->zz_direction = 0;
+
+    /* Standard MPEG-4 Headers do DC/AC prediction*/
+    /* check whether neighbors are INTER */
+    if (y_pos > 0)
+    {
+        Mode_top = video->headerInfo.Mode[mbnum-nMBPerRow];
+        if (!(Mode_top == MODE_INTRA || Mode_top == MODE_INTRA_Q))
+        {
+            DCAC = DC_store[-nMBPerRow];
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            /* set to 0 DCAC_row[x_pos][0..3] */
+            if (bACPredEnable == TRUE)
+            {
+                M4VENC_MEMSET(DCAC_row[x_pos][0], 0, sizeof(Short) << 5);
+            }
+        }
+    }
+    if (x_pos > 0)
+    {
+        Mode_left = video->headerInfo.Mode[mbnum-1];
+        if (!(Mode_left == MODE_INTRA || Mode_left == MODE_INTRA_Q))
+        {
+            DCAC = DC_store[-1];
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            *DCAC++ = mid_grey;
+            /* set to 0 DCAC_col[x_pos][0..3] */
+            if (bACPredEnable == TRUE)
+            {
+                M4VENC_MEMSET(DCAC_col[0][0], 0, sizeof(Short) << 5);
+            }
+        }
+    }
+
+    S1 = 0;
+    S2 = 0;
+
+    for (comp = 0; comp < 6; comp++)
+    {
+
+        if (Ypos[comp] != 0)        y_offset = -nMBPerRow;
+        else                    y_offset = 0;
+        x_offset = Xpos[comp];
+        x_tab = Xtab[comp];
+        y_tab = Ytab[comp];
+        z_tab = Ztab[comp];
+
+        b_xtab = B_Xtab[comp];
+        b_ytab = B_Ytab[comp];
+
+        qcoeff = MB->block[comp];
+
+        /****************************/
+        /*  Store DC coefficients */
+        /****************************/
+        /* Store coeff values for Intra MB */
+        if (comp == 0) dc_scale = cal_dc_scalerENC(QP, 1) ;
+        if (comp == 4) dc_scale = cal_dc_scalerENC(QP, 2) ;
+
+        QPtmp = qcoeff[0] * dc_scale; /* DC value */
+
+        if (QPtmp > 2047)   /* 10/10/01, add clipping (bug fixed) */
+            DC_store[0][comp] = 2047;
+        else if (QPtmp < -2048)
+            DC_store[0][comp] = -2048;
+        else
+            DC_store[0][comp] = QPtmp;
+
+        /**************************************************************/
+        /* Find the direction of the prediction and the DC prediction */
+        /**************************************************************/
+
+        if ((x_pos == 0) && y_pos == 0)
+        {   /* top left corner */
+            block_A = (comp == 1 || comp == 3) ? DC_store[0][x_tab] : mid_grey;
+            block_B = (comp == 3) ? DC_store[x_offset][z_tab] : mid_grey;
+            block_C = (comp == 2 || comp == 3) ? DC_store[0][y_tab] : mid_grey;
+        }
+        else if (x_pos == 0)
+        {   /* left edge */
+            block_A = (comp == 1 || comp == 3) ? DC_store[0][x_tab] : mid_grey;
+            block_B = ((comp == 1 && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])) || comp == 3) ?
+                      DC_store[y_offset+x_offset][z_tab] : mid_grey;
+            block_C = (comp == 2 || comp == 3 ||
+                       (Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))) ?
+                      DC_store[y_offset][y_tab] : mid_grey;
+        }
+        else if (y_pos == 0)
+        { /* top row */
+            block_A = (comp == 1 || comp == 3 || (Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))) ?
+                      DC_store[x_offset][x_tab] : mid_grey;
+            block_B = ((comp == 2 && (slice_nb[mbnum] == slice_nb[mbnum-1])) || comp == 3) ?
+                      DC_store[y_offset + x_offset][z_tab] : mid_grey;
+            block_C = (comp == 2 || comp == 3) ?
+                      DC_store[y_offset][y_tab] : mid_grey;
+        }
+        else
+        {
+            block_A = (comp == 1 || comp == 3 || (Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))) ?
+                      DC_store[x_offset][x_tab] : mid_grey;
+            block_B = (((comp == 0 || comp == 4 || comp == 5) &&
+                        (slice_nb[mbnum] == slice_nb[mbnum-1-nMBPerRow])) ||
+                       (comp == 1 && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])) ||
+                       (comp == 2 && (slice_nb[mbnum] == slice_nb[mbnum-1])) || (comp == 3)) ?
+                      (DC_store[y_offset + x_offset][z_tab]) : mid_grey;
+            block_C = (comp == 2 || comp == 3 || (Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))) ?
+                      DC_store[y_offset][y_tab] : mid_grey;
+        }
+        grad_hor = block_B - block_C;
+        grad_ver = block_A - block_B;
+
+        if ((PV_ABS(grad_ver)) < (PV_ABS(grad_hor)))
+        {
+            DC_pred = block_C;
+            direction[comp] = 1;
+            video->zz_direction = (video->zz_direction) | mask1[comp];
+
+        }
+        else
+        {
+            DC_pred = block_A;
+            direction[comp] = 0;
+            //video->zz_direction=video->zz_direction<<1;
+        }
+
+        /* DC prediction */
+        QPtmp = dc_scale; /* 5/28/01 */
+        qcoeff[0] -= (DC_pred + QPtmp / 2) / QPtmp;
+
+
+        if (bACPredEnable)
+        {
+            /***********************/
+            /* Find AC prediction  */
+            /***********************/
+
+            if ((x_pos == 0) && y_pos == 0)     /* top left corner */
+            {
+                if (direction[comp] == 0)
+                {
+                    if (comp == 1 || comp == 3)
+                    {
+                        QPtmp = QPMB[mbnum+x_offset];
+                        DCAC = DCAC_col[0][b_ytab];
+                        if (QPtmp != QP)
+                        {
+                            predptr = pred;
+                            PREDICT_AC
+                        }
+                        else
+                        {
+                            predptr = DCAC;
+                        }
+                    }
+                    else
+                    {
+                        predptr = pred;
+                        pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+                    }
+                }
+                else
+                {
+                    if (comp == 2 || comp == 3)
+                    {
+                        QPtmp = QPMB[mbnum+ y_offset];
+                        DCAC = DCAC_row[x_pos][b_xtab];
+                        if (QPtmp != QP)
+                        {
+                            predptr = pred;
+                            PREDICT_AC
+                        }
+                        else
+                        {
+                            predptr = DCAC;
+                        }
+                    }
+                    else
+                    {
+                        predptr = pred;
+                        pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+                    }
+                }
+            }
+            else if (x_pos == 0)    /* left edge */
+            {
+                if (direction[comp] == 0)
+                {
+                    if (comp == 1 || comp == 3)
+                    {
+                        QPtmp = QPMB[mbnum+x_offset];
+                        DCAC = DCAC_col[0][b_ytab];
+                        if (QPtmp != QP)
+                        {
+                            predptr = pred;
+                            PREDICT_AC
+                        }
+                        else
+                        {
+                            predptr = DCAC;
+                        }
+                    }
+                    else
+                    {
+                        predptr = pred;
+                        pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+                    }
+                }
+                else
+                {
+
+                    if ((Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))
+                            || comp == 2 || comp == 3)
+                    {
+                        QPtmp = QPMB[mbnum+y_offset];
+                        DCAC = DCAC_row[x_pos][b_xtab];
+                        if (QPtmp != QP)
+                        {
+                            predptr = pred;
+                            PREDICT_AC
+                        }
+                        else
+                        {
+                            predptr = DCAC;
+                        }
+                    }
+                    else
+                    {
+                        predptr = pred;
+                        pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+                    }
+                }
+            }
+            else if (y_pos == 0)  /* top row */
+            {
+                if (direction[comp] == 0)
+                {
+                    if ((Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))
+                            || comp == 1 || comp == 3)
+                    {
+                        QPtmp = QPMB[mbnum+x_offset];
+                        DCAC = DCAC_col[0][b_ytab];
+                        if (QPtmp != QP)
+                        {
+                            predptr = pred;
+                            PREDICT_AC
+                        }
+                        else
+                        {
+                            predptr = DCAC;
+                        }
+                    }
+                    else
+                    {
+                        predptr = pred;
+                        pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+                    }
+                }
+                else
+                {
+                    if (comp == 2 || comp == 3)
+                    {
+                        QPtmp = QPMB[mbnum+y_offset];
+                        DCAC = DCAC_row[x_pos][b_xtab];
+                        if (QPtmp != QP)
+                        {
+                            predptr = pred;
+                            PREDICT_AC
+                        }
+                        else
+                        {
+                            predptr = DCAC;
+                        }
+                    }
+                    else
+                    {
+                        predptr = pred;
+                        pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+                    }
+                }
+            }
+            else
+            {
+                if (direction[comp] == 0)
+                {
+                    if ((Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))
+                            || comp == 1 || comp == 3)
+                    {
+                        QPtmp = QPMB[mbnum+x_offset];
+                        DCAC = DCAC_col[0][b_ytab];
+                        if (QPtmp != QP)
+                        {
+                            predptr = pred;
+                            PREDICT_AC
+                        }
+                        else
+                        {
+                            predptr = DCAC;
+                        }
+                    }
+                    else
+                    {
+                        predptr = pred;
+                        pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+                    }
+                }
+                else
+                {
+                    if ((Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))
+                            || comp  == 2 || comp == 3)
+                    {
+                        QPtmp = QPMB[mbnum+y_offset];
+                        DCAC = DCAC_row[x_pos][b_xtab];
+                        if (QPtmp != QP)
+                        {
+                            predptr = pred;
+                            PREDICT_AC
+                        }
+                        else
+                        {
+                            predptr = DCAC;
+                        }
+                    }
+                    else
+                    {
+                        predptr = pred;
+                        pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+                    }
+                }
+            }
+
+            /************************************/
+            /* Decide and Perform AC prediction */
+            /************************************/
+            newCBP[comp] = 0;
+
+            if (direction[comp] == 0)   /* Horizontal, left COLUMN of block A */
+            {
+                DCAC = pcoeff + comp * 7; /* re-use DCAC as local var */
+                qcoeff += 8;
+                for (m = 0; m < 7; m++)
+                {
+                    QPtmp = qcoeff[m<<3];
+                    if (QPtmp > 0)  S1 += QPtmp;
+                    else        S1 -= QPtmp;
+                    QPtmp -= predptr[m];
+                    DCAC[m] = QPtmp; /* save prediction residue to pcoeff*/
+                    if (QPtmp)  newCBP[comp] = 1;
+                    diff = PV_ABS(QPtmp);
+                    S2 += diff;
+                }
+            }
+            else            /* Vertical, top ROW of block C */
+            {
+                qcoeff++;
+                DCAC = pcoeff + comp * 7; /* re-use DCAC as local var */
+                for (m = 0; m < 7; m++)
+                {
+                    QPtmp = qcoeff[m];
+                    if (QPtmp > 0)  S1 += QPtmp;
+                    else        S1 -= QPtmp;
+                    QPtmp -= predptr[m];
+                    DCAC[m] = QPtmp; /* save prediction residue to pcoeff*/
+                    if (QPtmp)  newCBP[comp] = 1;
+                    diff = PV_ABS(QPtmp);
+                    S2 += diff;
+                }
+            }
+
+            /****************************/
+            /*  Store DCAC coefficients */
+            /****************************/
+            /* Store coeff values for Intra MB */
+            qcoeff = MB->block[comp];
+            DCAC = DCAC_row[x_pos][b_xtab];
+            DCAC[0] = qcoeff[1];
+            DCAC[1] = qcoeff[2];
+            DCAC[2] = qcoeff[3];
+            DCAC[3] = qcoeff[4];
+            DCAC[4] = qcoeff[5];
+            DCAC[5] = qcoeff[6];
+            DCAC[6] = qcoeff[7];
+
+            DCAC = DCAC_col[0][b_ytab];
+            DCAC[0] = qcoeff[8];
+            DCAC[1] = qcoeff[16];
+            DCAC[2] = qcoeff[24];
+            DCAC[3] = qcoeff[32];
+            DCAC[4] = qcoeff[40];
+            DCAC[5] = qcoeff[48];
+            DCAC[6] = qcoeff[56];
+
+
+        } /* bACPredEnable */
+
+    } /* END COMP FOR LOOP */
+
+    //if (diff > 2047)
+    //    break;
+    S += (S1 - S2);
+
+
+    if (S >= 0 && bACPredEnable == TRUE)
+    {
+        ACpred_flag[mbnum] = 1;
+        DCAC = pcoeff; /* prediction residue */
+        qcoeff = MB->block[0];
+
+        for (comp = 0; comp < 6; comp++)
+        {
+            if (direction[comp] == 0)
+            {
+                qcoeff[8] = DCAC[0];
+                qcoeff[16] = DCAC[1];
+                qcoeff[24] = DCAC[2];
+                qcoeff[32] = DCAC[3];
+                qcoeff[40] = DCAC[4];
+                qcoeff[48] = DCAC[5];
+                qcoeff[56] = DCAC[6];
+
+            }
+            else
+            {
+                qcoeff[1] = DCAC[0];
+                qcoeff[2] = DCAC[1];
+                qcoeff[3] = DCAC[2];
+                qcoeff[4] = DCAC[3];
+                qcoeff[5] = DCAC[4];
+                qcoeff[6] = DCAC[5];
+                qcoeff[7] = DCAC[6];
+            }
+            if (newCBP[comp]) /* 5/28/01, update CBP */
+                video->headerInfo.CBP[mbnum] |= mask1[comp];
+            DCAC += 7;
+            qcoeff += 64;
+        }
+    }
+    else  /* Only DC Prediction */
+    {
+        ACpred_flag[mbnum] = 0;
+    }
+
+    *intraDC_decision = IntraDCSwitch_Decision(Mode, video->currVop->intraDCVlcThr, intraDCVlcQP);
+    if (*intraDC_decision) /* code DC with AC , 5/28/01*/
+    {
+        qcoeff = MB->block[0];
+        for (comp = 0; comp < 6; comp++)
+        {
+            if (*qcoeff)
+                video->headerInfo.CBP[mbnum] |= mask1[comp];
+            qcoeff += 64;
+        }
+    }
+    return;
+}
+#endif /* H263_ONLY */
+
+
+
+Void find_pmvs(VideoEncData *video, Int block, Int *mvx, Int *mvy)
+{
+    Vol *currVol = video->vol[video->currLayer];
+//  UChar *Mode = video->headerInfo.Mode; /* modes for MBs */
+    UChar *slice_nb = video->sliceNo;
+    Int nMBPerRow = currVol->nMBPerRow;
+    Int mbnum = video->mbnum;
+
+    Int   p1x, p2x, p3x;
+    Int   p1y, p2y, p3y;
+    Int   xin1, xin2, xin3;
+    Int   yin1, yin2, yin3;
+    Int   vec1, vec2, vec3;
+    Int   rule1, rule2, rule3;
+    MOT   **motdata = video->mot;
+    Int   x = mbnum % nMBPerRow;
+    Int   y = mbnum / nMBPerRow;
+
+    /*
+        In a previous version, a MB vector (block = 0) was predicted the same way
+        as block 1, which is the most likely interpretation of the VM.
+
+        Therefore, if we have advanced pred. mode, and if all MBs around have
+        only one 16x16 vector each, we chose the appropiate block as if these
+        MBs have 4 vectors.
+
+        This different prediction affects only 16x16 vectors of MBs with
+        transparent blocks.
+
+        In the current version, we choose for the 16x16 mode the first
+        non-transparent block in the surrounding MBs
+    */
+
+    switch (block)
+    {
+        case 0:
+            vec1 = 2 ;
+            yin1 = y  ;
+            xin1 = x - 1;
+            vec2 = 3 ;
+            yin2 = y - 1;
+            xin2 = x;
+            vec3 = 3 ;
+            yin3 = y - 1;
+            xin3 = x + 1;
+            break;
+
+        case 1:
+            vec1 = 2 ;
+            yin1 = y  ;
+            xin1 = x - 1;
+            vec2 = 3 ;
+            yin2 = y - 1;
+            xin2 = x;
+            vec3 = 3 ;
+            yin3 = y - 1;
+            xin3 = x + 1;
+            break;
+
+        case 2:
+            vec1 = 1 ;
+            yin1 = y  ;
+            xin1 = x;
+            vec2 = 4 ;
+            yin2 = y - 1;
+            xin2 = x;
+            vec3 = 3 ;
+            yin3 = y - 1;
+            xin3 = x + 1;
+            break;
+
+        case 3:
+            vec1 = 4 ;
+            yin1 = y  ;
+            xin1 = x - 1;
+            vec2 = 1 ;
+            yin2 = y  ;
+            xin2 = x;
+            vec3 = 2 ;
+            yin3 = y  ;
+            xin3 = x;
+            break;
+
+        default: /* case 4 */
+            vec1 = 3 ;
+            yin1 = y  ;
+            xin1 = x;
+            vec2 = 1 ;
+            yin2 = y  ;
+            xin2 = x;
+            vec3 = 2 ;
+            yin3 = y  ;
+            xin3 = x;
+            break;
+    }
+
+    if (block == 0)
+    {
+        /* according to the motion encoding, we must choose a first non-transparent
+        block in the surrounding MBs (16-mode)
+            */
+
+        if (x > 0 && slice_nb[mbnum] == slice_nb[mbnum-1])
+            rule1 = 0;
+        else
+            rule1 = 1;
+
+        if (y > 0 && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
+            rule2 = 0;
+        else
+            rule2 = 1;
+
+        if ((x != nMBPerRow - 1) && (y > 0) && slice_nb[mbnum] == slice_nb[mbnum+1-nMBPerRow])
+            rule3 = 0;
+        else
+            rule3 = 1;
+    }
+    else
+    {
+        /* check borders for single blocks (advanced mode) */
+        /* rule 1 */
+        if (((block == 1 || block == 3) &&
+                (x == 0 || slice_nb[mbnum] != slice_nb[mbnum-1])))
+            rule1 = 1;
+        else
+            rule1 = 0;
+
+        /* rule 2 */
+        if (((block == 1 || block == 2) &&
+                (y == 0 || slice_nb[mbnum] != slice_nb[mbnum-nMBPerRow])))
+            rule2 = 1;
+        else
+            rule2 = 0;
+
+        /* rule 3 */
+        if (((block == 1 || block == 2) &&
+                (x == nMBPerRow - 1 || y == 0 || slice_nb[mbnum] != slice_nb[mbnum+1-nMBPerRow])))
+            rule3 = 1;
+        else
+            rule3 = 0;
+    }
+
+    if (rule1)
+    {
+        p1x = p1y = 0;
+    }
+    else
+    {
+
+        p1x = motdata[yin1*nMBPerRow+xin1][vec1].x;
+        p1y = motdata[yin1*nMBPerRow+xin1][vec1].y;
+        //p1x = motxdata[xin1*2+(vec1&0x1) + (yin1*2+(vec1>>1))*xB];
+        //p1y = motydata[xin1*2+(vec1&0x1) + (yin1*2+(vec1>>1))*xB];
+    }
+
+    if (rule2)
+    {
+        p2x = p2y = 0;
+    }
+    else
+    {
+        p2x = motdata[yin2*nMBPerRow+xin2][vec2].x;
+        p2y = motdata[yin2*nMBPerRow+xin2][vec2].y;
+        //p2x = motxdata[xin2*2+(vec2&0x1) + (yin2*2+(vec2>>1))*xB];
+        //p2y = motydata[xin2*2+(vec2&0x1) + (yin2*2+(vec2>>1))*xB];
+    }
+
+    if (rule3)
+    {
+        p3x = p3y = 0;
+    }
+    else
+    {
+        p3x = motdata[yin3*nMBPerRow+xin3][vec3].x;
+        p3y = motdata[yin3*nMBPerRow+xin3][vec3].y;
+        //p3x = motxdata[xin3*2+ (vec3&0x1) + (yin3*2+(vec3>>1))*xB];
+        //p3y = motydata[xin3*2+ (vec3&0x1) + (yin3*2+(vec3>>1))*xB];
+    }
+
+    if (rule1 && rule2 && rule3)
+    {
+        /* all MBs are outside the VOP */
+        *mvx = *mvy = 0;
+    }
+    else if (rule1 + rule2 + rule3 == 2)
+    {
+        /* two of three are zero */
+        *mvx = (p1x + p2x + p3x);
+        *mvy = (p1y + p2y + p3y);
+    }
+    else
+    {
+        *mvx = ((p1x + p2x + p3x - PV_MAX(p1x, PV_MAX(p2x, p3x)) - PV_MIN(p1x, PV_MIN(p2x, p3x))));
+        *mvy = ((p1y + p2y + p3y - PV_MAX(p1y, PV_MAX(p2y, p3y)) - PV_MIN(p1y, PV_MIN(p2y, p3y))));
+    }
+
+    return;
+}
+
+
+Void WriteMVcomponent(Int f_code, Int dmv, BitstreamEncVideo *bs)
+{
+    Int residual, vlc_code_mag, bits, entry;
+
+    ScaleMVD(f_code, dmv, &residual, &vlc_code_mag);
+
+    if (vlc_code_mag < 0)
+        entry = vlc_code_mag + 65;
+    else
+        entry = vlc_code_mag;
+
+    bits = PutMV(entry, bs);
+
+    if ((f_code != 1) && (vlc_code_mag != 0))
+    {
+        BitstreamPutBits(bs, f_code - 1, residual);
+        bits += f_code - 1;
+    }
+    return;
+}
+
+
+Void
+ScaleMVD(
+    Int  f_code,       /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048     */
+    Int  diff_vector,  /* <-- MV Difference commponent in 1/2 units           */
+    Int  *residual,    /* --> value to be FLC coded                           */
+    Int  *vlc_code_mag /* --> value to be VLC coded                           */
+)
+{
+    Int   range;
+    Int   scale_factor;
+    Int   r_size;
+    Int   low;
+    Int   high;
+    Int   aux;
+
+    r_size = f_code - 1;
+    scale_factor = 1 << r_size;
+    range = 32 * scale_factor;
+    low   = -range;
+    high  =  range - 1;
+
+    if (diff_vector < low)
+        diff_vector += 2 * range;
+    else if (diff_vector > high)
+        diff_vector -= 2 * range;
+
+    if (diff_vector == 0)
+    {
+        *vlc_code_mag = 0;
+        *residual = 0;
+    }
+    else if (scale_factor == 1)
+    {
+        *vlc_code_mag = diff_vector;
+        *residual = 0;
+    }
+    else
+    {
+        aux = PV_ABS(diff_vector) + scale_factor - 1;
+        *vlc_code_mag = aux >> r_size;
+
+        if (diff_vector < 0)
+            *vlc_code_mag = -*vlc_code_mag;
+        *residual = aux & (scale_factor - 1);
+    }
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h
new file mode 100644
index 0000000..3721b6b
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h
@@ -0,0 +1,42 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _VLC_ENCODE_H_
+#define _VLC_ENCODE_H_
+
+#include "mp4def.h"
+#include "mp4enc_api.h"
+
+Int PutCoeff_Inter(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutCoeff_Intra(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutCBPY(Int cbpy, Char intra, BitstreamEncVideo *bitstream);
+Int PutMCBPC_Inter(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
+Int PutMCBPC_Intra(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
+Int PutMV(Int mvint, BitstreamEncVideo *bitstream);
+Int PutDCsize_chrom(Int size, BitstreamEncVideo *bitstream);
+Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
+Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
+Int PutCoeff_Inter_RVLC(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutCoeff_Intra_RVLC(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutRunCoeff_Inter(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutRunCoeff_Intra(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutLevelCoeff_Inter(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutLevelCoeff_Intra(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+
+Void MB_CodeCoeff(VideoEncData *video, BitstreamEncVideo *bs);
+Void BlockCodeCoeff(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, UChar Mode, Int rvlc, Int shortVideoHeader);
+#endif /* _VLC_ENCODE_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h
new file mode 100644
index 0000000..a2f4934
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h
@@ -0,0 +1,316 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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 _VLC_ENCODE_INLINE_H_
+#define _VLC_ENCODE_INLINE_H_
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4)
+
+__inline  Int zero_run_search(UInt *bitmapzz, Short *dataBlock, RunLevelBlock *RLB, Int nc)
+{
+    Int idx, run, level, j;
+    UInt end, match;
+
+    idx = 0;
+    j   = 0;
+    run = 0;
+    match = 1 << 31;
+    if (nc > 32)
+        end = 1;
+    else
+        end = 1 << (32 - nc);
+
+    while (match >= end)
+    {
+        if ((match&bitmapzz[0]) == 0)
+        {
+            run++;
+            j++;
+            match >>= 1;
+        }
+        else
+        {
+            match >>= 1;
+            level = dataBlock[j];
+            dataBlock[j] = 0; /* reset output */
+            j++;
+            if (level < 0)
+            {
+                RLB->level[idx] = -level;
+                RLB->s[idx] = 1;
+                RLB->run[idx] = run;
+                run = 0;
+                idx++;
+            }
+            else
+            {
+                RLB->level[idx] = level;
+                RLB->s[idx] = 0;
+                RLB->run[idx] = run;
+                run = 0;
+                idx++;
+            }
+        }
+    }
+    nc -= 32;
+    if (nc > 0)
+    {
+        match = 1 << 31;
+        end = 1 << (32 - nc);
+        while (match >= end)
+        {
+            if ((match&bitmapzz[1]) == 0)
+            {
+                run++;
+                j++;
+                match >>= 1;
+            }
+            else
+            {
+                match >>= 1;
+                level = dataBlock[j];
+                dataBlock[j] = 0; /* reset output */
+                j++;
+                if (level < 0)
+                {
+                    RLB->level[idx] = -level;
+                    RLB->s[idx] = 1;
+                    RLB->run[idx] = run;
+                    run = 0;
+                    idx++;
+                }
+                else
+                {
+                    RLB->level[idx] = level;
+                    RLB->s[idx] = 0;
+                    RLB->run[idx] = run;
+                    run = 0;
+                    idx++;
+                }
+            }
+        }
+    }
+
+    return idx;
+}
+
+#elif defined(__CC_ARM)  /* only work with arm v5 */
+
+__inline  Int zero_run_search(UInt *bitmapzz, Short *dataBlock, RunLevelBlock *RLB, Int nc)
+{
+    OSCL_UNUSED_ARG(nc);
+    Int idx, run, level, j;
+    UInt end, match;
+    Int  zzorder;
+
+    idx = 0;
+    run = 0;
+    j   = -1;
+    __asm
+    {
+        ldr match, [bitmapzz]
+        clz run, match
+    }
+
+    zzorder = 0;
+
+    while (run < 32)
+    {
+        __asm
+        {
+            mov end, #0x80000000
+            mov end, end, lsr run   /* mask*/
+            bic match, match, end       /* remove it from bitmap */
+            mov run, run, lsl #1  /* 05/09/02 */
+            ldrsh level, [dataBlock, run] /*  load data */
+            strh zzorder, [dataBlock, run] /* reset output */
+            add j, j, #1
+            rsb run, j, run, lsr #1 /* delta run */
+            add j, j, run           /* current position */
+        }
+        if (level < 0)
+        {
+            RLB->level[idx] = -level;
+            RLB->s[idx] = 1;
+            RLB->run[idx] = run;
+            run = 0;
+            idx++;
+        }
+        else
+        {
+            RLB->level[idx] = level;
+            RLB->s[idx] = 0;
+            RLB->run[idx] = run;
+            run = 0;
+            idx++;
+        }
+        __asm
+        {
+            clz run, match
+        }
+    }
+    __asm
+    {
+        ldr match, [bitmapzz, #4]
+        clz run, match
+    }
+
+    while (run < 32)
+    {
+        __asm
+        {
+            mov end, #0x80000000
+            mov end, end, lsr run   /* mask*/
+            bic match, match, end       /* remove it from bitmap */
+            add run, run, #32       /* current position */
+            mov run, run, lsl #1    /* 09/02/05 */
+            ldrsh level, [dataBlock, run] /*  load data */
+            strh  zzorder, [dataBlock, run] /* reset output */
+            add j, j, #1
+            rsb run, j, run, lsr #1     /* delta run */
+            add j, j, run           /* current position */
+        }
+        if (level < 0)
+        {
+            RLB->level[idx] = -level;
+            RLB->s[idx] = 1;
+            RLB->run[idx] = run;
+            run = 0;
+            idx++;
+        }
+        else
+        {
+            RLB->level[idx] = level;
+            RLB->s[idx] = 0;
+            RLB->run[idx] = run;
+            run = 0;
+            idx++;
+        }
+        __asm
+        {
+            clz run, match
+        }
+    }
+
+    return idx;
+}
+
+#elif ( defined(PV_ARM_GCC_V4) || defined(PV_ARM_GCC_V5) ) /* ARM GNU COMPILER  */
+
+__inline Int m4v_enc_clz(UInt temp)
+{
+    register Int rb;
+    register UInt ra = (UInt)temp;
+
+    asm volatile("clz   %0, %1"
+             : "=&r"(rb)
+                         : "r"(ra)
+                        );
+
+    return (rb);
+}
+
+__inline  Int zero_run_search(UInt *bitmapzz, Short *dataBlock, RunLevelBlock *RLB, Int nc)
+{
+    OSCL_UNUSED_ARG(nc);
+    Int idx, run, level = 0, j;
+    UInt end = 0, match;
+    Int  zzorder;
+
+    idx = 0;
+    run = 0;
+    j   = -1;
+    match = *bitmapzz;
+    run = m4v_enc_clz(match);
+
+    zzorder = 0;
+
+    while (run < 32)
+    {
+        asm volatile("mov   %0, #0x80000000\n\t"
+                     "mov   %0, %0, lsr %1\n\t"
+                     "bic   %2, %2, %0\n\t"
+                     "mov   %1, %1, lsl #1\n\t"
+                     "ldrsh %3, [%6, %1]\n\t"
+                     "strh  %5, [%6, %1]\n\t"
+                     "add   %4, %4, #1\n\t"
+                     "rsb   %1, %4, %1, lsr #1\n\t"
+                     "add   %4, %4, %1"
+             : "+r"(end), "+r"(run), "+r"(match), "=r"(level), "+r"(j)
+                             : "r"(zzorder), "r"(dataBlock));
+        if (level < 0)
+        {
+            RLB->level[idx] = -level;
+            RLB->s[idx] = 1;
+            RLB->run[idx] = run;
+            run = 0;
+            idx++;
+        }
+        else
+        {
+            RLB->level[idx] = level;
+            RLB->s[idx] = 0;
+            RLB->run[idx] = run;
+            run = 0;
+            idx++;
+        }
+        run = m4v_enc_clz(match);
+    }
+    match = bitmapzz[1];
+    run = m4v_enc_clz(match);
+
+    while (run < 32)
+    {
+        asm volatile("mov   %0, #0x80000000\n\t"
+                     "mov   %0, %0, lsr %1\n\t"
+                     "bic   %2, %2, %0\n\t"
+                     "add   %1, %1, #32\n\t"
+                     "mov   %1, %1, lsl #1\n\t"
+                     "ldrsh %3, [%6, %1]\n\t"
+                     "strh  %5, [%6, %1]\n\t"
+                     "add   %4, %4, #1\n\t"
+                     "rsb   %1, %4, %1, lsr #1\n\t"
+                     "add   %4, %4, %1"
+             : "+r"(end), "+r"(run), "+r"(match), "+r"(level), "+r"(j)
+                             : "r"(zzorder), "r"(dataBlock));
+        if (level < 0)
+        {
+            RLB->level[idx] = -level;
+            RLB->s[idx] = 1;
+            RLB->run[idx] = run;
+            run = 0;
+            idx++;
+        }
+        else
+        {
+            RLB->level[idx] = level;
+            RLB->s[idx] = 0;
+            RLB->run[idx] = run;
+            run = 0;
+            idx++;
+        }
+        run = m4v_enc_clz(match);
+    }
+
+    return idx;
+}
+
+#endif
+
+#endif // _VLC_ENCODE_INLINE_H_
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp
new file mode 100644
index 0000000..47076c3
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp
@@ -0,0 +1,581 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * 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.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "mp4enc_lib.h"
+#include "bitstream_io.h"
+#include "m4venc_oscl.h"
+
+PV_STATUS EncodeShortHeader(BitstreamEncVideo *stream, Vop *currVop);
+PV_STATUS EncodeVOPHeader(BitstreamEncVideo *stream, Vol *currVol, Vop *currVop);
+PV_STATUS EncodeGOVHeader(BitstreamEncVideo *stream, UInt seconds);
+
+PV_STATUS EncodeVop_BXRC(VideoEncData *video);
+PV_STATUS EncodeVop_NoME(VideoEncData *video);
+
+/* ======================================================================== */
+/*  Function : DecodeVop()                                                  */
+/*  Date     : 08/23/2000                                                   */
+/*  Purpose  : Encode VOP Header                                            */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+PV_STATUS EncodeVop(VideoEncData *video)
+{
+
+    PV_STATUS status;
+    Int currLayer = video->currLayer;
+    Vol *currVol = video->vol[currLayer];
+    Vop *currVop = video->currVop;
+//  BitstreamEncVideo *stream=video->bitstream1;
+    UChar *Mode = video->headerInfo.Mode;
+    rateControl **rc = video->rc;
+//  UInt time=0;
+
+    /*******************/
+    /* Initialize mode */
+    /*******************/
+
+    switch (currVop->predictionType)
+    {
+        case I_VOP:
+            M4VENC_MEMSET(Mode, MODE_INTRA, sizeof(UChar)*currVol->nTotalMB);
+            break;
+        case P_VOP:
+            M4VENC_MEMSET(Mode, MODE_INTER, sizeof(UChar)*currVol->nTotalMB);
+            break;
+        case B_VOP:
+            /*M4VENC_MEMSET(Mode, MODE_INTER_B,sizeof(UChar)*nTotalMB);*/
+            return PV_FAIL;
+        default:
+            return PV_FAIL;
+    }
+
+    /*********************/
+    /* Motion Estimation */
+    /* compute MVs, scene change detection, edge padding, */
+    /* intra refresh, compute block activity */
+    /*********************/
+    MotionEstimation(video);    /* do ME for the whole frame */
+
+    /***************************/
+    /* rate Control (assign QP) */
+    /* 4/11/01, clean-up, and put into a separate function */
+    /***************************/
+    status = RC_VopQPSetting(video, rc);
+    if (status == PV_FAIL)
+        return PV_FAIL;
+
+    /**********************/
+    /*     Encode VOP     */
+    /**********************/
+    if (video->slice_coding) /* end here */
+    {
+        /* initialize state variable for slice-based APIs */
+        video->totalSAD = 0;
+        video->mbnum = 0;
+        video->sliceNo[0] = 0;
+        video->numIntra = 0;
+        video->offset = 0;
+        video->end_of_buf = 0;
+        video->hp_guess = -1;
+        return status;
+    }
+
+    status = EncodeVop_NoME(video);
+
+    /******************************/
+    /* rate control (update stat) */
+    /* 6/2/01 separate function */
+    /******************************/
+
+    RC_VopUpdateStat(video, rc[currLayer]);
+
+    return status;
+}
+
+/* ======================================================================== */
+/*  Function : EncodeVop_NoME()                                             */
+/*  Date     : 08/28/2001                                                   */
+/*  History  :                                                              */
+/*  Purpose  : EncodeVop without motion est.                                */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+PV_STATUS EncodeVop_NoME(VideoEncData *video)
+{
+    Vop *currVop = video->currVop;
+    Vol *currVol = video->vol[video->currLayer];
+    BitstreamEncVideo *stream = video->bitstream1;
+    Int time = 0;   /* follows EncodeVop value */
+    PV_STATUS status = PV_SUCCESS;
+
+    if (currVol->shortVideoHeader) /* Short Video Header = 1 */
+    {
+
+        status = EncodeShortHeader(stream, currVop); /* Encode Short Header */
+
+        video->header_bits = BitstreamGetPos(stream); /* Header Bits */
+
+        status = EncodeFrameCombinedMode(video);
+
+    }
+#ifndef H263_ONLY
+    else    /* Short Video Header = 0 */
+    {
+
+        if (currVol->GOVStart && currVop->predictionType == I_VOP)
+            status = EncodeGOVHeader(stream, time); /* Encode GOV Header */
+
+        status = EncodeVOPHeader(stream, currVol, currVop);  /* Encode VOP Header */
+
+        video->header_bits = BitstreamGetPos(stream); /* Header Bits */
+
+        if (currVop->vopCoded)
+        {
+            if (!currVol->scalability)
+            {
+                if (currVol->dataPartitioning)
+                {
+                    status = EncodeFrameDataPartMode(video); /* Encode Data Partitioning Mode VOP */
+                }
+                else
+                {
+                    status = EncodeFrameCombinedMode(video); /* Encode Combined Mode VOP */
+                }
+            }
+            else
+                status = EncodeFrameCombinedMode(video); /* Encode Combined Mode VOP */
+        }
+        else  /* Vop Not coded */
+        {
+
+            return status;
+        }
+    }
+#endif /* H263_ONLY */
+    return status;
+
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/*  Function : EncodeSlice()                                                */
+/*  Date     : 04/19/2002                                                   */
+/*  History  :                                                              */
+/*  Purpose  : Encode one slice.                                            */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/*                                                                          */
+/* ======================================================================== */
+
+PV_STATUS EncodeSlice(VideoEncData *video)
+{
+    Vop *currVop = video->currVop;
+    Int currLayer = video->currLayer;
+    Vol *currVol = video->vol[currLayer];
+    BitstreamEncVideo *stream = video->bitstream1; /* different from frame-based */
+    Int time = 0;   /* follows EncodeVop value */
+    PV_STATUS status = PV_SUCCESS;
+    rateControl **rc = video->rc;
+
+    if (currVol->shortVideoHeader) /* Short Video Header = 1 */
+    {
+
+        if (video->mbnum == 0)
+        {
+            status = EncodeShortHeader(stream, currVop); /* Encode Short Header */
+
+            video->header_bits = BitstreamGetPos(stream); /* Header Bits */
+        }
+
+        status = EncodeSliceCombinedMode(video);
+
+    }
+#ifndef H263_ONLY
+    else    /* Short Video Header = 0 */
+    {
+
+        if (video->mbnum == 0)
+        {
+            if (currVol->GOVStart)
+                status = EncodeGOVHeader(stream, time); /* Encode GOV Header */
+
+            status = EncodeVOPHeader(stream, currVol, currVop);  /* Encode VOP Header */
+
+            video->header_bits = BitstreamGetPos(stream); /* Header Bits */
+        }
+
+        if (currVop->vopCoded)
+        {
+            if (!currVol->scalability)
+            {
+                if (currVol->dataPartitioning)
+                {
+                    status = EncodeSliceDataPartMode(video); /* Encode Data Partitioning Mode VOP */
+                }
+                else
+                {
+                    status = EncodeSliceCombinedMode(video); /* Encode Combined Mode VOP */
+                }
+            }
+            else
+                status = EncodeSliceCombinedMode(video); /* Encode Combined Mode VOP */
+        }
+        else  /* Vop Not coded */
+        {
+
+            return status;
+        }
+    }
+#endif /* H263_ONLY */
+    if (video->mbnum >= currVol->nTotalMB && status != PV_END_OF_BUF) /* end of Vop */
+    {
+        /******************************/
+        /* rate control (update stat) */
+        /* 6/2/01 separate function */
+        /******************************/
+
+        status = RC_VopUpdateStat(video, rc[currLayer]);
+    }
+
+    return status;
+
+}
+#endif /* NO_SLICE_ENCODE */
+
+#ifndef H263_ONLY
+/* ======================================================================== */
+/*  Function : EncodeGOVHeader()                                            */
+/*  Date     : 08/23/2000                                                   */
+/*  Purpose  : Encode GOV Header                                            */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+PV_STATUS EncodeGOVHeader(BitstreamEncVideo *stream, UInt seconds)
+{
+    PV_STATUS status;
+//  int temp;
+    UInt tmpvar;
+
+    /********************************/
+    /* Group_of_VideoObjectPlane()  */
+    /********************************/
+
+    status = BitstreamPutGT16Bits(stream, 32, GROUP_START_CODE);
+    /* time_code */
+    tmpvar = seconds / 3600;
+    status = BitstreamPutBits(stream, 5, tmpvar); /* Hours*/
+
+    tmpvar = (seconds - tmpvar * 3600) / 60;
+    status = BitstreamPutBits(stream, 6, tmpvar); /* Minutes*/
+
+    status = BitstreamPut1Bits(stream, 1); /* Marker*/
+
+    tmpvar = seconds % 60;
+    status = BitstreamPutBits(stream, 6, tmpvar); /* Seconds*/
+
+    status = BitstreamPut1Bits(stream, 1); /* closed_gov */
+    status = BitstreamPut1Bits(stream, 0); /* broken_link */
+    /*temp =*/
+    BitstreamMpeg4ByteAlignStuffing(stream); /* Byte align GOV Header */
+
+    return status;
+}
+
+#ifdef ALLOW_VOP_NOT_CODED
+
+PV_STATUS EncodeVopNotCoded(VideoEncData *video, UChar *bstream, Int *size, ULong modTime)
+{
+    PV_STATUS status;
+    Vol *currVol = video->vol[0];
+    Vop *currVop = video->currVop;
+    BitstreamEncVideo *stream = currVol->stream;
+    UInt frameTick;
+    Int timeInc;
+
+    stream->bitstreamBuffer = bstream;
+    stream->bufferSize = *size;
+    BitstreamEncReset(stream);
+
+    status = BitstreamPutGT16Bits(stream, 32, VOP_START_CODE); /*Start Code for VOP*/
+    status = BitstreamPutBits(stream, 2, P_VOP);/* VOP Coding Type*/
+
+    frameTick = (Int)(((double)(modTime - video->modTimeRef) * currVol->timeIncrementResolution + 500) / 1000);
+    timeInc = frameTick - video->refTick[0];
+    while (timeInc >= currVol->timeIncrementResolution)
+    {
+        timeInc -= currVol->timeIncrementResolution;
+        status = BitstreamPut1Bits(stream, 1);
+        /* do not update refTick and modTimeRef yet, do it after encoding!! */
+    }
+    status = BitstreamPut1Bits(stream, 0);
+    status = BitstreamPut1Bits(stream, 1); /* marker bit */
+    status = BitstreamPutBits(stream, currVol->nbitsTimeIncRes, timeInc); /* vop_time_increment */
+    status = BitstreamPut1Bits(stream, 1); /* marker bit */
+    status = BitstreamPut1Bits(stream, 0); /* vop_coded bit */
+    BitstreamMpeg4ByteAlignStuffing(stream);
+
+    return status;
+}
+#endif
+
+/* ======================================================================== */
+/*  Function : EncodeVOPHeader()                                            */
+/*  Date     : 08/23/2000                                                   */
+/*  Purpose  : Encode VOP Header                                            */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+PV_STATUS EncodeVOPHeader(BitstreamEncVideo *stream, Vol *currVol, Vop *currVop)
+{
+    PV_STATUS status;
+    //int temp;
+
+    int MTB = currVol->moduloTimeBase;
+    /************************/
+    /* VideoObjectPlane()   */
+    /************************/
+
+    status = BitstreamPutGT16Bits(stream, 32, VOP_START_CODE); /*Start Code for VOP*/
+    status = BitstreamPutBits(stream, 2, currVop->predictionType);/* VOP Coding Type*/
+
+    currVol->prevModuloTimeBase = currVol->moduloTimeBase;
+
+    while (MTB)
+    {
+        status = BitstreamPut1Bits(stream, 1);
+        MTB--;
+    }
+    status = BitstreamPut1Bits(stream, 0);
+
+    status = BitstreamPut1Bits(stream, 1); /* marker bit */
+    status = BitstreamPutBits(stream, currVol->nbitsTimeIncRes, currVop->timeInc); /* vop_time_increment */
+    status = BitstreamPut1Bits(stream, 1); /* marker bit */
+    status = BitstreamPut1Bits(stream, currVop->vopCoded); /* vop_coded bit */
+    if (currVop->vopCoded == 0)
+    {
+        /*temp =*/
+        BitstreamMpeg4ByteAlignStuffing(stream); /* Byte align VOP Header */
+        return status;
+    }
+    if (currVop->predictionType == P_VOP)
+        status = BitstreamPut1Bits(stream, currVop->roundingType); /* vop_rounding_type */
+
+    status = BitstreamPutBits(stream, 3, currVop->intraDCVlcThr); /* intra_dc_vlc_thr */
+    status = BitstreamPutBits(stream, 5, currVop->quantizer);   /* vop_quant */
+
+    if (currVop->predictionType != I_VOP)
+        status = BitstreamPutBits(stream, 3, currVop->fcodeForward); /* vop_fcode_forward */
+    if (currVop->predictionType == B_VOP)
+        status = BitstreamPutBits(stream, 3, currVop->fcodeBackward);/* vop_fcode_backward */
+
+    if (currVol->scalability)
+        /* enhancement_type = 0 */
+        status = BitstreamPutBits(stream, 2, currVop->refSelectCode); /* ref_select_code */
+
+    return status;
+}
+#endif /* H263_ONLY */
+/* ======================================================================== */
+/*  Function : EncodeShortHeader()                                          */
+/*  Date     : 08/23/2000                                                   */
+/*  Purpose  : Encode VOP Header                                            */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified :                                                              */
+/* ======================================================================== */
+
+PV_STATUS EncodeShortHeader(BitstreamEncVideo *stream, Vop *currVop)
+{
+
+    PV_STATUS status;
+
+    status = BitstreamPutGT16Bits(stream, 22, SHORT_VIDEO_START_MARKER); /* Short_video_start_marker */
+    status = BitstreamPutBits(stream, 8, currVop->temporalRef); /* temporal_reference */
+    status = BitstreamPut1Bits(stream, 1); /* marker bit */
+    status = BitstreamPut1Bits(stream, 0); /* zero bit */
+    status = BitstreamPut1Bits(stream, 0); /* split_screen_indicator=0*/
+    status = BitstreamPut1Bits(stream, 0); /* document_camera_indicator=0*/
+    status = BitstreamPut1Bits(stream, 0); /* full_picture_freeze_release=0*/
+
+    switch (currVop->width)
+    {
+        case 128:
+            if (currVop->height == 96)
+                status = BitstreamPutBits(stream, 3, 1); /* source_format = 1 */
+            else
+            {
+                status = PV_FAIL;
+                return status;
+            }
+            break;
+
+        case 176:
+            if (currVop->height == 144)
+                status = BitstreamPutBits(stream, 3, 2); /* source_format = 2 */
+            else
+            {
+                status = PV_FAIL;
+                return status;
+            }
+            break;
+
+        case 352:
+            if (currVop->height == 288)
+                status = BitstreamPutBits(stream, 3, 3); /* source_format = 3 */
+            else
+            {
+                status = PV_FAIL;
+                return status;
+            }
+            break;
+
+        case 704:
+            if (currVop->height == 576)
+                status = BitstreamPutBits(stream, 3, 4); /* source_format = 4 */
+            else
+            {
+                status = PV_FAIL;
+                return status;
+            }
+            break;
+
+        case 1408:
+            if (currVop->height == 1152)
+                status = BitstreamPutBits(stream, 3, 5); /* source_format = 5 */
+            else
+            {
+                status = PV_FAIL;
+                return status;
+            }
+            break;
+
+        default:
+            status = PV_FAIL;
+            return status;
+    }
+
+
+    status = BitstreamPut1Bits(stream, currVop->predictionType); /* picture_coding type */
+    status = BitstreamPutBits(stream, 4, 0); /* four_reserved_zero_bits */
+    status = BitstreamPutBits(stream, 5, currVop->quantizer); /* vop_quant*/
+    status = BitstreamPut1Bits(stream, 0); /* zero_bit*/
+    status = BitstreamPut1Bits(stream, 0); /* pei=0 */
+
+    return status;
+}
+
+#ifndef H263_ONLY
+/* ======================================================================== */
+/*  Function : EncodeVideoPacketHeader()                                    */
+/*  Date     : 09/05/2000                                                   */
+/*  History  :                                                              */
+/*  Purpose  : Encode a frame of MPEG4 bitstream in Combined mode.          */
+/*  In/out   :                                                              */
+/*  Return   :                                                              */
+/*  Modified : 04/25/2002                               */
+/*             Add bitstream structure as input argument                    */
+/*                                                                          */
+/* ======================================================================== */
+PV_STATUS EncodeVideoPacketHeader(VideoEncData *video, int MB_number,
+                                  int quant_scale, Int insert)
+{
+//  PV_STATUS status=PV_SUCCESS;
+    int fcode;
+    Vop *currVop = video->currVop;
+    Vol *currVol = video->vol[video->currLayer];
+    BitstreamEncVideo *bs, tmp;
+    UChar buffer[30];
+
+    if (insert) /* insert packet header to the beginning of bs1 */
+    {
+        tmp.bitstreamBuffer = buffer; /* use temporary buffer */
+        tmp.bufferSize = 30;
+        BitstreamEncReset(&tmp);
+        bs = &tmp;
+    }
+    else
+        bs = video->bitstream1;
+
+
+    if (currVop->predictionType == I_VOP)
+        BitstreamPutGT16Bits(bs, 17, 1);    /* resync_marker I_VOP */
+    else if (currVop->predictionType == P_VOP)
+    {
+        fcode = currVop->fcodeForward;
+        BitstreamPutGT16Bits(bs, 16 + fcode, 1);    /* resync_marker P_VOP */
+
+    }
+    else
+    {
+        fcode = currVop->fcodeForward;
+        if (currVop->fcodeBackward > fcode)
+            fcode = currVop->fcodeBackward;
+        BitstreamPutGT16Bits(bs, 16 + fcode, 1);    /* resync_marker B_VOP */
+    }
+
+    BitstreamPutBits(bs, currVol->nBitsForMBID, MB_number); /* resync_marker */
+    BitstreamPutBits(bs, 5, quant_scale); /* quant_scale */
+    BitstreamPut1Bits(bs, 0); /* header_extension_code = 0 */
+
+    if (0) /* header_extension_code = 1 */
+    {
+        /* NEED modulo_time_base code here ... default 0x01  belo*/
+        /*status =*/
+        BitstreamPut1Bits(bs, 1);
+        /*status = */
+        BitstreamPut1Bits(bs, 0);
+
+        /*status = */
+        BitstreamPut1Bits(bs, 1); /* marker bit */
+        /*status = */
+        BitstreamPutBits(bs, currVol->nbitsTimeIncRes, currVop->timeInc); /* vop_time_increment */
+        /*status = */
+        BitstreamPut1Bits(bs, 1); /* marker bit */
+
+        /*status = */
+        BitstreamPutBits(bs, 2, currVop->predictionType);/* VOP Coding Type*/
+
+        /*status = */
+        BitstreamPutBits(bs, 3, currVop->intraDCVlcThr); /* intra_dc_vlc_thr */
+
+        if (currVop->predictionType != I_VOP)
+            /*status = */ BitstreamPutBits(bs, 3, currVop->fcodeForward);
+        if (currVop->predictionType == B_VOP)
+            /*status = */ BitstreamPutBits(bs, 3, currVop->fcodeBackward);
+    }
+#ifndef NO_SLICE_ENCODE
+    if (insert)
+        BitstreamPrependPacket(video->bitstream1, bs);
+#endif
+    return PV_SUCCESS;
+}
+
+#endif /* H263_ONLY */
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
index efcb476..c4a8280 100644
--- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
@@ -27,13 +27,35 @@
 
 MP3Decoder::MP3Decoder(const sp<MediaSource> &source)
     : mSource(source),
+      mNumChannels(0),
       mStarted(false),
       mBufferGroup(NULL),
       mConfig(new tPVMP3DecoderExternal),
       mDecoderBuf(NULL),
       mAnchorTimeUs(0),
-      mNumSamplesOutput(0),
+      mNumFramesOutput(0),
       mInputBuffer(NULL) {
+    init();
+}
+
+void MP3Decoder::init() {
+    sp<MetaData> srcFormat = mSource->getFormat();
+
+    int32_t sampleRate;
+    CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels));
+    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
+
+    mMeta = new MetaData;
+    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+    mMeta->setInt32(kKeyChannelCount, mNumChannels);
+    mMeta->setInt32(kKeySampleRate, sampleRate);
+
+    int64_t durationUs;
+    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+        mMeta->setInt64(kKeyDuration, durationUs);
+    }
+
+    mMeta->setCString(kKeyDecoderComponent, "MP3Decoder");
 }
 
 MP3Decoder::~MP3Decoder() {
@@ -62,7 +84,7 @@
     mSource->start();
 
     mAnchorTimeUs = 0;
-    mNumSamplesOutput = 0;
+    mNumFramesOutput = 0;
     mStarted = true;
 
     return OK;
@@ -90,26 +112,7 @@
 }
 
 sp<MetaData> MP3Decoder::getFormat() {
-    sp<MetaData> srcFormat = mSource->getFormat();
-
-    int32_t numChannels;
-    int32_t sampleRate;
-    CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
-    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
-    sp<MetaData> meta = new MetaData;
-    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-    meta->setInt32(kKeyChannelCount, numChannels);
-    meta->setInt32(kKeySampleRate, sampleRate);
-
-    int64_t durationUs;
-    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
-        meta->setInt64(kKeyDuration, durationUs);
-    }
-
-    meta->setCString(kKeyDecoderComponent, "MP3Decoder");
-
-    return meta;
+    return mMeta;
 }
 
 status_t MP3Decoder::read(
@@ -119,10 +122,11 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         CHECK(seekTimeUs >= 0);
 
-        mNumSamplesOutput = 0;
+        mNumFramesOutput = 0;
 
         if (mInputBuffer) {
             mInputBuffer->release();
@@ -142,7 +146,7 @@
         int64_t timeUs;
         if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
             mAnchorTimeUs = timeUs;
-            mNumSamplesOutput = 0;
+            mNumFramesOutput = 0;
         } else {
             // We must have a new timestamp after seeking.
             CHECK(seekTimeUs < 0);
@@ -179,7 +183,7 @@
 
         // This is recoverable, just ignore the current frame and
         // play silence instead.
-        memset(buffer->data(), 0, mConfig->outputFrameSize);
+        memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t));
         mConfig->inputBufferUsedLength = mInputBuffer->range_length();
     }
 
@@ -198,9 +202,9 @@
     buffer->meta_data()->setInt64(
             kKeyTime,
             mAnchorTimeUs
-                + (mNumSamplesOutput * 1000000) / mConfig->samplingRate);
+                + (mNumFramesOutput * 1000000) / mConfig->samplingRate);
 
-    mNumSamplesOutput += mConfig->outputFrameSize / sizeof(int16_t);
+    mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
 
     *out = buffer;
 
diff --git a/media/libstagefright/codecs/on2/Android.mk b/media/libstagefright/codecs/on2/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/on2/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
new file mode 100644
index 0000000..03dfb75
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+        VPXDecoder.cpp
+
+LOCAL_MODULE := libstagefright_vpxdec
+
+LOCAL_C_INCLUDES := \
+        $(TOP)/frameworks/base/media/libstagefright/include \
+        $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+        $(TOP)/external/libvpx \
+        $(TOP)/external/libvpx/vpx_codec \
+        $(TOP)/external/libvpx/vpx_ports
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
new file mode 100644
index 0000000..fbc97f4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2010 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 "VPXDecoder"
+#include <utils/Log.h>
+
+#include "VPXDecoder.h"
+
+#include <OMX_Component.h>
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include "vpx_codec/vpx_decoder.h"
+#include "vp8/vp8dx.h"
+
+namespace android {
+
+VPXDecoder::VPXDecoder(const sp<MediaSource> &source)
+    : mSource(source),
+      mStarted(false),
+      mBufferSize(0),
+      mCtx(NULL),
+      mBufferGroup(NULL),
+      mTargetTimeUs(-1) {
+    sp<MetaData> inputFormat = source->getFormat();
+    const char *mime;
+    CHECK(inputFormat->findCString(kKeyMIMEType, &mime));
+    CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_VPX));
+
+    CHECK(inputFormat->findInt32(kKeyWidth, &mWidth));
+    CHECK(inputFormat->findInt32(kKeyHeight, &mHeight));
+
+    mBufferSize = (mWidth * mHeight * 3) / 2;
+
+    mFormat = new MetaData;
+    mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+    mFormat->setInt32(kKeyWidth, mWidth);
+    mFormat->setInt32(kKeyHeight, mHeight);
+    mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+    mFormat->setCString(kKeyDecoderComponent, "VPXDecoder");
+
+    int64_t durationUs;
+    if (inputFormat->findInt64(kKeyDuration, &durationUs)) {
+        mFormat->setInt64(kKeyDuration, durationUs);
+    }
+}
+
+VPXDecoder::~VPXDecoder() {
+    if (mStarted) {
+        stop();
+    }
+}
+
+status_t VPXDecoder::start(MetaData *) {
+    if (mStarted) {
+        return UNKNOWN_ERROR;
+    }
+
+    status_t err = mSource->start();
+
+    if (err != OK) {
+        return err;
+    }
+
+    mCtx = new vpx_codec_ctx_t;
+    if (vpx_codec_dec_init(
+                (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, NULL, 0)) {
+        LOGE("on2 decoder failed to initialize.");
+
+        mSource->stop();
+
+        return UNKNOWN_ERROR;
+    }
+
+    mBufferGroup = new MediaBufferGroup;
+    mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+    mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+
+    mTargetTimeUs = -1;
+
+    mStarted = true;
+
+    return OK;
+}
+
+status_t VPXDecoder::stop() {
+    if (!mStarted) {
+        return UNKNOWN_ERROR;
+    }
+
+    delete mBufferGroup;
+    mBufferGroup = NULL;
+
+    vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
+    delete (vpx_codec_ctx_t *)mCtx;
+    mCtx = NULL;
+
+    mSource->stop();
+
+    mStarted = false;
+
+    return OK;
+}
+
+sp<MetaData> VPXDecoder::getFormat() {
+    return mFormat;
+}
+
+status_t VPXDecoder::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    *out = NULL;
+
+    bool seeking = false;
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode seekMode;
+    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+        seeking = true;
+    }
+
+    MediaBuffer *input;
+    status_t err = mSource->read(&input, options);
+
+    if (err != OK) {
+        return err;
+    }
+
+    LOGV("read %d bytes from source\n", input->range_length());
+
+    if (seeking) {
+        int64_t targetTimeUs;
+        if (input->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
+                && targetTimeUs >= 0) {
+            mTargetTimeUs = targetTimeUs;
+        } else {
+            mTargetTimeUs = -1;
+        }
+    }
+
+    if (vpx_codec_decode(
+                (vpx_codec_ctx_t *)mCtx,
+                (uint8_t *)input->data() + input->range_offset(),
+                input->range_length(),
+                NULL,
+                0)) {
+        LOGE("on2 decoder failed to decode frame.");
+        input->release();
+        input = NULL;
+
+        return UNKNOWN_ERROR;
+    }
+
+    LOGV("successfully decoded 1 or more frames.");
+
+    int64_t timeUs;
+    CHECK(input->meta_data()->findInt64(kKeyTime, &timeUs));
+
+    input->release();
+    input = NULL;
+
+    bool skipFrame = false;
+
+    if (mTargetTimeUs >= 0) {
+        CHECK(timeUs <= mTargetTimeUs);
+
+        if (timeUs < mTargetTimeUs) {
+            // We're still waiting for the frame with the matching
+            // timestamp and we won't return the current one.
+            skipFrame = true;
+
+            LOGV("skipping frame at %lld us", timeUs);
+        } else {
+            LOGV("found target frame at %lld us", timeUs);
+
+            mTargetTimeUs = -1;
+        }
+    }
+
+    if (skipFrame) {
+        *out = new MediaBuffer(0);
+        return OK;
+    }
+
+    vpx_codec_iter_t iter = NULL;
+    vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
+
+    if (img == NULL) {
+        LOGI("on2 decoder did not return a frame.");
+
+        *out = new MediaBuffer(0);
+        return OK;
+    }
+
+    CHECK_EQ(img->fmt, IMG_FMT_I420);
+
+    int32_t width = img->d_w;
+    int32_t height = img->d_h;
+
+    if (width != mWidth || height != mHeight) {
+        LOGI("Image dimensions changed, width = %d, height = %d",
+             width, height);
+
+        mWidth = width;
+        mHeight = height;
+        mFormat->setInt32(kKeyWidth, width);
+        mFormat->setInt32(kKeyHeight, height);
+
+        mBufferSize = (mWidth * mHeight * 3) / 2;
+        delete mBufferGroup;
+        mBufferGroup = new MediaBufferGroup;
+        mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+        mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+
+        return INFO_FORMAT_CHANGED;
+    }
+
+    MediaBuffer *output;
+    CHECK_EQ(mBufferGroup->acquire_buffer(&output), OK);
+
+    const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
+    uint8_t *dst = (uint8_t *)output->data();
+    for (size_t i = 0; i < img->d_h; ++i) {
+        memcpy(dst, srcLine, img->d_w);
+
+        srcLine += img->stride[PLANE_Y];
+        dst += img->d_w;
+    }
+
+    srcLine = (const uint8_t *)img->planes[PLANE_U];
+    for (size_t i = 0; i < img->d_h / 2; ++i) {
+        memcpy(dst, srcLine, img->d_w / 2);
+
+        srcLine += img->stride[PLANE_U];
+        dst += img->d_w / 2;
+    }
+
+    srcLine = (const uint8_t *)img->planes[PLANE_V];
+    for (size_t i = 0; i < img->d_h / 2; ++i) {
+        memcpy(dst, srcLine, img->d_w / 2);
+
+        srcLine += img->stride[PLANE_V];
+        dst += img->d_w / 2;
+    }
+
+    output->set_range(0, (width * height * 3) / 2);
+
+    output->meta_data()->setInt64(kKeyTime, timeUs);
+
+    *out = output;
+
+    return OK;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
index df3f16a..53f0638 100644
--- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
@@ -200,7 +200,8 @@
     *out = NULL;
 
     int64_t seekTimeUs;
-    if (options && options->getSeekTo(&seekTimeUs)) {
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
         CHECK(seekTimeUs >= 0);
 
         mNumFramesOutput = 0;
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index e74782f..5b16997 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -42,6 +42,7 @@
         case OMX_COLOR_FormatYUV420Planar:
         case OMX_COLOR_FormatCbYCrY:
         case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+        case OMX_COLOR_FormatYUV420SemiPlanar:
             return true;
 
         default:
@@ -71,6 +72,11 @@
                     width, height, srcBits, srcSkip, dstBits, dstSkip);
             break;
 
+        case OMX_COLOR_FormatYUV420SemiPlanar:
+            convertYUV420SemiPlanar(
+                    width, height, srcBits, srcSkip, dstBits, dstSkip);
+            break;
+
         default:
         {
             CHECK(!"Should not be here. Unknown color conversion.");
@@ -279,6 +285,68 @@
     }
 }
 
+void ColorConverter::convertYUV420SemiPlanar(
+        size_t width, size_t height,
+        const void *srcBits, size_t srcSkip,
+        void *dstBits, size_t dstSkip) {
+    CHECK_EQ(srcSkip, 0);  // Doesn't really make sense for YUV formats.
+    CHECK(dstSkip >= width * 2);
+    CHECK((dstSkip & 3) == 0);
+
+    uint8_t *kAdjustedClip = initClip();
+
+    uint32_t *dst_ptr = (uint32_t *)dstBits;
+    const uint8_t *src_y = (const uint8_t *)srcBits;
+
+    const uint8_t *src_u =
+        (const uint8_t *)src_y + width * height;
+
+    for (size_t y = 0; y < height; ++y) {
+        for (size_t x = 0; x < width; x += 2) {
+            signed y1 = (signed)src_y[x] - 16;
+            signed y2 = (signed)src_y[x + 1] - 16;
+
+            signed v = (signed)src_u[x & ~1] - 128;
+            signed u = (signed)src_u[(x & ~1) + 1] - 128;
+
+            signed u_b = u * 517;
+            signed u_g = -u * 100;
+            signed v_g = -v * 208;
+            signed v_r = v * 409;
+
+            signed tmp1 = y1 * 298;
+            signed b1 = (tmp1 + u_b) / 256;
+            signed g1 = (tmp1 + v_g + u_g) / 256;
+            signed r1 = (tmp1 + v_r) / 256;
+
+            signed tmp2 = y2 * 298;
+            signed b2 = (tmp2 + u_b) / 256;
+            signed g2 = (tmp2 + v_g + u_g) / 256;
+            signed r2 = (tmp2 + v_r) / 256;
+
+            uint32_t rgb1 =
+                ((kAdjustedClip[b1] >> 3) << 11)
+                | ((kAdjustedClip[g1] >> 2) << 5)
+                | (kAdjustedClip[r1] >> 3);
+
+            uint32_t rgb2 =
+                ((kAdjustedClip[b2] >> 3) << 11)
+                | ((kAdjustedClip[g2] >> 2) << 5)
+                | (kAdjustedClip[r2] >> 3);
+
+            dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+        }
+
+        src_y += width;
+
+        if (y & 1) {
+            src_u += width;
+        }
+
+        dst_ptr += dstSkip / 4;
+    }
+}
+
 uint8_t *ColorConverter::initClip() {
     static const signed kClipMin = -278;
     static const signed kClipMax = 535;
diff --git a/media/libstagefright/foundation/AAtomizer.cpp b/media/libstagefright/foundation/AAtomizer.cpp
new file mode 100644
index 0000000..b7b9e9f
--- /dev/null
+++ b/media/libstagefright/foundation/AAtomizer.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <sys/types.h>
+
+#include "AAtomizer.h"
+
+namespace android {
+
+// static
+AAtomizer AAtomizer::gAtomizer;
+
+// static
+const char *AAtomizer::Atomize(const char *name) {
+    return gAtomizer.atomize(name);
+}
+
+AAtomizer::AAtomizer() {
+    for (size_t i = 0; i < 128; ++i) {
+        mAtoms.push(List<AString>());
+    }
+}
+
+const char *AAtomizer::atomize(const char *name) {
+    Mutex::Autolock autoLock(mLock);
+
+    const size_t n = mAtoms.size();
+    size_t index = AAtomizer::Hash(name) % n;
+    List<AString> &entry = mAtoms.editItemAt(index);
+    List<AString>::iterator it = entry.begin();
+    while (it != entry.end()) {
+        if ((*it) == name) {
+            return (*it).c_str();
+        }
+        ++it;
+    }
+
+    entry.push_back(AString(name));
+
+    return (*--entry.end()).c_str();
+}
+
+// static
+uint32_t AAtomizer::Hash(const char *s) {
+    uint32_t sum = 0;
+    while (*s != '\0') {
+        sum = (sum * 31) + *s;
+        ++s;
+    }
+
+    return sum;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp
new file mode 100644
index 0000000..6173db4
--- /dev/null
+++ b/media/libstagefright/foundation/ABuffer.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ABuffer.h"
+
+#include "ADebug.h"
+#include "ALooper.h"
+#include "AMessage.h"
+
+namespace android {
+
+ABuffer::ABuffer(size_t capacity)
+    : mData(malloc(capacity)),
+      mCapacity(capacity),
+      mRangeOffset(0),
+      mRangeLength(capacity),
+      mInt32Data(0),
+      mOwnsData(true) {
+}
+
+ABuffer::ABuffer(void *data, size_t capacity)
+    : mData(data),
+      mCapacity(capacity),
+      mRangeOffset(0),
+      mRangeLength(capacity),
+      mInt32Data(0),
+      mOwnsData(false) {
+}
+
+ABuffer::~ABuffer() {
+    if (mOwnsData) {
+        if (mData != NULL) {
+            free(mData);
+            mData = NULL;
+        }
+    }
+
+    if (mFarewell != NULL) {
+        mFarewell->post();
+    }
+}
+
+void ABuffer::setRange(size_t offset, size_t size) {
+    CHECK_LE(offset, mCapacity);
+    CHECK_LE(offset + size, mCapacity);
+
+    mRangeOffset = offset;
+    mRangeLength = size;
+}
+
+void ABuffer::setFarewellMessage(const sp<AMessage> msg) {
+    mFarewell = msg;
+}
+
+sp<AMessage> ABuffer::meta() {
+    if (mMeta == NULL) {
+        mMeta = new AMessage;
+    }
+    return mMeta;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp
new file mode 100644
index 0000000..16f8b22
--- /dev/null
+++ b/media/libstagefright/foundation/ADebug.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ADebug.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef ANDROID
+#include <cutils/log.h>
+#endif
+
+namespace android {
+
+Logger::Logger(LogType type)
+    : mLogType(type) {
+    switch (mLogType) {
+        case VERBOSE:
+            mMessage = "V ";
+            break;
+        case INFO:
+            mMessage = "I ";
+            break;
+        case WARNING:
+            mMessage = "W ";
+            break;
+        case ERROR:
+            mMessage = "E ";
+            break;
+        case FATAL:
+            mMessage = "F ";
+            break;
+
+        default:
+            break;
+    }
+}
+
+Logger::~Logger() {
+    if (mLogType == VERBOSE) {
+        return;
+    }
+
+    mMessage.append("\n");
+
+#if defined(ANDROID) && 1
+    LOG_PRI(ANDROID_LOG_INFO, "ADebug", "%s", mMessage.c_str());
+#else
+    fprintf(stderr, mMessage.c_str());
+    fflush(stderr);
+#endif
+
+    if (mLogType == FATAL) {
+        abort();
+    }
+}
+
+const char *LeafName(const char *s) {
+    const char *lastSlash = strrchr(s, '/');
+    return lastSlash != NULL ? lastSlash + 1 : s;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/AHandler.cpp b/media/libstagefright/foundation/AHandler.cpp
new file mode 100644
index 0000000..bd5f7e9
--- /dev/null
+++ b/media/libstagefright/foundation/AHandler.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 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 "AHandler"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AHandler.h>
+
+#include <media/stagefright/foundation/ALooperRoster.h>
+
+namespace android {
+
+sp<ALooper> AHandler::looper() {
+    extern ALooperRoster gLooperRoster;
+
+    return gLooperRoster.findLooper(id());
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
new file mode 100644
index 0000000..77afb01
--- /dev/null
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2010 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 "ALooper"
+#include <utils/Log.h>
+
+#include <sys/time.h>
+
+#include "ALooper.h"
+
+#include "AHandler.h"
+#include "ALooperRoster.h"
+#include "AMessage.h"
+
+namespace android {
+
+ALooperRoster gLooperRoster;
+
+struct ALooper::LooperThread : public Thread {
+    LooperThread(ALooper *looper, bool canCallJava)
+        : Thread(canCallJava),
+          mLooper(looper) {
+    }
+
+    virtual bool threadLoop() {
+        return mLooper->loop();
+    }
+
+protected:
+    virtual ~LooperThread() {}
+
+private:
+    ALooper *mLooper;
+
+    DISALLOW_EVIL_CONSTRUCTORS(LooperThread);
+};
+
+// static
+int64_t ALooper::GetNowUs() {
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+
+    return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec;
+}
+
+ALooper::ALooper()
+    : mRunningLocally(false) {
+}
+
+ALooper::~ALooper() {
+    stop();
+}
+
+ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {
+    return gLooperRoster.registerHandler(this, handler);
+}
+
+void ALooper::unregisterHandler(handler_id handlerID) {
+    gLooperRoster.unregisterHandler(handlerID);
+}
+
+status_t ALooper::start(
+        bool runOnCallingThread, bool canCallJava, int32_t priority) {
+    if (runOnCallingThread) {
+        {
+            Mutex::Autolock autoLock(mLock);
+
+            if (mThread != NULL || mRunningLocally) {
+                return INVALID_OPERATION;
+            }
+
+            mRunningLocally = true;
+        }
+
+        do {
+        } while (loop());
+
+        return OK;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (mThread != NULL || mRunningLocally) {
+        return INVALID_OPERATION;
+    }
+
+    mThread = new LooperThread(this, canCallJava);
+
+    status_t err = mThread->run("ALooper", priority);
+    if (err != OK) {
+        mThread.clear();
+    }
+
+    return err;
+}
+
+status_t ALooper::stop() {
+    sp<LooperThread> thread;
+    bool runningLocally;
+
+    {
+        Mutex::Autolock autoLock(mLock);
+
+        thread = mThread;
+        runningLocally = mRunningLocally;
+        mThread.clear();
+        mRunningLocally = false;
+    }
+
+    if (thread == NULL && !runningLocally) {
+        return INVALID_OPERATION;
+    }
+
+    if (thread != NULL) {
+        thread->requestExit();
+    }
+
+    mQueueChangedCondition.signal();
+
+    if (!runningLocally) {
+        thread->requestExitAndWait();
+    }
+
+    return OK;
+}
+
+void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {
+    Mutex::Autolock autoLock(mLock);
+
+    int64_t whenUs;
+    if (delayUs > 0) {
+        whenUs = GetNowUs() + delayUs;
+    } else {
+        whenUs = GetNowUs();
+    }
+
+    List<Event>::iterator it = mEventQueue.begin();
+    while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) {
+        ++it;
+    }
+
+    Event event;
+    event.mWhenUs = whenUs;
+    event.mMessage = msg;
+
+    if (it == mEventQueue.begin()) {
+        mQueueChangedCondition.signal();
+    }
+
+    mEventQueue.insert(it, event);
+}
+
+bool ALooper::loop() {
+    Event event;
+
+    {
+        Mutex::Autolock autoLock(mLock);
+        if (mThread == NULL && !mRunningLocally) {
+            return false;
+        }
+        if (mEventQueue.empty()) {
+            mQueueChangedCondition.wait(mLock);
+            return true;
+        }
+        int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
+        int64_t nowUs = GetNowUs();
+
+        if (whenUs > nowUs) {
+            int64_t delayUs = whenUs - nowUs;
+            mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);
+
+            return true;
+        }
+
+        event = *mEventQueue.begin();
+        mEventQueue.erase(mEventQueue.begin());
+    }
+
+    gLooperRoster.deliverMessage(event.mMessage);
+
+    return true;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
new file mode 100644
index 0000000..65f7593
--- /dev/null
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2010 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 "ALooperRoster"
+#include <utils/Log.h>
+
+#include "ALooperRoster.h"
+
+#include "ADebug.h"
+#include "AHandler.h"
+#include "AMessage.h"
+
+namespace android {
+
+ALooperRoster::ALooperRoster()
+    : mNextHandlerID(1) {
+}
+
+ALooper::handler_id ALooperRoster::registerHandler(
+        const sp<ALooper> looper, const sp<AHandler> &handler) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (handler->id() != 0) {
+        CHECK(!"A handler must only be registered once.");
+        return INVALID_OPERATION;
+    }
+
+    HandlerInfo info;
+    info.mLooper = looper;
+    info.mHandler = handler;
+    ALooper::handler_id handlerID = mNextHandlerID++;
+    mHandlers.add(handlerID, info);
+
+    handler->setID(handlerID);
+
+    return handlerID;
+}
+
+void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
+    Mutex::Autolock autoLock(mLock);
+
+    ssize_t index = mHandlers.indexOfKey(handlerID);
+    CHECK_GE(index, 0);
+
+    const HandlerInfo &info = mHandlers.valueAt(index);
+
+    sp<AHandler> handler = info.mHandler.promote();
+
+    if (handler != NULL) {
+        handler->setID(0);
+    }
+
+    mHandlers.removeItemsAt(index);
+}
+
+void ALooperRoster::postMessage(
+        const sp<AMessage> &msg, int64_t delayUs) {
+    Mutex::Autolock autoLock(mLock);
+
+    ssize_t index = mHandlers.indexOfKey(msg->target());
+
+    if (index < 0) {
+        LOG(WARNING) << "failed to post message. Target handler not registered.";
+        return;
+    }
+
+    const HandlerInfo &info = mHandlers.valueAt(index);
+
+    sp<ALooper> looper = info.mLooper.promote();
+
+    if (looper == NULL) {
+        LOG(WARNING) << "failed to post message. "
+                        "Target handler still registered, but object gone.";
+
+        mHandlers.removeItemsAt(index);
+        return;
+    }
+
+    looper->post(msg, delayUs);
+}
+
+void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
+    sp<AHandler> handler;
+
+    {
+        Mutex::Autolock autoLock(mLock);
+
+        ssize_t index = mHandlers.indexOfKey(msg->target());
+
+        if (index < 0) {
+            LOG(WARNING) << "failed to deliver message. "
+                         << "Target handler not registered.";
+            return;
+        }
+
+        const HandlerInfo &info = mHandlers.valueAt(index);
+        handler = info.mHandler.promote();
+
+        if (handler == NULL) {
+            LOG(WARNING) << "failed to deliver message. "
+                            "Target handler registered, but object gone.";
+
+            mHandlers.removeItemsAt(index);
+            return;
+        }
+    }
+
+    handler->onMessageReceived(msg);
+}
+
+sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
+    Mutex::Autolock autoLock(mLock);
+
+    ssize_t index = mHandlers.indexOfKey(handlerID);
+
+    if (index < 0) {
+        return NULL;
+    }
+
+    sp<ALooper> looper = mHandlers.valueAt(index).mLooper.promote();
+
+    if (looper == NULL) {
+        mHandlers.removeItemsAt(index);
+        return NULL;
+    }
+
+    return looper;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
new file mode 100644
index 0000000..26c6d42
--- /dev/null
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "AMessage.h"
+
+#include <ctype.h>
+
+#include "AAtomizer.h"
+#include "ADebug.h"
+#include "ALooperRoster.h"
+#include "AString.h"
+
+namespace android {
+
+AMessage::AMessage(uint32_t what, ALooper::handler_id target)
+    : mWhat(what),
+      mTarget(target),
+      mNumItems(0) {
+}
+
+AMessage::~AMessage() {
+    clear();
+}
+
+void AMessage::setWhat(uint32_t what) {
+    mWhat = what;
+}
+
+uint32_t AMessage::what() const {
+    return mWhat;
+}
+
+void AMessage::setTarget(ALooper::handler_id handlerID) {
+    mTarget = handlerID;
+}
+
+ALooper::handler_id AMessage::target() const {
+    return mTarget;
+}
+
+void AMessage::clear() {
+    for (size_t i = 0; i < mNumItems; ++i) {
+        Item *item = &mItems[i];
+        freeItem(item);
+    }
+    mNumItems = 0;
+}
+
+void AMessage::freeItem(Item *item) {
+    switch (item->mType) {
+        case kTypeString:
+        {
+            delete item->u.stringValue;
+            break;
+        }
+
+        case kTypeObject:
+        case kTypeMessage:
+        {
+            if (item->u.refValue != NULL) {
+                item->u.refValue->decStrong(this);
+            }
+            break;
+        }
+
+        default:
+            break;
+    }
+}
+
+AMessage::Item *AMessage::allocateItem(const char *name) {
+    name = AAtomizer::Atomize(name);
+
+    size_t i = 0;
+    while (i < mNumItems && mItems[i].mName != name) {
+        ++i;
+    }
+
+    Item *item;
+
+    if (i < mNumItems) {
+        item = &mItems[i];
+        freeItem(item);
+    } else {
+        CHECK(mNumItems < kMaxNumItems);
+        i = mNumItems++;
+        item = &mItems[i];
+
+        item->mName = name;
+    }
+
+    return item;
+}
+
+const AMessage::Item *AMessage::findItem(
+        const char *name, Type type) const {
+    name = AAtomizer::Atomize(name);
+
+    for (size_t i = 0; i < mNumItems; ++i) {
+        const Item *item = &mItems[i];
+
+        if (item->mName == name) {
+            return item->mType == type ? item : NULL;
+        }
+    }
+
+    return NULL;
+}
+
+#define BASIC_TYPE(NAME,FIELDNAME,TYPENAME)                             \
+void AMessage::set##NAME(const char *name, TYPENAME value) {            \
+    Item *item = allocateItem(name);                                    \
+                                                                        \
+    item->mType = kType##NAME;                                          \
+    item->u.FIELDNAME = value;                                          \
+}                                                                       \
+                                                                        \
+bool AMessage::find##NAME(const char *name, TYPENAME *value) const {    \
+    const Item *item = findItem(name, kType##NAME);                     \
+    if (item) {                                                         \
+        *value = item->u.FIELDNAME;                                     \
+        return true;                                                    \
+    }                                                                   \
+    return false;                                                       \
+}
+
+BASIC_TYPE(Int32,int32Value,int32_t)
+BASIC_TYPE(Int64,int64Value,int64_t)
+BASIC_TYPE(Size,sizeValue,size_t)
+BASIC_TYPE(Float,floatValue,float)
+BASIC_TYPE(Double,doubleValue,double)
+BASIC_TYPE(Pointer,ptrValue,void *)
+
+#undef BASIC_TYPE
+
+void AMessage::setString(
+        const char *name, const char *s, ssize_t len) {
+    Item *item = allocateItem(name);
+    item->mType = kTypeString;
+    item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
+}
+
+void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
+    Item *item = allocateItem(name);
+    item->mType = kTypeObject;
+
+    if (obj != NULL) { obj->incStrong(this); }
+    item->u.refValue = obj.get();
+}
+
+void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
+    Item *item = allocateItem(name);
+    item->mType = kTypeMessage;
+
+    if (obj != NULL) { obj->incStrong(this); }
+    item->u.refValue = obj.get();
+}
+
+bool AMessage::findString(const char *name, AString *value) const {
+    const Item *item = findItem(name, kTypeString);
+    if (item) {
+        *value = *item->u.stringValue;
+        return true;
+    }
+    return false;
+}
+
+bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
+    const Item *item = findItem(name, kTypeObject);
+    if (item) {
+        *obj = item->u.refValue;
+        return true;
+    }
+    return false;
+}
+
+bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
+    const Item *item = findItem(name, kTypeMessage);
+    if (item) {
+        *obj = static_cast<AMessage *>(item->u.refValue);
+        return true;
+    }
+    return false;
+}
+
+void AMessage::post(int64_t delayUs) {
+    extern ALooperRoster gLooperRoster;
+
+    gLooperRoster.postMessage(this, delayUs);
+}
+
+sp<AMessage> AMessage::dup() const {
+    sp<AMessage> msg = new AMessage(mWhat, mTarget);
+    msg->mNumItems = mNumItems;
+
+    for (size_t i = 0; i < mNumItems; ++i) {
+        const Item *from = &mItems[i];
+        Item *to = &msg->mItems[i];
+
+        to->mName = from->mName;
+        to->mType = from->mType;
+
+        switch (from->mType) {
+            case kTypeString:
+            {
+                to->u.stringValue =
+                    new AString(*from->u.stringValue);
+                break;
+            }
+
+            case kTypeObject:
+            case kTypeMessage:
+            {
+                to->u.refValue = from->u.refValue;
+                to->u.refValue->incStrong(msg.get());
+                break;
+            }
+
+            default:
+            {
+                to->u = from->u;
+                break;
+            }
+        }
+    }
+
+    return msg;
+}
+
+static void appendIndent(AString *s, int32_t indent) {
+    static const char kWhitespace[] =
+        "                                        "
+        "                                        ";
+
+    CHECK_LT((size_t)indent, sizeof(kWhitespace));
+
+    s->append(kWhitespace, indent);
+}
+
+static bool isFourcc(uint32_t what) {
+    return isprint(what & 0xff)
+        && isprint((what >> 8) & 0xff)
+        && isprint((what >> 16) & 0xff)
+        && isprint((what >> 24) & 0xff);
+}
+
+AString AMessage::debugString(int32_t indent) const {
+    AString s = "AMessage(what = ";
+
+    AString tmp;
+    if (isFourcc(mWhat)) {
+        tmp = StringPrintf(
+                "'%c%c%c%c'",
+                (char)(mWhat >> 24),
+                (char)((mWhat >> 16) & 0xff),
+                (char)((mWhat >> 8) & 0xff),
+                (char)(mWhat & 0xff));
+    } else {
+        tmp = StringPrintf("0x%08x", mWhat);
+    }
+    s.append(tmp);
+
+    if (mTarget != 0) {
+        tmp = StringPrintf(", target = %d", mTarget);
+        s.append(tmp);
+    }
+    s.append(") = {\n");
+
+    for (size_t i = 0; i < mNumItems; ++i) {
+        const Item &item = mItems[i];
+
+        switch (item.mType) {
+            case kTypeInt32:
+                tmp = StringPrintf(
+                        "int32_t %s = %d", item.mName, item.u.int32Value);
+                break;
+            case kTypeInt64:
+                tmp = StringPrintf(
+                        "int64_t %s = %lld", item.mName, item.u.int64Value);
+                break;
+            case kTypeSize:
+                tmp = StringPrintf(
+                        "size_t %s = %d", item.mName, item.u.sizeValue);
+                break;
+            case kTypeFloat:
+                tmp = StringPrintf(
+                        "float %s = %f", item.mName, item.u.floatValue);
+                break;
+            case kTypeDouble:
+                tmp = StringPrintf(
+                        "double %s = %f", item.mName, item.u.doubleValue);
+                break;
+            case kTypePointer:
+                tmp = StringPrintf(
+                        "void *%s = %p", item.mName, item.u.ptrValue);
+                break;
+            case kTypeString:
+                tmp = StringPrintf(
+                        "string %s = \"%s\"",
+                        item.mName,
+                        item.u.stringValue->c_str());
+                break;
+            case kTypeObject:
+                tmp = StringPrintf(
+                        "RefBase *%s = %p", item.mName, item.u.refValue);
+                break;
+            case kTypeMessage:
+                tmp = StringPrintf(
+                        "AMessage %s = %s",
+                        item.mName,
+                        static_cast<AMessage *>(
+                            item.u.refValue)->debugString(
+                                indent + strlen(item.mName) + 14).c_str());
+                break;
+            default:
+                TRESPASS();
+        }
+
+        appendIndent(&s, indent);
+        s.append("  ");
+        s.append(tmp);
+        s.append("\n");
+    }
+
+    appendIndent(&s, indent);
+    s.append("}");
+
+    return s;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
new file mode 100644
index 0000000..61b76cf
--- /dev/null
+++ b/media/libstagefright/foundation/AString.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ADebug.h"
+#include "AString.h"
+
+namespace android {
+
+// static
+const char *AString::kEmptyString = "";
+
+AString::AString()
+    : mData((char *)kEmptyString),
+      mSize(0),
+      mAllocSize(1) {
+}
+
+AString::AString(const char *s)
+    : mData(NULL),
+      mSize(0),
+      mAllocSize(1) {
+    setTo(s);
+}
+
+AString::AString(const char *s, size_t size)
+    : mData(NULL),
+      mSize(0),
+      mAllocSize(1) {
+    setTo(s, size);
+}
+
+AString::AString(const AString &from)
+    : mData(NULL),
+      mSize(0),
+      mAllocSize(1) {
+    setTo(from, 0, from.size());
+}
+
+AString::AString(const AString &from, size_t offset, size_t n)
+    : mData(NULL),
+      mSize(0),
+      mAllocSize(1) {
+    setTo(from, offset, n);
+}
+
+AString::~AString() {
+    clear();
+}
+
+AString &AString::operator=(const AString &from) {
+    if (&from != this) {
+        setTo(from, 0, from.size());
+    }
+
+    return *this;
+}
+
+size_t AString::size() const {
+    return mSize;
+}
+
+const char *AString::c_str() const {
+    return mData;
+}
+
+bool AString::empty() const {
+    return mSize == 0;
+}
+
+void AString::setTo(const char *s) {
+    setTo(s, strlen(s));
+}
+
+void AString::setTo(const char *s, size_t size) {
+    clear();
+    append(s, size);
+}
+
+void AString::setTo(const AString &from, size_t offset, size_t n) {
+    CHECK(&from != this);
+
+    clear();
+    setTo(from.mData + offset, n);
+}
+
+void AString::clear() {
+    if (mData && mData != kEmptyString) {
+        free(mData);
+        mData = NULL;
+    }
+
+    mData = (char *)kEmptyString;
+    mSize = 0;
+    mAllocSize = 1;
+}
+
+size_t AString::hash() const {
+    size_t x = 0;
+    for (size_t i = 0; i < mSize; ++i) {
+        x = (x * 31) + mData[i];
+    }
+
+    return x;
+}
+
+bool AString::operator==(const AString &other) const {
+    return mSize == other.mSize && !memcmp(mData, other.mData, mSize);
+}
+
+void AString::trim() {
+    makeMutable();
+
+    size_t i = 0;
+    while (i < mSize && isspace(mData[i])) {
+        ++i;
+    }
+
+    size_t j = mSize;
+    while (j > i && isspace(mData[j - 1])) {
+        --j;
+    }
+
+    memmove(mData, &mData[i], j - i);
+    mSize = j - i;
+    mData[mSize] = '\0';
+}
+
+void AString::erase(size_t start, size_t n) {
+    CHECK_LT(start, mSize);
+    CHECK_LE(start + n, mSize);
+
+    makeMutable();
+
+    memmove(&mData[start], &mData[start + n], mSize - start - n);
+    mSize -= n;
+    mData[mSize] = '\0';
+}
+
+void AString::makeMutable() {
+    if (mData == kEmptyString) {
+        mData = strdup(kEmptyString);
+    }
+}
+
+void AString::append(const char *s) {
+    append(s, strlen(s));
+}
+
+void AString::append(const char *s, size_t size) {
+    makeMutable();
+
+    if (mSize + size + 1 > mAllocSize) {
+        mAllocSize = (mAllocSize + size + 31) & -32;
+        mData = (char *)realloc(mData, mAllocSize);
+        CHECK(mData != NULL);
+    }
+
+    memcpy(&mData[mSize], s, size);
+    mSize += size;
+    mData[mSize] = '\0';
+}
+
+void AString::append(const AString &from) {
+    append(from.c_str(), from.size());
+}
+
+void AString::append(const AString &from, size_t offset, size_t n) {
+    append(from.c_str() + offset, n);
+}
+
+void AString::append(int x) {
+    char s[16];
+    sprintf(s, "%d", x);
+
+    append(s);
+}
+
+void AString::append(unsigned x) {
+    char s[16];
+    sprintf(s, "%u", x);
+
+    append(s);
+}
+
+void AString::append(long x) {
+    char s[16];
+    sprintf(s, "%ld", x);
+
+    append(s);
+}
+
+void AString::append(unsigned long x) {
+    char s[16];
+    sprintf(s, "%lu", x);
+
+    append(s);
+}
+
+void AString::append(long long x) {
+    char s[32];
+    sprintf(s, "%lld", x);
+
+    append(s);
+}
+
+void AString::append(unsigned long long x) {
+    char s[32];
+    sprintf(s, "%llu", x);
+
+    append(s);
+}
+
+void AString::append(float x) {
+    char s[16];
+    sprintf(s, "%f", x);
+
+    append(s);
+}
+
+void AString::append(double x) {
+    char s[16];
+    sprintf(s, "%f", x);
+
+    append(s);
+}
+
+void AString::append(void *x) {
+    char s[16];
+    sprintf(s, "%p", x);
+
+    append(s);
+}
+
+ssize_t AString::find(const char *substring, size_t start) const {
+    CHECK_LE(start, size());
+
+    const char *match = strstr(mData + start, substring);
+
+    if (match == NULL) {
+        return -1;
+    }
+
+    return match - mData;
+}
+
+void AString::insert(const AString &from, size_t insertionPos) {
+    insert(from.c_str(), from.size(), insertionPos);
+}
+
+void AString::insert(const char *from, size_t size, size_t insertionPos) {
+    CHECK_GE(insertionPos, 0u);
+    CHECK_LE(insertionPos, mSize);
+
+    makeMutable();
+
+    if (mSize + size + 1 > mAllocSize) {
+        mAllocSize = (mAllocSize + size + 31) & -32;
+        mData = (char *)realloc(mData, mAllocSize);
+        CHECK(mData != NULL);
+    }
+
+    memmove(&mData[insertionPos + size],
+            &mData[insertionPos], mSize - insertionPos + 1);
+
+    memcpy(&mData[insertionPos], from, size);
+
+    mSize += size;
+}
+
+bool AString::operator<(const AString &other) const {
+    return compare(other) < 0;
+}
+
+bool AString::operator>(const AString &other) const {
+    return compare(other) > 0;
+}
+
+int AString::compare(const AString &other) const {
+    return strcmp(mData, other.mData);
+}
+
+void AString::tolower() {
+    makeMutable();
+
+    for (size_t i = 0; i < mSize; ++i) {
+        mData[i] = ::tolower(mData[i]);
+    }
+}
+
+bool AString::startsWith(const char *prefix) const {
+    return !strncmp(mData, prefix, strlen(prefix));
+}
+
+AString StringPrintf(const char *format, ...) {
+    va_list ap;
+    va_start(ap, format);
+
+    char *buffer;
+    vasprintf(&buffer, format, ap);
+
+    va_end(ap);
+
+    AString result(buffer);
+
+    free(buffer);
+    buffer = NULL;
+
+    return result;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
new file mode 100644
index 0000000..35eea7e
--- /dev/null
+++ b/media/libstagefright/foundation/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    AAtomizer.cpp               \
+    ABuffer.cpp                 \
+    ADebug.cpp                  \
+    AHandler.cpp                \
+    ALooper.cpp                 \
+    ALooperRoster.cpp           \
+    AMessage.cpp                \
+    AString.cpp                 \
+    base64.cpp                  \
+    hexdump.cpp
+
+LOCAL_C_INCLUDES:= \
+    frameworks/base/include/media/stagefright/foundation
+
+LOCAL_SHARED_LIBRARIES := \
+        libbinder         \
+        libmedia          \
+        libutils          \
+        libcutils         \
+        libui             \
+        libsonivox        \
+        libvorbisidec     \
+        libsurfaceflinger_client \
+        libcamera_client
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= libstagefright_foundation
+
+LOCAL_PRELINK_MODULE:= false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp
new file mode 100644
index 0000000..d5fb4e0
--- /dev/null
+++ b/media/libstagefright/foundation/base64.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "base64.h"
+
+#include "ABuffer.h"
+#include "ADebug.h"
+
+namespace android {
+
+sp<ABuffer> decodeBase64(const AString &s) {
+    if ((s.size() % 4) != 0) {
+        return NULL;
+    }
+
+    size_t n = s.size();
+    size_t padding = 0;
+    if (n >= 1 && s.c_str()[n - 1] == '=') {
+        padding = 1;
+
+        if (n >= 2 && s.c_str()[n - 2] == '=') {
+            padding = 2;
+        }
+    }
+
+    size_t outLen = 3 * s.size() / 4 - padding;
+
+    sp<ABuffer> buffer = new ABuffer(outLen);
+
+    uint8_t *out = buffer->data();
+    size_t j = 0;
+    uint32_t accum = 0;
+    for (size_t i = 0; i < n; ++i) {
+        char c = s.c_str()[i];
+        unsigned value;
+        if (c >= 'A' && c <= 'Z') {
+            value = c - 'A';
+        } else if (c >= 'a' && c <= 'z') {
+            value = 26 + c - 'a';
+        } else if (c >= '0' && c <= '9') {
+            value = 52 + c - '0';
+        } else if (c == '+') {
+            value = 62;
+        } else if (c == '/') {
+            value = 63;
+        } else if (c != '=') {
+            return NULL;
+        } else {
+            if (i < n - padding) {
+                return NULL;
+            }
+
+            value = 0;
+        }
+
+        accum = (accum << 6) | value;
+
+        if (((i + 1) % 4) == 0) {
+            out[j++] = (accum >> 16);
+
+            if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 
+            if (j < outLen) { out[j++] = accum & 0xff; }
+
+            accum = 0;
+        }
+    }
+
+    return buffer;
+}
+
+static char encode6Bit(unsigned x) {
+    if (x <= 25) {
+        return 'A' + x;
+    } else if (x <= 51) {
+        return 'a' + x - 26;
+    } else if (x <= 61) {
+        return '0' + x - 52;
+    } else if (x == 62) {
+        return '+';
+    } else {
+        return '/';
+    }
+}
+
+void encodeBase64(
+        const void *_data, size_t size, AString *out) {
+    out->clear();
+
+    const uint8_t *data = (const uint8_t *)_data;
+
+    size_t i;
+    for (i = 0; i < (size / 3) * 3; i += 3) {
+        uint8_t x1 = data[i];
+        uint8_t x2 = data[i + 1];
+        uint8_t x3 = data[i + 2];
+
+        out->append(encode6Bit(x1 >> 2));
+        out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+        out->append(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f));
+        out->append(encode6Bit(x3 & 0x3f));
+    }
+    switch (size % 3) {
+        case 0:
+            break;
+        case 2:
+        {
+            uint8_t x1 = data[i];
+            uint8_t x2 = data[i + 1];
+            out->append(encode6Bit(x1 >> 2));
+            out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+            out->append(encode6Bit((x2 << 2) & 0x3f));
+            out->append('=');
+            break;
+        }
+        default:
+        {
+            uint8_t x1 = data[i];
+            out->append(encode6Bit(x1 >> 2));
+            out->append(encode6Bit((x1 << 4) & 0x3f));
+            out->append("==");
+            break;
+        }
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/libstagefright/foundation/hexdump.cpp
new file mode 100644
index 0000000..093b587
--- /dev/null
+++ b/media/libstagefright/foundation/hexdump.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "hexdump.h"
+
+#include "ADebug.h"
+#include "AString.h"
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdio.h>
+
+namespace android {
+
+void hexdump(const void *_data, size_t size) {
+    const uint8_t *data = (const uint8_t *)_data;
+
+    size_t offset = 0;
+    while (offset < size) {
+        AString line;
+
+        char tmp[32];
+        sprintf(tmp, "%08lx:  ", (unsigned long)offset);
+
+        line.append(tmp);
+
+        for (size_t i = 0; i < 16; ++i) {
+            if (i == 8) {
+                line.append(' ');
+            }
+            if (offset + i >= size) {
+                line.append("   ");
+            } else {
+                sprintf(tmp, "%02x ", data[offset + i]);
+                line.append(tmp);
+            }
+        }
+
+        line.append(' ');
+
+        for (size_t i = 0; i < 16; ++i) {
+            if (offset + i >= size) {
+                break;
+            }
+
+            if (isprint(data[offset + i])) {
+                line.append((char)data[offset + i]);
+            } else {
+                line.append('.');
+            }
+        }
+
+        LOG(INFO) << line;
+
+        offset += 16;
+    }
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
new file mode 100644
index 0000000..3de2c80
--- /dev/null
+++ b/media/libstagefright/httplive/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=       \
+        LiveSource.cpp  \
+        M3UParser.cpp   \
+
+LOCAL_C_INCLUDES:= \
+	$(JNI_H_INCLUDE) \
+	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+        $(TOP)/frameworks/base/media/libstagefright
+
+LOCAL_MODULE:= libstagefright_httplive
+
+ifeq ($(TARGET_ARCH),arm)
+    LOCAL_CFLAGS += -Wno-psabi
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/httplive/LiveSource.cpp b/media/libstagefright/httplive/LiveSource.cpp
new file mode 100644
index 0000000..001afc4
--- /dev/null
+++ b/media/libstagefright/httplive/LiveSource.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2010 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_TAG "LiveSource"
+#include <utils/Log.h>
+
+#include "include/LiveSource.h"
+#include "include/M3UParser.h"
+#include "include/NuHTTPDataSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/MediaDebug.h>
+
+namespace android {
+
+LiveSource::LiveSource(const char *url)
+    : mURL(url),
+      mInitCheck(NO_INIT),
+      mPlaylistIndex(0),
+      mLastFetchTimeUs(-1),
+      mSource(new NuHTTPDataSource),
+      mSourceSize(0),
+      mOffsetBias(0) {
+    if (switchToNext()) {
+        mInitCheck = OK;
+    }
+}
+
+LiveSource::~LiveSource() {
+}
+
+status_t LiveSource::initCheck() const {
+    return mInitCheck;
+}
+
+bool LiveSource::loadPlaylist() {
+    mPlaylist.clear();
+    mPlaylistIndex = 0;
+
+    sp<ABuffer> buffer;
+    status_t err = fetchM3U(mURL.c_str(), &buffer);
+
+    if (err != OK) {
+        return false;
+    }
+
+    mPlaylist = new M3UParser(mURL.c_str(), buffer->data(), buffer->size());
+
+    if (mPlaylist->initCheck() != OK) {
+        return false;
+    }
+
+    if (!mPlaylist->meta()->findInt32(
+                "media-sequence", &mFirstItemSequenceNumber)) {
+        mFirstItemSequenceNumber = 0;
+    }
+
+    return true;
+}
+
+static int64_t getNowUs() {
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+
+    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
+}
+
+bool LiveSource::switchToNext() {
+    mOffsetBias += mSourceSize;
+    mSourceSize = 0;
+
+    if (mLastFetchTimeUs < 0 || getNowUs() >= mLastFetchTimeUs + 15000000ll
+        || mPlaylistIndex == mPlaylist->size()) {
+        int32_t nextSequenceNumber =
+            mPlaylistIndex + mFirstItemSequenceNumber;
+
+        if (!loadPlaylist()) {
+            LOGE("failed to reload playlist");
+            return false;
+        }
+
+        if (mLastFetchTimeUs < 0) {
+            mPlaylistIndex = mPlaylist->size() / 2;
+        } else {
+            if (nextSequenceNumber < mFirstItemSequenceNumber
+                    || nextSequenceNumber
+                            >= mFirstItemSequenceNumber + (int32_t)mPlaylist->size()) {
+                LOGE("Cannot find sequence number %d in new playlist",
+                     nextSequenceNumber);
+
+                return false;
+            }
+
+            mPlaylistIndex = nextSequenceNumber - mFirstItemSequenceNumber;
+        }
+
+        mLastFetchTimeUs = getNowUs();
+    }
+
+    AString uri;
+    CHECK(mPlaylist->itemAt(mPlaylistIndex, &uri));
+    LOGI("switching to %s", uri.c_str());
+
+    if (mSource->connect(uri.c_str()) != OK
+            || mSource->getSize(&mSourceSize) != OK) {
+        return false;
+    }
+
+    mPlaylistIndex++;
+    return true;
+}
+
+ssize_t LiveSource::readAt(off_t offset, void *data, size_t size) {
+    CHECK(offset >= mOffsetBias);
+    offset -= mOffsetBias;
+
+    if (offset >= mSourceSize) {
+        CHECK_EQ(offset, mSourceSize);
+
+        offset -= mSourceSize;
+        if (!switchToNext()) {
+            return ERROR_END_OF_STREAM;
+        }
+    }
+
+    size_t numRead = 0;
+    while (numRead < size) {
+        ssize_t n = mSource->readAt(
+                offset + numRead, (uint8_t *)data + numRead, size - numRead);
+
+        if (n <= 0) {
+            break;
+        }
+
+        numRead += n;
+    }
+
+    return numRead;
+}
+
+status_t LiveSource::fetchM3U(const char *url, sp<ABuffer> *out) {
+    *out = NULL;
+
+    status_t err = mSource->connect(url);
+
+    if (err != OK) {
+        return err;
+    }
+
+    off_t size;
+    err = mSource->getSize(&size);
+
+    if (err != OK) {
+        return err;
+    }
+
+    sp<ABuffer> buffer = new ABuffer(size);
+    size_t offset = 0;
+    while (offset < (size_t)size) {
+        ssize_t n = mSource->readAt(
+                offset, buffer->data() + offset, size - offset);
+
+        if (n <= 0) {
+            return ERROR_IO;
+        }
+
+        offset += n;
+    }
+
+    *out = buffer;
+
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
new file mode 100644
index 0000000..edd8648
--- /dev/null
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "include/M3UParser.h"
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+M3UParser::M3UParser(
+        const char *baseURI, const void *data, size_t size)
+    : mInitCheck(NO_INIT),
+      mBaseURI(baseURI),
+      mIsExtM3U(false),
+      mIsVariantPlaylist(false) {
+    mInitCheck = parse(data, size);
+}
+
+M3UParser::~M3UParser() {
+}
+
+status_t M3UParser::initCheck() const {
+    return mInitCheck;
+}
+
+bool M3UParser::isExtM3U() const {
+    return mIsExtM3U;
+}
+
+bool M3UParser::isVariantPlaylist() const {
+    return mIsVariantPlaylist;
+}
+
+sp<AMessage> M3UParser::meta() {
+    return mMeta;
+}
+
+size_t M3UParser::size() {
+    return mItems.size();
+}
+
+bool M3UParser::itemAt(size_t index, AString *uri, sp<AMessage> *meta) {
+    uri->clear();
+    if (meta) { *meta = NULL; }
+
+    if (index >= mItems.size()) {
+        return false;
+    }
+
+    *uri = mItems.itemAt(index).mURI;
+
+    if (meta) {
+        *meta = mItems.itemAt(index).mMeta;
+    }
+
+    return true;
+}
+
+static bool MakeURL(const char *baseURL, const char *url, AString *out) {
+    out->clear();
+
+    if (strncasecmp("http://", baseURL, 7)) {
+        // Base URL must be absolute
+        return false;
+    }
+
+    if (!strncasecmp("http://", url, 7)) {
+        // "url" is already an absolute URL, ignore base URL.
+        out->setTo(url);
+        return true;
+    }
+
+    size_t n = strlen(baseURL);
+    if (baseURL[n - 1] == '/') {
+        out->setTo(baseURL);
+        out->append(url);
+    } else {
+        char *slashPos = strrchr(baseURL, '/');
+
+        if (slashPos > &baseURL[6]) {
+            out->setTo(baseURL, slashPos - baseURL);
+        } else {
+            out->setTo(baseURL);
+        }
+
+        out->append("/");
+        out->append(url);
+    }
+
+    return true;
+}
+
+status_t M3UParser::parse(const void *_data, size_t size) {
+    int32_t lineNo = 0;
+
+    sp<AMessage> itemMeta;
+
+    const char *data = (const char *)_data;
+    size_t offset = 0;
+    while (offset < size) {
+        size_t offsetLF = offset;
+        while (offsetLF < size && data[offsetLF] != '\n') {
+            ++offsetLF;
+        }
+        if (offsetLF >= size) {
+            break;
+        }
+
+        AString line;
+        if (offsetLF > offset && data[offsetLF - 1] == '\r') {
+            line.setTo(&data[offset], offsetLF - offset - 1);
+        } else {
+            line.setTo(&data[offset], offsetLF - offset);
+        }
+
+        LOGI("#%s#", line.c_str());
+
+        if (lineNo == 0 && line == "#EXTM3U") {
+            mIsExtM3U = true;
+        }
+
+        if (mIsExtM3U) {
+            status_t err = OK;
+
+            if (line.startsWith("#EXT-X-TARGETDURATION")) {
+                if (mIsVariantPlaylist) {
+                    return ERROR_MALFORMED;
+                }
+                err = parseMetaData(line, &mMeta, "target-duration");
+            } else if (line.startsWith("#EXT-X-MEDIA-SEQUENCE")) {
+                if (mIsVariantPlaylist) {
+                    return ERROR_MALFORMED;
+                }
+                err = parseMetaData(line, &mMeta, "media-sequence");
+            } else if (line.startsWith("#EXTINF")) {
+                if (mIsVariantPlaylist) {
+                    return ERROR_MALFORMED;
+                }
+                err = parseMetaData(line, &itemMeta, "duration");
+            } else if (line.startsWith("#EXT-X-STREAM-INF")) {
+                if (mMeta != NULL) {
+                    return ERROR_MALFORMED;
+                }
+                mIsVariantPlaylist = true;
+            }
+
+            if (err != OK) {
+                return err;
+            }
+        }
+
+        if (!line.startsWith("#")) {
+            if (!mIsVariantPlaylist) {
+                int32_t durationSecs;
+                if (itemMeta == NULL
+                        || !itemMeta->findInt32("duration", &durationSecs)) {
+                    return ERROR_MALFORMED;
+                }
+            }
+
+            mItems.push();
+            Item *item = &mItems.editItemAt(mItems.size() - 1);
+
+            CHECK(MakeURL(mBaseURI.c_str(), line.c_str(), &item->mURI));
+
+            item->mMeta = itemMeta;
+
+            itemMeta.clear();
+        }
+
+        offset = offsetLF + 1;
+        ++lineNo;
+    }
+
+    return OK;
+}
+
+// static
+status_t M3UParser::parseMetaData(
+        const AString &line, sp<AMessage> *meta, const char *key) {
+    ssize_t colonPos = line.find(":");
+
+    if (colonPos < 0) {
+        return ERROR_MALFORMED;
+    }
+
+    int32_t x;
+    status_t err = ParseInt32(line.c_str() + colonPos + 1, &x);
+
+    if (err != OK) {
+        return err;
+    }
+
+    if (meta->get() == NULL) {
+        *meta = new AMessage;
+    }
+    (*meta)->setInt32(key, x);
+
+    return OK;
+}
+
+// static
+status_t M3UParser::ParseInt32(const char *s, int32_t *x) {
+    char *end;
+    long lval = strtol(s, &end, 10);
+
+    if (end == s || (*end != '\0' && *end != ',')) {
+        return ERROR_MALFORMED;
+    }
+
+    *x = (int32_t)lval;
+
+    return OK;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index 93fac1c..23c8e44 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -28,5 +26,3 @@
 LOCAL_MODULE := testid3
 
 include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h
new file mode 100644
index 0000000..ecc533f
--- /dev/null
+++ b/media/libstagefright/include/AACEncoder.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 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 AAC_ENCODER_H
+#define AAC_ENCODER_H
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+struct VO_AUDIO_CODECAPI;
+struct VO_MEM_OPERATOR;
+
+namespace android {
+
+struct MediaBufferGroup;
+
+class AACEncoder: public MediaSource {
+    public:
+        AACEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
+
+        virtual status_t start(MetaData *params);
+        virtual status_t stop();
+        virtual sp<MetaData> getFormat();
+        virtual status_t read(
+                MediaBuffer **buffer, const ReadOptions *options);
+
+
+    protected:
+        virtual ~AACEncoder();
+
+    private:
+        sp<MediaSource>   mSource;
+        sp<MetaData>      mMeta;
+        bool              mStarted;
+        MediaBufferGroup *mBufferGroup;
+        MediaBuffer      *mInputBuffer;
+        status_t          mInitCheck;
+        int32_t           mSampleRate;
+        int32_t           mChannels;
+        int32_t           mBitRate;
+        int32_t           mFrameCount;
+
+        int64_t           mAnchorTimeUs;
+        int64_t           mNumInputSamples;
+
+        enum {
+            kNumSamplesPerFrame = 1024,
+        };
+
+        int16_t           mInputFrame[kNumSamplesPerFrame];
+
+        uint8_t           mAudioSpecificConfigData[2]; // auido specific data
+        void             *mEncoderHandle;
+        VO_AUDIO_CODECAPI *mApiHandle;
+        VO_MEM_OPERATOR  *mMemOperator;
+
+        status_t setAudioSpecificConfigData();
+        status_t initCheck();
+
+        AACEncoder& operator=(const AACEncoder &rhs);
+        AACEncoder(const AACEncoder& copy);
+
+};
+
+}
+
+#endif  //#ifndef AAC_ENCODER_H
+
diff --git a/media/libstagefright/include/AMRNBEncoder.h b/media/libstagefright/include/AMRNBEncoder.h
index 7167c00..71160e6 100644
--- a/media/libstagefright/include/AMRNBEncoder.h
+++ b/media/libstagefright/include/AMRNBEncoder.h
@@ -19,13 +19,14 @@
 #define AMR_NB_ENCODER_H_
 
 #include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
 
 namespace android {
 
 struct MediaBufferGroup;
 
 struct AMRNBEncoder : public MediaSource {
-    AMRNBEncoder(const sp<MediaSource> &source);
+    AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
 
     virtual status_t start(MetaData *params);
     virtual status_t stop();
@@ -40,6 +41,7 @@
 
 private:
     sp<MediaSource> mSource;
+    sp<MetaData>    mMeta;
     bool mStarted;
 
     MediaBufferGroup *mBufferGroup;
diff --git a/media/libstagefright/include/AMRWBEncoder.h b/media/libstagefright/include/AMRWBEncoder.h
new file mode 100644
index 0000000..f2d155f
--- /dev/null
+++ b/media/libstagefright/include/AMRWBEncoder.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 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 AMR_WB_ENCODER_H
+#define AMR_WB_ENCODER_H
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+struct VO_AUDIO_CODECAPI;
+struct VO_MEM_OPERATOR;
+
+namespace android {
+
+struct MediaBufferGroup;
+
+class AMRWBEncoder: public MediaSource {
+    public:
+        AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
+
+        virtual status_t start(MetaData *params);
+        virtual status_t stop();
+        virtual sp<MetaData> getFormat();
+        virtual status_t read(
+                MediaBuffer **buffer, const ReadOptions *options);
+
+
+    protected:
+        virtual ~AMRWBEncoder();
+
+    private:
+        sp<MediaSource>   mSource;
+        sp<MetaData>      mMeta;
+        bool              mStarted;
+        MediaBufferGroup *mBufferGroup;
+        MediaBuffer      *mInputBuffer;
+        status_t          mInitCheck;
+        int32_t           mBitRate;
+        void             *mEncoderHandle;
+        VO_AUDIO_CODECAPI *mApiHandle;
+        VO_MEM_OPERATOR  *mMemOperator;
+
+        int64_t mAnchorTimeUs;
+        int64_t mNumFramesOutput;
+
+        int16_t mInputFrame[320];
+        int32_t mNumInputSamples;
+
+        status_t initCheck();
+
+        AMRWBEncoder& operator=(const AMRWBEncoder &rhs);
+        AMRWBEncoder(const AMRWBEncoder& copy);
+
+};
+
+}
+
+#endif  //#ifndef AMR_WB_ENCODER_H
+
diff --git a/media/libstagefright/include/ARTSPController.h b/media/libstagefright/include/ARTSPController.h
new file mode 100644
index 0000000..55efd41
--- /dev/null
+++ b/media/libstagefright/include/ARTSPController.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 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 A_RTSP_CONTROLLER_H_
+
+#define A_RTSP_CONTROLLER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaExtractor.h>
+
+namespace android {
+
+struct ALooper;
+struct MyHandler;
+
+struct ARTSPController : public MediaExtractor {
+    ARTSPController(const sp<ALooper> &looper);
+
+    status_t connect(const char *url);
+    void disconnect();
+
+    virtual size_t countTracks();
+    virtual sp<MediaSource> getTrack(size_t index);
+
+    virtual sp<MetaData> getTrackMetaData(
+            size_t index, uint32_t flags);
+
+protected:
+    virtual ~ARTSPController();
+
+private:
+    sp<ALooper> mLooper;
+    sp<MyHandler> mHandler;
+
+    DISALLOW_EVIL_CONSTRUCTORS(ARTSPController);
+};
+
+}  // namespace android
+
+#endif  // A_RTSP_CONTROLLER_H_
diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h
index 621aa9a..7810171 100644
--- a/media/libstagefright/include/AVCDecoder.h
+++ b/media/libstagefright/include/AVCDecoder.h
@@ -58,6 +58,9 @@
     int64_t mAnchorTimeUs;
     int64_t mNumSamplesOutput;
     int64_t mPendingSeekTimeUs;
+    MediaSource::ReadOptions::SeekMode mPendingSeekMode;
+
+    int64_t mTargetTimeUs;
 
     void addCodecSpecificData(const uint8_t *data, size_t size);
 
diff --git a/media/libstagefright/include/AVCEncoder.h b/media/libstagefright/include/AVCEncoder.h
new file mode 100644
index 0000000..4fe2e30
--- /dev/null
+++ b/media/libstagefright/include/AVCEncoder.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 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 AVC_ENCODER_H_
+
+#define AVC_ENCODER_H_
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+struct tagAVCHandle;
+struct tagAVCEncParam;
+
+namespace android {
+
+struct MediaBuffer;
+struct MediaBufferGroup;
+
+struct AVCEncoder : public MediaSource,
+                    public MediaBufferObserver {
+    AVCEncoder(const sp<MediaSource> &source,
+            const sp<MetaData>& meta);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options);
+
+    virtual void signalBufferReturned(MediaBuffer *buffer);
+
+    // Callbacks required by the encoder
+    int32_t allocOutputBuffers(unsigned int sizeInMbs, unsigned int numBuffers);
+    void    unbindOutputBuffer(int32_t index);
+    int32_t bindOutputBuffer(int32_t index, uint8_t **yuv);
+
+protected:
+    virtual ~AVCEncoder();
+
+private:
+    sp<MediaSource> mSource;
+    sp<MetaData>    mFormat;
+    sp<MetaData>    mMeta;
+
+    int32_t  mVideoWidth;
+    int32_t  mVideoHeight;
+    int32_t  mVideoFrameRate;
+    int32_t  mVideoBitRate;
+    int32_t  mVideoColorFormat;
+    int64_t  mNumInputFrames;
+    status_t mInitCheck;
+    bool     mStarted;
+    bool     mSpsPpsHeaderReceived;
+    bool     mReadyForNextFrame;
+    int32_t  mIsIDRFrame;  // for set kKeyIsSyncFrame
+
+    tagAVCHandle          *mHandle;
+    tagAVCEncParam        *mEncParams;
+    MediaBuffer           *mInputBuffer;
+    uint8_t               *mInputFrameData;
+    MediaBufferGroup      *mGroup;
+    Vector<MediaBuffer *> mOutputBuffers;
+
+
+    status_t initCheck(const sp<MetaData>& meta);
+    void releaseOutputBuffers();
+
+    AVCEncoder(const AVCEncoder &);
+    AVCEncoder &operator=(const AVCEncoder &);
+};
+
+}  // namespace android
+
+#endif  // AVC_ENCODER_H_
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 9455743..8d0877c 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -18,12 +18,13 @@
 
 #define AWESOME_PLAYER_H_
 
+#include "NuHTTPDataSource.h"
 #include "TimedEventQueue.h"
 
 #include <media/MediaPlayerInterface.h>
 #include <media/stagefright/DataSource.h>
-#include <media/stagefright/HTTPDataSource.h>
 #include <media/stagefright/OMXClient.h>
+#include <media/stagefright/TimeSource.h>
 #include <utils/threads.h>
 
 namespace android {
@@ -33,8 +34,10 @@
 struct MediaBuffer;
 struct MediaExtractor;
 struct MediaSource;
-struct Prefetcher;
-struct TimeSource;
+struct NuCachedSource2;
+
+struct ALooper;
+struct ARTSPController;
 
 struct AwesomeRenderer : public RefBase {
     AwesomeRenderer() {}
@@ -98,6 +101,9 @@
         PREPARED            = 16,
         AT_EOS              = 32,
         PREPARE_CANCELLED   = 64,
+        CACHE_UNDERRUN      = 128,
+        AUDIO_AT_EOS        = 256,
+        VIDEO_AT_EOS        = 512,
     };
 
     mutable Mutex mLock;
@@ -111,6 +117,7 @@
     sp<ISurface> mISurface;
     sp<MediaPlayerBase::AudioSink> mAudioSink;
 
+    SystemTimeSource mSystemTimeSource;
     TimeSource *mTimeSource;
 
     String8 mUri;
@@ -166,8 +173,11 @@
     MediaBuffer *mLastVideoBuffer;
     MediaBuffer *mVideoBuffer;
 
-    sp<Prefetcher> mPrefetcher;
-    sp<HTTPDataSource> mConnectingDataSource;
+    sp<NuHTTPDataSource> mConnectingDataSource;
+    sp<NuCachedSource2> mCachedSource;
+
+    sp<ALooper> mLooper;
+    sp<ARTSPController> mRTSPController;
 
     struct SuspensionState {
         String8 mUri;
diff --git a/media/libstagefright/include/LiveSource.h b/media/libstagefright/include/LiveSource.h
new file mode 100644
index 0000000..c55508c
--- /dev/null
+++ b/media/libstagefright/include/LiveSource.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 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 LIVE_SOURCE_H_
+
+#define LIVE_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/DataSource.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct ABuffer;
+struct NuHTTPDataSource;
+struct M3UParser;
+
+struct LiveSource : public DataSource {
+    LiveSource(const char *url);
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off_t offset, void *data, size_t size);
+
+    virtual uint32_t flags() {
+        return kWantsPrefetching;
+    }
+
+protected:
+    virtual ~LiveSource();
+
+private:
+    AString mURL;
+    status_t mInitCheck;
+
+    sp<M3UParser> mPlaylist;
+    int32_t mFirstItemSequenceNumber;
+    size_t mPlaylistIndex;
+    int64_t mLastFetchTimeUs;
+
+    sp<NuHTTPDataSource> mSource;
+    off_t mSourceSize;
+    off_t mOffsetBias;
+
+    status_t fetchM3U(const char *url, sp<ABuffer> *buffer);
+
+    bool switchToNext();
+    bool loadPlaylist();
+
+    DISALLOW_EVIL_CONSTRUCTORS(LiveSource);
+};
+
+}  // namespace android
+
+#endif  // LIVE_SOURCE_H_
diff --git a/media/libstagefright/include/M3UParser.h b/media/libstagefright/include/M3UParser.h
new file mode 100644
index 0000000..36553de
--- /dev/null
+++ b/media/libstagefright/include/M3UParser.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 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 M3U_PARSER_H_
+
+#define M3U_PARSER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct M3UParser : public RefBase {
+    M3UParser(const char *baseURI, const void *data, size_t size);
+
+    status_t initCheck() const;
+
+    bool isExtM3U() const;
+    bool isVariantPlaylist() const;
+
+    sp<AMessage> meta();
+
+    size_t size();
+    bool itemAt(size_t index, AString *uri, sp<AMessage> *meta = NULL);
+
+protected:
+    virtual ~M3UParser();
+
+private:
+    struct Item {
+        AString mURI;
+        sp<AMessage> mMeta;
+    };
+
+    status_t mInitCheck;
+
+    AString mBaseURI;
+    bool mIsExtM3U;
+    bool mIsVariantPlaylist;
+
+    sp<AMessage> mMeta;
+    Vector<Item> mItems;
+
+    status_t parse(const void *data, size_t size);
+
+    static status_t parseMetaData(
+            const AString &line, sp<AMessage> *meta, const char *key);
+
+    static status_t ParseInt32(const char *s, int32_t *x);
+
+    DISALLOW_EVIL_CONSTRUCTORS(M3UParser);
+};
+
+}  // namespace android
+
+#endif  // M3U_PARSER_H_
diff --git a/media/libstagefright/include/M4vH263Decoder.h b/media/libstagefright/include/M4vH263Decoder.h
index ec49e80..7d73e30 100644
--- a/media/libstagefright/include/M4vH263Decoder.h
+++ b/media/libstagefright/include/M4vH263Decoder.h
@@ -54,6 +54,7 @@
     MediaBuffer *mInputBuffer;
 
     int64_t mNumSamplesOutput;
+    int64_t mTargetTimeUs;
 
     void allocateFrames(int32_t width, int32_t height);
     void releaseFrames();
diff --git a/media/libstagefright/include/M4vH263Encoder.h b/media/libstagefright/include/M4vH263Encoder.h
new file mode 100644
index 0000000..dd146f4
--- /dev/null
+++ b/media/libstagefright/include/M4vH263Encoder.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 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 M4V_H263_ENCODER_H_
+
+#define M4V_H263_ENCODER_H_
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+
+struct tagvideoEncControls;
+struct tagvideoEncOptions;
+
+namespace android {
+
+struct MediaBuffer;
+struct MediaBufferGroup;
+
+struct M4vH263Encoder : public MediaSource,
+                    public MediaBufferObserver {
+    M4vH263Encoder(const sp<MediaSource> &source,
+            const sp<MetaData>& meta);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options);
+
+    virtual void signalBufferReturned(MediaBuffer *buffer);
+
+protected:
+    virtual ~M4vH263Encoder();
+
+private:
+    sp<MediaSource> mSource;
+    sp<MetaData>    mFormat;
+    sp<MetaData>    mMeta;
+
+    int32_t  mVideoWidth;
+    int32_t  mVideoHeight;
+    int32_t  mVideoFrameRate;
+    int32_t  mVideoBitRate;
+    int32_t  mVideoColorFormat;
+    int64_t  mNumInputFrames;
+    int64_t  mNextModTimeUs;
+    status_t mInitCheck;
+    bool     mStarted;
+
+    tagvideoEncControls   *mHandle;
+    tagvideoEncOptions    *mEncParams;
+    MediaBuffer           *mInputBuffer;
+    uint8_t               *mInputFrameData;
+    MediaBufferGroup      *mGroup;
+
+    status_t initCheck(const sp<MetaData>& meta);
+    void releaseOutputBuffers();
+
+    M4vH263Encoder(const M4vH263Encoder &);
+    M4vH263Encoder &operator=(const M4vH263Encoder &);
+};
+
+}  // namespace android
+
+#endif  // M4V_H263_ENCODER_H_
diff --git a/media/libstagefright/include/MP3Decoder.h b/media/libstagefright/include/MP3Decoder.h
index 88aa4c6..4086fb6 100644
--- a/media/libstagefright/include/MP3Decoder.h
+++ b/media/libstagefright/include/MP3Decoder.h
@@ -42,6 +42,9 @@
 
 private:
     sp<MediaSource> mSource;
+    sp<MetaData> mMeta;
+    int32_t mNumChannels;
+
     bool mStarted;
 
     MediaBufferGroup *mBufferGroup;
@@ -49,10 +52,12 @@
     tPVMP3DecoderExternal *mConfig;
     void *mDecoderBuf;
     int64_t mAnchorTimeUs;
-    int64_t mNumSamplesOutput;
+    int64_t mNumFramesOutput;
 
     MediaBuffer *mInputBuffer;
 
+    void init();
+
     MP3Decoder(const MP3Decoder &);
     MP3Decoder &operator=(const MP3Decoder &);
 };
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
new file mode 100644
index 0000000..c96973b
--- /dev/null
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -0,0 +1,54 @@
+#ifndef MPEG2_TS_EXTRACTOR_H_
+
+#define MPEG2_TS_EXTRACTOR_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AnotherPacketSource;
+struct ATSParser;
+struct DataSource;
+struct MPEG2TSSource;
+struct String8;
+
+struct MPEG2TSExtractor : public MediaExtractor {
+    MPEG2TSExtractor(const sp<DataSource> &source);
+
+    virtual size_t countTracks();
+    virtual sp<MediaSource> getTrack(size_t index);
+    virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+
+    virtual sp<MetaData> getMetaData();
+
+    virtual uint32_t flags() const {
+        return CAN_PAUSE;
+    }
+
+private:
+    friend struct MPEG2TSSource;
+
+    Mutex mLock;
+
+    sp<DataSource> mDataSource;
+    sp<ATSParser> mParser;
+
+    Vector<sp<AnotherPacketSource> > mSourceImpls;
+
+    off_t mOffset;
+
+    void init();
+    status_t feedMore();
+
+    DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSExtractor);
+};
+
+bool SniffMPEG2TS(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence);
+
+}  // namespace android
+
+#endif  // MPEG2_TS_EXTRACTOR_H_
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
new file mode 100644
index 0000000..3a20c16
--- /dev/null
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 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 NU_CACHED_SOURCE_2_H_
+
+#define NU_CACHED_SOURCE_2_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
+#include <media/stagefright/DataSource.h>
+
+namespace android {
+
+struct ALooper;
+struct PageCache;
+
+struct NuCachedSource2 : public DataSource {
+    NuCachedSource2(const sp<DataSource> &source);
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off_t offset, void *data, size_t size);
+
+    virtual status_t getSize(off_t *size);
+    virtual uint32_t flags();
+
+    ////////////////////////////////////////////////////////////////////////////
+
+    size_t cachedSize();
+    size_t approxDataRemaining(bool *eos);
+
+protected:
+    virtual ~NuCachedSource2();
+
+private:
+    friend struct AHandlerReflector<NuCachedSource2>;
+
+    enum {
+        kPageSize            = 65536,
+        kHighWaterThreshold  = 5 * 1024 * 1024,
+        kLowWaterThreshold   = 512 * 1024,
+
+        // Read data after a 15 sec timeout whether we're actively
+        // fetching or not.
+        kKeepAliveIntervalUs = 15000000,
+    };
+
+    enum {
+        kWhatFetchMore  = 'fetc',
+        kWhatRead       = 'read',
+    };
+
+    sp<DataSource> mSource;
+    sp<AHandlerReflector<NuCachedSource2> > mReflector;
+    sp<ALooper> mLooper;
+
+    Mutex mSerializer;
+    Mutex mLock;
+    Condition mCondition;
+
+    PageCache *mCache;
+    off_t mCacheOffset;
+    status_t mFinalStatus;
+    off_t mLastAccessPos;
+    sp<AMessage> mAsyncResult;
+    bool mFetching;
+    int64_t mLastFetchTimeUs;
+
+    void onMessageReceived(const sp<AMessage> &msg);
+    void onFetch();
+    void onRead(const sp<AMessage> &msg);
+
+    void fetchInternal();
+    ssize_t readInternal(off_t offset, void *data, size_t size);
+    status_t seekInternal_l(off_t offset);
+
+    size_t approxDataRemaining_l(bool *eos);
+    void restartPrefetcherIfNecessary_l();
+
+    DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2);
+};
+
+}  // namespace android
+
+#endif  // NU_CACHED_SOURCE_2_H_
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
new file mode 100644
index 0000000..8593a91
--- /dev/null
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -0,0 +1,73 @@
+#ifndef NU_HTTP_DATA_SOURCE_H_
+
+#define NU_HTTP_DATA_SOURCE_H_
+
+#include <media/stagefright/DataSource.h>
+#include <utils/String8.h>
+#include <utils/threads.h>
+
+#include "HTTPStream.h"
+
+namespace android {
+
+struct NuHTTPDataSource : public DataSource {
+    NuHTTPDataSource();
+
+    status_t connect(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers = NULL,
+            off_t offset = 0);
+
+    void disconnect();
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off_t offset, void *data, size_t size);
+    virtual status_t getSize(off_t *size);
+    virtual uint32_t flags();
+
+protected:
+    virtual ~NuHTTPDataSource();
+
+private:
+    enum State {
+        DISCONNECTED,
+        CONNECTING,
+        CONNECTED
+    };
+
+    Mutex mLock;
+
+    State mState;
+
+    String8 mHost;
+    unsigned mPort;
+    String8 mPath;
+    String8 mHeaders;
+
+    HTTPStream mHTTP;
+    off_t mOffset;
+    off_t mContentLength;
+    bool mContentLengthValid;
+
+    status_t connect(
+            const char *uri, const String8 &headers, off_t offset);
+
+    status_t connect(
+            const char *host, unsigned port, const char *path,
+            const String8 &headers,
+            off_t offset);
+
+    void applyTimeoutResponse();
+
+    static void MakeFullHeaders(
+            const KeyedVector<String8, String8> *overrides,
+            String8 *headers);
+
+    NuHTTPDataSource(const NuHTTPDataSource &);
+    NuHTTPDataSource &operator=(const NuHTTPDataSource &);
+};
+
+}  // namespace android
+
+#endif  // NU_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index ea131e8..c99da59 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -102,7 +102,7 @@
             OMX_IN OMX_U32 nData1,
             OMX_IN OMX_U32 nData2,
             OMX_IN OMX_PTR pEventData);
-        
+
     OMX_ERRORTYPE OnEmptyBufferDone(
             node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
 
@@ -115,20 +115,19 @@
     virtual ~OMX();
 
 private:
-    Mutex mLock;
-
-    OMXMaster *mMaster;
-
     struct CallbackDispatcher;
-    sp<CallbackDispatcher> mDispatcher;
 
+    Mutex mLock;
+    OMXMaster *mMaster;
     int32_t mNodeCounter;
 
     KeyedVector<wp<IBinder>, OMXNodeInstance *> mLiveNodes;
     KeyedVector<node_id, OMXNodeInstance *> mNodeIDToInstance;
+    KeyedVector<node_id, sp<CallbackDispatcher> > mDispatchers;
 
     node_id makeNodeID(OMXNodeInstance *instance);
     OMXNodeInstance *findInstance(node_id node);
+    sp<CallbackDispatcher> findDispatcher(node_id node);
 
     void invalidateNodeID_l(node_id node);
 
diff --git a/media/libstagefright/include/Prefetcher.h b/media/libstagefright/include/Prefetcher.h
deleted file mode 100644
index b411d1b..0000000
--- a/media/libstagefright/include/Prefetcher.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 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 PREFETCHER_H_
-
-#define PREFETCHER_H_
-
-#include <utils/RefBase.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-struct MediaSource;
-struct PrefetchedSource;
-
-struct Prefetcher : public RefBase {
-    Prefetcher();
-
-    // Given an existing MediaSource returns a new MediaSource
-    // that will benefit from prefetching/caching the original one.
-    sp<MediaSource> addSource(const sp<MediaSource> &source);
-
-    int64_t getCachedDurationUs(bool *noMoreData = NULL);
-
-    // If provided (non-NULL), "continueFunc" will be called repeatedly
-    // while preparing and preparation will finish early if it returns
-    // false. In this case "-EINTR" is returned as a result.
-    status_t prepare(
-            bool (*continueFunc)(void *cookie) = NULL,
-            void *cookie = NULL);
-
-protected:
-    virtual ~Prefetcher();
-
-private:
-    Mutex mLock;
-    Condition mCondition;
-
-    Vector<wp<PrefetchedSource> > mSources;
-    android_thread_id_t mThread;
-    bool mDone;
-    bool mThreadExited;
-
-    void startThread();
-    void stopThread();
-
-    static int ThreadWrapper(void *me);
-    void threadFunc();
-
-    Prefetcher(const Prefetcher &);
-    Prefetcher &operator=(const Prefetcher &);
-};
-
-}  // namespace android
-
-#endif  // PREFETCHER_H_
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 533ce84..a2b2c99 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -63,11 +63,17 @@
             uint32_t *decodingTime);
 
     enum {
-        kSyncSample_Flag = 1
+        kFlagBefore,
+        kFlagAfter,
+        kFlagClosest
     };
-    status_t findClosestSample(
+    status_t findSampleAtTime(
             uint32_t req_time, uint32_t *sample_index, uint32_t flags);
 
+    status_t findSyncSampleNear(
+            uint32_t start_sample_index, uint32_t *sample_index,
+            uint32_t flags);
+
     status_t findThumbnailSample(uint32_t *sample_index);
 
 protected:
@@ -111,9 +117,6 @@
 
     friend struct SampleIterator;
 
-    status_t findClosestSyncSample_l(
-            uint32_t start_sample_index, uint32_t *sample_index);
-
     status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
 
     SampleTable(const SampleTable &);
diff --git a/media/libstagefright/include/ThrottledSource.h b/media/libstagefright/include/ThrottledSource.h
new file mode 100644
index 0000000..88164b3
--- /dev/null
+++ b/media/libstagefright/include/ThrottledSource.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 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 THROTTLED_SOURCE_H_
+
+#define THROTTLED_SOURCE_H_
+
+#include <media/stagefright/DataSource.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct ThrottledSource : public DataSource {
+    ThrottledSource(
+            const sp<DataSource> &source,
+            int32_t bandwidthLimitBytesPerSecond);
+
+    virtual status_t initCheck() const;
+
+    virtual ssize_t readAt(off_t offset, void *data, size_t size);
+
+    virtual status_t getSize(off_t *size);
+    virtual uint32_t flags();
+
+private:
+    Mutex mLock;
+
+    sp<DataSource> mSource;
+    int32_t mBandwidthLimitBytesPerSecond;
+    int64_t mStartTimeUs;
+    size_t mTotalTransferred;
+
+    ThrottledSource(const ThrottledSource &);
+    ThrottledSource &operator=(const ThrottledSource &);
+};
+
+}  // namespace android
+
+#endif  // THROTTLED_SOURCE_H_
diff --git a/media/libstagefright/include/VPXDecoder.h b/media/libstagefright/include/VPXDecoder.h
new file mode 100644
index 0000000..3b8362d
--- /dev/null
+++ b/media/libstagefright/include/VPXDecoder.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 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 VPX_DECODER_H_
+
+#define VPX_DECODER_H_
+
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct MediaBufferGroup;
+
+struct VPXDecoder : public MediaSource {
+    VPXDecoder(const sp<MediaSource> &source);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options);
+
+protected:
+    virtual ~VPXDecoder();
+
+private:
+    sp<MediaSource> mSource;
+    bool mStarted;
+    int32_t mWidth, mHeight;
+    size_t mBufferSize;
+
+    void *mCtx;
+    MediaBufferGroup *mBufferGroup;
+
+    int64_t mTargetTimeUs;
+
+    sp<MetaData> mFormat;
+
+    VPXDecoder(const VPXDecoder &);
+    VPXDecoder &operator=(const VPXDecoder &);
+};
+
+}  // namespace android
+
+#endif  // VPX_DECODER_H_
+
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
new file mode 100644
index 0000000..0e72198
--- /dev/null
+++ b/media/libstagefright/matroska/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=                 \
+        MatroskaExtractor.cpp     \
+        mkvparser.cpp             \
+
+LOCAL_C_INCLUDES:= \
+	$(JNI_H_INCLUDE) \
+        $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= libstagefright_matroska
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
new file mode 100644
index 0000000..3739be1
--- /dev/null
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -0,0 +1,595 @@
+/*
+ * Copyright (C) 2010 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 "MatroskaExtractor"
+#include <utils/Log.h>
+
+#include "MatroskaExtractor.h"
+
+#include "mkvparser.hpp"
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct DataSourceReader : public mkvparser::IMkvReader {
+    DataSourceReader(const sp<DataSource> &source)
+        : mSource(source) {
+    }
+
+    virtual int Read(long long position, long length, unsigned char* buffer) {
+        CHECK(position >= 0);
+        CHECK(length >= 0);
+
+        if (length == 0) {
+            return 0;
+        }
+
+        ssize_t n = mSource->readAt(position, buffer, length);
+
+        if (n <= 0) {
+            return -1;
+        }
+
+        return 0;
+    }
+
+    virtual int Length(long long* total, long long* available) {
+        off_t size;
+        if (mSource->getSize(&size) != OK) {
+            return -1;
+        }
+
+        if (total) {
+            *total = size;
+        }
+
+        if (available) {
+            *available = size;
+        }
+
+        return 0;
+    }
+
+private:
+    sp<DataSource> mSource;
+
+    DataSourceReader(const DataSourceReader &);
+    DataSourceReader &operator=(const DataSourceReader &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#include <ctype.h>
+static void hexdump(const void *_data, size_t size) {
+    const uint8_t *data = (const uint8_t *)_data;
+    size_t offset = 0;
+    while (offset < size) {
+        printf("0x%04x  ", offset);
+
+        size_t n = size - offset;
+        if (n > 16) {
+            n = 16;
+        }
+
+        for (size_t i = 0; i < 16; ++i) {
+            if (i == 8) {
+                printf(" ");
+            }
+
+            if (offset + i < size) {
+                printf("%02x ", data[offset + i]);
+            } else {
+                printf("   ");
+            }
+        }
+
+        printf(" ");
+
+        for (size_t i = 0; i < n; ++i) {
+            if (isprint(data[offset + i])) {
+                printf("%c", data[offset + i]);
+            } else {
+                printf(".");
+            }
+        }
+
+        printf("\n");
+
+        offset += 16;
+    }
+}
+
+struct BlockIterator {
+    BlockIterator(mkvparser::Segment *segment, unsigned long trackNum);
+
+    bool eos() const;
+
+    void advance();
+    void reset();
+    void seek(int64_t seekTimeUs);
+
+    const mkvparser::Block *block() const;
+    int64_t blockTimeUs() const;
+
+private:
+    mkvparser::Segment *mSegment;
+    unsigned long mTrackNum;
+
+    mkvparser::Cluster *mCluster;
+    const mkvparser::BlockEntry *mBlockEntry;
+
+    BlockIterator(const BlockIterator &);
+    BlockIterator &operator=(const BlockIterator &);
+};
+
+struct MatroskaSource : public MediaSource {
+    MatroskaSource(
+            const sp<MatroskaExtractor> &extractor, size_t index);
+
+    virtual status_t start(MetaData *params);
+    virtual status_t stop();
+
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options);
+
+private:
+    enum Type {
+        AVC,
+        AAC,
+        OTHER
+    };
+
+    sp<MatroskaExtractor> mExtractor;
+    size_t mTrackIndex;
+    Type mType;
+    BlockIterator mBlockIter;
+
+    status_t advance();
+
+    MatroskaSource(const MatroskaSource &);
+    MatroskaSource &operator=(const MatroskaSource &);
+};
+
+MatroskaSource::MatroskaSource(
+        const sp<MatroskaExtractor> &extractor, size_t index)
+    : mExtractor(extractor),
+      mTrackIndex(index),
+      mType(OTHER),
+      mBlockIter(mExtractor->mSegment,
+                 mExtractor->mTracks.itemAt(index).mTrackNum) {
+    const char *mime;
+    CHECK(mExtractor->mTracks.itemAt(index).mMeta->
+            findCString(kKeyMIMEType, &mime));
+
+    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+        mType = AVC;
+    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+        mType = AAC;
+    }
+}
+
+status_t MatroskaSource::start(MetaData *params) {
+    mBlockIter.reset();
+
+    return OK;
+}
+
+status_t MatroskaSource::stop() {
+    return OK;
+}
+
+sp<MetaData> MatroskaSource::getFormat() {
+    return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+BlockIterator::BlockIterator(
+        mkvparser::Segment *segment, unsigned long trackNum)
+    : mSegment(segment),
+      mTrackNum(trackNum),
+      mCluster(NULL),
+      mBlockEntry(NULL) {
+    reset();
+}
+
+bool BlockIterator::eos() const {
+    return mCluster == NULL || mCluster->EOS();
+}
+
+void BlockIterator::advance() {
+    while (!eos()) {
+        if (mBlockEntry != NULL) {
+            mBlockEntry = mCluster->GetNext(mBlockEntry);
+        } else if (mCluster != NULL) {
+            mCluster = mSegment->GetNext(mCluster);
+
+            if (eos()) {
+                break;
+            }
+
+            mBlockEntry = mCluster->GetFirst();
+        }
+
+        if (mBlockEntry != NULL
+                && mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
+            break;
+        }
+    }
+}
+
+void BlockIterator::reset() {
+    mCluster = mSegment->GetFirst();
+    mBlockEntry = mCluster->GetFirst();
+
+    while (!eos() && block()->GetTrackNumber() != mTrackNum) {
+        advance();
+    }
+}
+
+void BlockIterator::seek(int64_t seekTimeUs) {
+    mCluster = mSegment->GetCluster(seekTimeUs * 1000ll);
+    mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL;
+
+    while (!eos() && block()->GetTrackNumber() != mTrackNum) {
+        advance();
+    }
+
+    while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
+        advance();
+    }
+}
+
+const mkvparser::Block *BlockIterator::block() const {
+    CHECK(!eos());
+
+    return mBlockEntry->GetBlock();
+}
+
+int64_t BlockIterator::blockTimeUs() const {
+    return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+status_t MatroskaSource::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    *out = NULL;
+
+    int64_t seekTimeUs;
+    ReadOptions::SeekMode mode;
+    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+        mBlockIter.seek(seekTimeUs);
+    }
+
+    if (mBlockIter.eos()) {
+        return ERROR_END_OF_STREAM;
+    }
+
+    const mkvparser::Block *block = mBlockIter.block();
+    size_t size = block->GetSize();
+    int64_t timeUs = mBlockIter.blockTimeUs();
+
+    MediaBuffer *buffer = new MediaBuffer(size + 2);
+    buffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+    long res = block->Read(
+            mExtractor->mReader, (unsigned char *)buffer->data() + 2);
+
+    if (res != 0) {
+        return ERROR_END_OF_STREAM;
+    }
+
+    buffer->set_range(2, size);
+
+    if (mType == AVC) {
+        CHECK(size >= 2);
+
+        uint8_t *data = (uint8_t *)buffer->data();
+
+        unsigned NALsize = data[2] << 8 | data[3];
+        CHECK_EQ(size, NALsize + 2);
+
+        memcpy(data, "\x00\x00\x00\x01", 4);
+        buffer->set_range(0, size + 2);
+    } else if (mType == AAC) {
+        // There's strange junk at the beginning...
+
+        const uint8_t *data = (const uint8_t *)buffer->data() + 2;
+        size_t offset = 0;
+        while (offset < size && data[offset] != 0x21) {
+            ++offset;
+        }
+        buffer->set_range(2 + offset, size - offset);
+    }
+
+    *out = buffer;
+
+#if 0
+    hexdump((const uint8_t *)buffer->data() + buffer->range_offset(),
+            buffer->range_length());
+#endif
+
+    mBlockIter.advance();
+
+    return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
+    : mDataSource(source),
+      mReader(new DataSourceReader(mDataSource)),
+      mSegment(NULL),
+      mExtractedThumbnails(false) {
+    mkvparser::EBMLHeader ebmlHeader;
+    long long pos;
+    if (ebmlHeader.Parse(mReader, pos) < 0) {
+        return;
+    }
+
+    long long ret =
+        mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
+
+    if (ret) {
+        CHECK(mSegment == NULL);
+        return;
+    }
+
+    ret = mSegment->Load();
+
+    if (ret < 0) {
+        delete mSegment;
+        mSegment = NULL;
+        return;
+    }
+
+    addTracks();
+}
+
+MatroskaExtractor::~MatroskaExtractor() {
+    delete mSegment;
+    mSegment = NULL;
+
+    delete mReader;
+    mReader = NULL;
+}
+
+size_t MatroskaExtractor::countTracks() {
+    return mTracks.size();
+}
+
+sp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
+    if (index >= mTracks.size()) {
+        return NULL;
+    }
+
+    return new MatroskaSource(this, index);
+}
+
+sp<MetaData> MatroskaExtractor::getTrackMetaData(
+        size_t index, uint32_t flags) {
+    if (index >= mTracks.size()) {
+        return NULL;
+    }
+
+    if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails) {
+        findThumbnails();
+        mExtractedThumbnails = true;
+    }
+
+    return mTracks.itemAt(index).mMeta;
+}
+
+static void addESDSFromAudioSpecificInfo(
+        const sp<MetaData> &meta, const void *asi, size_t asiSize) {
+    static const uint8_t kStaticESDS[] = {
+        0x03, 22,
+        0x00, 0x00,     // ES_ID
+        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+        0x04, 17,
+        0x40,                       // Audio ISO/IEC 14496-3
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+
+        0x05,
+        // AudioSpecificInfo (with size prefix) follows
+    };
+
+    CHECK(asiSize < 128);
+    size_t esdsSize = sizeof(kStaticESDS) + asiSize + 1;
+    uint8_t *esds = new uint8_t[esdsSize];
+    memcpy(esds, kStaticESDS, sizeof(kStaticESDS));
+    uint8_t *ptr = esds + sizeof(kStaticESDS);
+    *ptr++ = asiSize;
+    memcpy(ptr, asi, asiSize);
+
+    meta->setData(kKeyESDS, 0, esds, esdsSize);
+
+    delete[] esds;
+    esds = NULL;
+}
+
+void addVorbisCodecInfo(
+        const sp<MetaData> &meta,
+        const void *_codecPrivate, size_t codecPrivateSize) {
+    // printf("vorbis private data follows:\n");
+    // hexdump(_codecPrivate, codecPrivateSize);
+
+    CHECK(codecPrivateSize >= 3);
+
+    const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
+    CHECK(codecPrivate[0] == 0x02);
+
+    size_t len1 = codecPrivate[1];
+    size_t len2 = codecPrivate[2];
+
+    CHECK(codecPrivateSize > 3 + len1 + len2);
+
+    CHECK(codecPrivate[3] == 0x01);
+    meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1);
+
+    CHECK(codecPrivate[len1 + 3] == 0x03);
+
+    CHECK(codecPrivate[len1 + len2 + 3] == 0x05);
+    meta->setData(
+            kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3],
+            codecPrivateSize - len1 - len2 - 3);
+}
+
+void MatroskaExtractor::addTracks() {
+    const mkvparser::Tracks *tracks = mSegment->GetTracks();
+
+    for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
+        const mkvparser::Track *track = tracks->GetTrackByIndex(index);
+
+        const char *const codecID = track->GetCodecId();
+        LOGV("codec id = %s", codecID);
+        LOGV("codec name = %s", track->GetCodecNameAsUTF8());
+
+        size_t codecPrivateSize;
+        const unsigned char *codecPrivate =
+            track->GetCodecPrivate(&codecPrivateSize);
+
+        enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
+
+        sp<MetaData> meta = new MetaData;
+
+        switch (track->GetType()) {
+            case VIDEO_TRACK:
+            {
+                const mkvparser::VideoTrack *vtrack =
+                    static_cast<const mkvparser::VideoTrack *>(track);
+
+                if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
+                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+                    meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
+                } else if (!strcmp("V_VP8", codecID)) {
+                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX);
+                } else {
+                    continue;
+                }
+
+                meta->setInt32(kKeyWidth, vtrack->GetWidth());
+                meta->setInt32(kKeyHeight, vtrack->GetHeight());
+                break;
+            }
+
+            case AUDIO_TRACK:
+            {
+                const mkvparser::AudioTrack *atrack =
+                    static_cast<const mkvparser::AudioTrack *>(track);
+
+                if (!strcmp("A_AAC", codecID)) {
+                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+                    CHECK(codecPrivateSize >= 2);
+
+                    addESDSFromAudioSpecificInfo(
+                            meta, codecPrivate, codecPrivateSize);
+                } else if (!strcmp("A_VORBIS", codecID)) {
+                    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+
+                    addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize);
+                } else {
+                    continue;
+                }
+
+                meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
+                meta->setInt32(kKeyChannelCount, atrack->GetChannels());
+                break;
+            }
+
+            default:
+                continue;
+        }
+
+        long long durationNs = mSegment->GetDuration();
+        meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
+
+        mTracks.push();
+        TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
+        trackInfo->mTrackNum = track->GetNumber();
+        trackInfo->mMeta = meta;
+    }
+}
+
+void MatroskaExtractor::findThumbnails() {
+    for (size_t i = 0; i < mTracks.size(); ++i) {
+        TrackInfo *info = &mTracks.editItemAt(i);
+
+        const char *mime;
+        CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
+
+        if (strncasecmp(mime, "video/", 6)) {
+            continue;
+        }
+
+        BlockIterator iter(mSegment, info->mTrackNum);
+        int32_t i = 0;
+        int64_t thumbnailTimeUs = 0;
+        size_t maxBlockSize = 0;
+        while (!iter.eos() && i < 20) {
+            if (iter.block()->IsKey()) {
+                ++i;
+
+                size_t blockSize = iter.block()->GetSize();
+                if (blockSize > maxBlockSize) {
+                    maxBlockSize = blockSize;
+                    thumbnailTimeUs = iter.blockTimeUs();
+                }
+            }
+            iter.advance();
+        }
+        info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
+    }
+}
+
+sp<MetaData> MatroskaExtractor::getMetaData() {
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MATROSKA);
+
+    return meta;
+}
+
+bool SniffMatroska(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+    DataSourceReader reader(source);
+    mkvparser::EBMLHeader ebmlHeader;
+    long long pos;
+    if (ebmlHeader.Parse(&reader, pos) < 0) {
+        return false;
+    }
+
+    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
+    *confidence = 0.6;
+
+    return true;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
new file mode 100644
index 0000000..7471848
--- /dev/null
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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 MATROSKA_EXTRACTOR_H_
+
+#define MATROSKA_EXTRACTOR_H_
+
+#include <media/stagefright/MediaExtractor.h>
+#include <utils/Vector.h>
+
+namespace mkvparser {
+struct Segment;
+};
+
+namespace android {
+
+class String8;
+
+struct DataSourceReader;
+struct MatroskaSource;
+
+struct MatroskaExtractor : public MediaExtractor {
+    MatroskaExtractor(const sp<DataSource> &source);
+
+    virtual size_t countTracks();
+
+    virtual sp<MediaSource> getTrack(size_t index);
+
+    virtual sp<MetaData> getTrackMetaData(
+            size_t index, uint32_t flags);
+
+    virtual sp<MetaData> getMetaData();
+
+protected:
+    virtual ~MatroskaExtractor();
+
+private:
+    friend struct MatroskaSource;
+
+    struct TrackInfo {
+        unsigned long mTrackNum;
+        sp<MetaData> mMeta;
+    };
+    Vector<TrackInfo> mTracks;
+
+    sp<DataSource> mDataSource;
+    DataSourceReader *mReader;
+    mkvparser::Segment *mSegment;
+    bool mExtractedThumbnails;
+
+    void addTracks();
+    void findThumbnails();
+
+    MatroskaExtractor(const MatroskaExtractor &);
+    MatroskaExtractor &operator=(const MatroskaExtractor &);
+};
+
+bool SniffMatroska(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence);
+
+}  // namespace android
+
+#endif  // MATROSKA_EXTRACTOR_H_
diff --git a/media/libstagefright/matroska/mkvparser.cpp b/media/libstagefright/matroska/mkvparser.cpp
new file mode 100644
index 0000000..4e51004
--- /dev/null
+++ b/media/libstagefright/matroska/mkvparser.cpp
@@ -0,0 +1,3103 @@
+#include "mkvparser.hpp"
+#include <cassert>
+#include <cstring>
+
+mkvparser::IMkvReader::~IMkvReader()
+{
+}
+
+long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(pos < available);
+    assert((available - pos) >= 1);  //assume here max u-int len is 8
+    
+    unsigned char b;
+
+    hr = pReader->Read(pos, 1, &b);
+    if (hr < 0)
+        return hr;
+        
+    assert(hr == 0L);
+    
+    if (b & 0x80)       //1000 0000
+    {
+        len = 1;
+        b &= 0x7F;      //0111 1111
+    }        
+    else if (b & 0x40)  //0100 0000
+    {
+        len = 2;
+        b &= 0x3F;      //0011 1111
+    }
+    else if (b & 0x20)  //0010 0000
+    {
+        len = 3;
+        b &= 0x1F;      //0001 1111
+    }
+    else if (b & 0x10)  //0001 0000
+    {
+        len = 4;
+        b &= 0x0F;      //0000 1111
+    }
+    else if (b & 0x08)  //0000 1000
+    {
+        len = 5;
+        b &= 0x07;      //0000 0111
+    }
+    else if (b & 0x04)  //0000 0100
+    {
+        len = 6;
+        b &= 0x03;      //0000 0011
+    }
+    else if (b & 0x02)  //0000 0010
+    {
+        len = 7;
+        b &= 0x01;      //0000 0001
+    }
+    else 
+    {
+        assert(b & 0x01);  //0000 0001
+        len = 8;
+        b = 0;             //0000 0000
+    }
+    
+    assert((available - pos) >= len);
+    
+    long long result = b;
+    ++pos;
+    for (long i = 1; i < len; ++i)
+    {
+        hr = pReader->Read(pos, 1, &b);
+        
+        if (hr < 0)
+            return hr;
+            
+        assert(hr == 0L);
+        
+        result <<= 8;
+        result |= b;
+        
+        ++pos;
+    }
+    
+    return result;
+}
+    
+    
+long long mkvparser::GetUIntLength(
+    IMkvReader* pReader,
+    long long pos, 
+    long& len)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    
+    if (pos >= available)
+        return pos;  //too few bytes available
+    
+    unsigned char b;
+    
+    hr = pReader->Read(pos, 1, &b);
+    
+    if (hr < 0)
+        return hr;
+
+    assert(hr == 0L);
+    
+    if (b == 0)  //we can't handle u-int values larger than 8 bytes
+        return E_FILE_FORMAT_INVALID;
+    
+    unsigned char m = 0x80;
+    len = 1;
+    
+    while (!(b & m))
+    {
+        m >>= 1;
+        ++len;
+    }
+    
+    return 0;  //success
+}
+
+
+long long mkvparser::SyncReadUInt(
+    IMkvReader* pReader,
+    long long pos, 
+    long long stop,
+    long& len)
+{
+    assert(pReader);
+
+    if (pos >= stop)
+        return E_FILE_FORMAT_INVALID;
+    
+    unsigned char b;
+    
+    long hr = pReader->Read(pos, 1, &b);
+    
+    if (hr < 0)
+        return hr;
+        
+    if (hr != 0L)
+        return E_BUFFER_NOT_FULL;
+
+    if (b == 0)  //we can't handle u-int values larger than 8 bytes
+        return E_FILE_FORMAT_INVALID;
+    
+    unsigned char m = 0x80;
+    len = 1;
+        
+    while (!(b & m))
+    {
+        m >>= 1;
+        ++len;
+    }
+    
+    if ((pos + len) > stop)
+        return E_FILE_FORMAT_INVALID;
+        
+    long long result = b & (~m);
+    ++pos;
+    
+    for (int i = 1; i < len; ++i)
+    {
+        hr = pReader->Read(pos, 1, &b);
+        
+        if (hr < 0)
+            return hr;
+           
+        if (hr != 0L)
+            return E_BUFFER_NOT_FULL;
+            
+        result <<= 8;
+        result |= b;
+        
+        ++pos;
+    }
+    
+    return result;
+}
+
+
+long long mkvparser::UnserializeUInt(
+    IMkvReader* pReader, 
+    long long pos,
+    long long size)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    assert(size > 0);
+    assert(size <= 8);
+    
+    long long result = 0;
+    
+    for (long long i = 0; i < size; ++i)
+    {
+        unsigned char b;
+        
+        const long hr = pReader->Read(pos, 1, &b);
+        
+        if (hr < 0)      
+            return hr;
+        result <<= 8;
+        result |= b;
+        
+        ++pos;
+    }
+    
+    return result;
+}
+
+
+float mkvparser::Unserialize4Float(
+    IMkvReader* pReader, 
+    long long pos)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+    
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    assert((pos + 4) <= available);
+    
+    float result;
+    
+    unsigned char* const p = (unsigned char*)&result;
+    unsigned char* q = p + 4;
+    
+    for (;;)
+    {
+        hr = pReader->Read(pos, 1, --q);
+        assert(hr == 0L);
+        
+        if (q == p)
+            break;
+            
+        ++pos;
+    }
+    
+    return result;
+}
+
+
+double mkvparser::Unserialize8Double(
+    IMkvReader* pReader, 
+    long long pos)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    double result;
+    
+    unsigned char* const p = (unsigned char*)&result;
+    unsigned char* q = p + 8;
+    
+    for (;;)
+    {
+        const long hr = pReader->Read(pos, 1, --q);
+        assert(hr == 0L);
+        
+        if (q == p)
+            break;
+            
+        ++pos;
+    }
+    
+    return result;
+}
+
+signed char mkvparser::Unserialize1SInt(
+    IMkvReader* pReader,
+    long long pos)
+{
+    assert(pReader);
+    assert(pos >= 0);
+ 
+    long long total, available;
+
+    long hr = pReader->Length(&total, &available);
+    assert(hr == 0);   
+    assert(available <= total);
+    assert(pos < available);
+
+    signed char result;
+
+    hr = pReader->Read(pos, 1, (unsigned char*)&result);
+    assert(hr == 0);
+
+    return result;
+}
+
+short mkvparser::Unserialize2SInt(
+    IMkvReader* pReader, 
+    long long pos)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+    
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    assert((pos + 2) <= available);
+    
+    short result;
+    
+    unsigned char* const p = (unsigned char*)&result;
+    unsigned char* q = p + 2;
+    
+    for (;;)
+    {
+        hr = pReader->Read(pos, 1, --q);
+        assert(hr == 0L);
+        
+        if (q == p)
+            break;
+            
+        ++pos;
+    }
+    
+    return result;
+}
+
+
+bool mkvparser::Match(
+    IMkvReader* pReader,
+    long long& pos,
+    unsigned long id_,
+    long long& val)
+
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    
+    long len;
+
+    const long long id = ReadUInt(pReader, pos, len);
+    assert(id >= 0);
+    assert(len > 0);
+    assert(len <= 8);
+    assert((pos + len) <= available);
+    
+    if ((unsigned long)id != id_)
+        return false;
+        
+    pos += len;  //consume id
+    
+    const long long size = ReadUInt(pReader, pos, len);
+    assert(size >= 0);
+    assert(size <= 8);
+    assert(len > 0);
+    assert(len <= 8);
+    assert((pos + len) <= available);
+    
+    pos += len;  //consume length of size of payload
+    
+    val = UnserializeUInt(pReader, pos, size);
+    assert(val >= 0);
+    
+    pos += size;  //consume size of payload
+    
+    return true;
+}
+
+bool mkvparser::Match(
+    IMkvReader* pReader,
+    long long& pos,
+    unsigned long id_,
+    char*& val)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    
+    long len;
+
+    const long long id = ReadUInt(pReader, pos, len);
+    assert(id >= 0);
+    assert(len > 0);
+    assert(len <= 8);
+    assert((pos + len) <= available);
+    
+    if ((unsigned long)id != id_)
+        return false;
+    
+    pos += len;  //consume id
+    
+    const long long size_ = ReadUInt(pReader, pos, len);
+    assert(size_ >= 0);
+    assert(len > 0);
+    assert(len <= 8);
+    assert((pos + len) <= available);
+    
+    pos += len;  //consume length of size of payload
+    assert((pos + size_) <= available);
+
+    const size_t size = static_cast<size_t>(size_);    
+    val = new char[size+1];
+
+    for (size_t i = 0; i < size; ++i)
+    {
+        char c;
+
+        hr = pReader->Read(pos + i, 1, (unsigned char*)&c);
+        assert(hr == 0L);
+            
+        val[i] = c;
+   
+        if (c == '\0')
+            break;     
+   
+    }
+
+    val[size] = '\0';
+    pos += size_;  //consume size of payload
+    
+    return true;
+}
+
+#if 0
+bool mkvparser::Match(
+    IMkvReader* pReader,
+    long long& pos,
+    unsigned long id,
+    wchar_t*& val)
+{
+    char* str;
+    
+    if (!Match(pReader, pos, id, str))
+        return false;
+
+    const size_t size = mbstowcs(NULL, str, 0);
+       
+    if (size == 0) 
+        val = NULL;
+    else 
+    { 
+        val = new wchar_t[size+1];
+        mbstowcs(val, str, size);
+        val[size] = L'\0';
+    }
+
+    delete[] str;
+    return true;    
+}
+#endif
+
+
+bool mkvparser::Match(
+    IMkvReader* pReader,
+    long long& pos,
+    unsigned long id_,
+    unsigned char*& val,
+    size_t *optionalSize)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    
+    long len;
+    const long long id = ReadUInt(pReader, pos, len);
+    assert(id >= 0);
+    assert(len > 0);
+    assert(len <= 8);
+    assert((pos + len) <= available);
+    
+    if ((unsigned long)id != id_)
+        return false;
+        
+    pos += len;  //consume id
+    
+    const long long size_ = ReadUInt(pReader, pos, len);
+    assert(size_ >= 0);
+    assert(len > 0);
+    assert(len <= 8);
+    assert((pos + len) <= available);
+    
+    pos += len;  //consume length of size of payload
+    assert((pos + size_) <= available);
+
+    const size_t size = static_cast<size_t>(size_);    
+    val = new unsigned char[size];
+ 
+    if (optionalSize) {
+        *optionalSize = size;
+    }
+
+    for (size_t i = 0; i < size; ++i)
+    {
+        unsigned char b;
+
+        hr = pReader->Read(pos + i, 1, &b);
+        assert(hr == 0L);
+
+        val[i] = b; 
+    }
+    
+    pos += size_;  //consume size of payload    
+    return true;
+}
+
+
+bool mkvparser::Match(
+    IMkvReader* pReader,
+    long long& pos,
+    unsigned long id_,
+    double& val)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    long idlen;
+    const long long id = ReadUInt(pReader, pos, idlen);
+    assert(id >= 0);  //TODO
+    
+    if ((unsigned long)id != id_)
+        return false;
+
+    long sizelen;
+    const long long size = ReadUInt(pReader, pos + idlen, sizelen);
+
+    switch (size)
+    {	
+        case 4:
+        case 8:
+            break;
+        default:
+            return false;
+    }
+
+    pos += idlen + sizelen;  //consume id and size fields
+    assert((pos + size) <= available);
+
+    if (size == 4)
+        val = Unserialize4Float(pReader, pos);
+    else
+    {
+        assert(size == 8);
+        val = Unserialize8Double(pReader, pos);
+    }
+    
+    pos += size;  //consume size of payload
+    
+    return true;
+}
+
+
+bool mkvparser::Match(
+    IMkvReader* pReader,
+    long long& pos,
+    unsigned long id_,
+    short& val)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    long long total, available;
+
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    
+    long len;
+    const long long id = ReadUInt(pReader, pos, len);
+    assert(id >= 0);
+    assert((pos + len) <= available);
+    
+    if ((unsigned long)id != id_)
+        return false;
+        
+    pos += len;  //consume id
+    
+    const long long size = ReadUInt(pReader, pos, len);
+    assert(size <= 2);
+    assert((pos + len) <= available);
+   
+    pos += len;  //consume length of size of payload
+    assert((pos + size) <= available);
+
+    //TODO:
+    // Generalize this to work for any size signed int
+    if (size == 1)
+        val = Unserialize1SInt(pReader, pos);
+    else 
+        val = Unserialize2SInt(pReader, pos);
+        
+    pos += size;  //consume size of payload
+    
+    return true;
+}
+
+
+namespace mkvparser
+{
+
+EBMLHeader::EBMLHeader():
+    m_docType(NULL)
+{
+}
+
+EBMLHeader::~EBMLHeader()
+{
+    delete[] m_docType;
+}
+
+long long EBMLHeader::Parse(
+    IMkvReader* pReader,
+    long long& pos)
+{
+    assert(pReader);
+    
+    long long total, available;
+    
+    long hr = pReader->Length(&total, &available);
+    
+    if (hr < 0) 
+        return hr;
+    
+    pos = 0;    
+    long long end = (1024 < available)? 1024: available;    
+
+    for (;;)
+    {    
+        unsigned char b = 0;
+    
+        while (pos < end)
+        {
+            hr = pReader->Read(pos, 1, &b);
+           
+            if (hr < 0)
+                return hr;
+            
+            if (b == 0x1A)
+                break;
+                
+            ++pos;
+        }
+    
+        if (b != 0x1A)
+        {
+            if ((pos >= 1024) ||
+                (available >= total) || 
+                ((total - available) < 5))
+                  return -1;
+                
+            return available + 5;  //5 = 4-byte ID + 1st byte of size
+        }
+    
+        if ((total - pos) < 5)
+            return E_FILE_FORMAT_INVALID;
+            
+        if ((available - pos) < 5)
+            return pos + 5;  //try again later
+
+        long len;            
+
+        const long long result = ReadUInt(pReader, pos, len);
+        
+        if (result < 0)  //error
+            return result;
+            
+        if (result == 0x0A45DFA3)  //ReadId masks-off length indicator bits
+        {
+            assert(len == 4);
+            pos += len;
+            break;
+        }
+
+        ++pos;  //throw away just the 0x1A byte, and try again
+    }
+        
+    long len;
+    long long result = GetUIntLength(pReader, pos, len);
+    
+    if (result < 0)  //error
+        return result;
+        
+    if (result > 0)  //need more data
+        return result;
+        
+    assert(len > 0);
+    assert(len <= 8);
+    
+    if ((total -  pos) < len)
+        return E_FILE_FORMAT_INVALID;
+    if ((available - pos) < len)
+        return pos + len;  //try again later
+        
+    result = ReadUInt(pReader, pos, len);
+    
+    if (result < 0)  //error
+        return result;
+        
+    pos += len;  //consume u-int
+    
+    if ((total - pos) < result)
+        return E_FILE_FORMAT_INVALID;
+
+    if ((available - pos) < result)
+        return pos + result;
+        
+    end = pos + result;
+    
+    m_version = 1;
+    m_readVersion = 1;
+    m_maxIdLength = 4;
+    m_maxSizeLength = 8;
+    m_docTypeVersion = 1;
+    m_docTypeReadVersion = 1;
+
+    while (pos < end)
+    {
+        if (Match(pReader, pos, 0x0286, m_version))   
+            ;
+        else if (Match(pReader, pos, 0x02F7, m_readVersion))        
+            ;
+        else if (Match(pReader, pos, 0x02F2, m_maxIdLength))        
+            ;
+        else if (Match(pReader, pos, 0x02F3, m_maxSizeLength))      
+            ;
+        else if (Match(pReader, pos, 0x0282, m_docType))            
+            ; 
+        else if (Match(pReader, pos, 0x0287, m_docTypeVersion))     
+            ;
+        else if (Match(pReader, pos, 0x0285, m_docTypeReadVersion)) 
+            ;
+        else
+        {
+            result = ReadUInt(pReader, pos, len);
+            assert(result > 0);
+            assert(len > 0);
+            assert(len <= 8);
+        
+            pos += len;
+            assert(pos < end);
+            
+            result = ReadUInt(pReader, pos, len);
+            assert(result >= 0);
+            assert(len > 0);
+            assert(len <= 8);
+            
+            pos += len + result;
+            assert(pos <= end);
+        }
+    }
+    
+    assert(pos == end);
+        
+    return 0;    
+}
+
+
+Segment::Segment(
+    IMkvReader* pReader,
+    long long start,
+    long long size) :
+    m_pReader(pReader),
+    m_start(start),
+    m_size(size),
+    m_pos(start),
+    m_pInfo(NULL),
+    m_pTracks(NULL),
+    m_clusterCount(0)
+    //m_clusterNumber(0)
+{
+}
+
+
+Segment::~Segment()
+{
+    Cluster** i = m_clusters;
+    Cluster** j = m_clusters + m_clusterCount;
+
+    while (i != j)
+    {
+        Cluster* p = *i++;
+        assert(p);		
+        delete p;
+    } 
+    
+    delete[] m_clusters;
+       
+    delete m_pTracks;
+    delete m_pInfo;
+}
+
+
+long long Segment::CreateInstance(
+    IMkvReader* pReader,
+    long long pos,
+    Segment*& pSegment)
+{
+    assert(pReader);
+    assert(pos >= 0);
+    
+    pSegment = NULL;
+    
+    long long total, available;
+    
+    long hr = pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    
+    //I would assume that in practice this loop would execute
+    //exactly once, but we allow for other elements (e.g. Void)
+    //to immediately follow the EBML header.  This is fine for
+    //the source filter case (since the entire file is available),
+    //but in the splitter case over a network we should probably
+    //just give up early.  We could for example decide only to
+    //execute this loop a maximum of, say, 10 times.
+    
+    while (pos < total)
+    {    
+        //Read ID
+        
+        long len;
+        long long result = GetUIntLength(pReader, pos, len);
+        
+        if (result)  //error, or too few available bytes
+            return result;
+            
+        if ((pos + len) > total)
+            return E_FILE_FORMAT_INVALID;
+            
+        if ((pos + len) > available)
+            return pos + len;
+
+        //TODO: if we liberalize the behavior of ReadUInt, we can
+        //probably eliminate having to use GetUIntLength here.
+        const long long id = ReadUInt(pReader, pos, len);
+        
+        if (id < 0)  //error
+            return id;
+            
+        pos += len;  //consume ID
+        
+        //Read Size
+        
+        result = GetUIntLength(pReader, pos, len);
+        
+        if (result)  //error, or too few available bytes
+            return result;
+            
+        if ((pos + len) > total)
+            return E_FILE_FORMAT_INVALID;
+            
+        if ((pos + len) > available)
+            return pos + len;
+
+        //TODO: if we liberalize the behavior of ReadUInt, we can
+        //probably eliminate having to use GetUIntLength here.
+        const long long size = ReadUInt(pReader, pos, len);
+        
+        if (size < 0)
+            return size;
+            
+        pos += len;  //consume length of size of element
+        
+        //Pos now points to start of payload
+        
+        if ((pos + size) > total)
+            return E_FILE_FORMAT_INVALID;
+        
+        if (id == 0x08538067)  //Segment ID
+        {
+            pSegment = new  Segment(pReader, pos, size); 
+            assert(pSegment);  //TODO   
+
+            return 0;    //success
+        }
+        
+        pos += size;  //consume payload
+    }
+    
+    assert(pos == total);
+    
+    pSegment = new Segment(pReader, pos, 0); 
+    assert(pSegment);  //TODO   
+
+    return 0;  //success (sort of)
+}
+
+
+long long Segment::ParseHeaders()
+{
+    //Outermost (level 0) segment object has been constructed, 
+    //and pos designates start of payload.  We need to find the
+    //inner (level 1) elements.
+    long long total, available;
+    
+    long hr = m_pReader->Length(&total, &available);
+    assert(hr >= 0);
+    assert(available <= total);
+    
+    const long long stop = m_start + m_size;
+    assert(stop <= total);
+    assert(m_pos <= stop);
+    
+    bool bQuit = false;
+    while ((m_pos < stop) && !bQuit)
+    {
+        long long pos = m_pos;
+        
+        long len;
+        long long result = GetUIntLength(m_pReader, pos, len);
+        
+        if (result)  //error, or too few available bytes
+            return result;
+            
+        if ((pos + len) > stop)
+            return E_FILE_FORMAT_INVALID;
+            
+        if ((pos + len) > available)
+            return pos + len;
+            
+        const long long idpos = pos;
+        const long long id = ReadUInt(m_pReader, idpos, len);
+        
+        if (id < 0)  //error
+            return id;
+            
+        pos += len;  //consume ID
+        
+        //Read Size
+        result = GetUIntLength(m_pReader, pos, len);
+        
+        if (result)  //error, or too few available bytes
+            return result;
+            
+        if ((pos + len) > stop)
+            return E_FILE_FORMAT_INVALID;
+            
+        if ((pos + len) > available)
+            return pos + len;
+
+        const long long size = ReadUInt(m_pReader, pos, len);
+        
+        if (size < 0)
+            return size;
+            
+        pos += len;  //consume length of size of element
+        
+        //Pos now points to start of payload
+        
+        if ((pos + size) > stop)
+            return E_FILE_FORMAT_INVALID;
+            
+        //We read EBML elements either in total or nothing at all.
+            
+        if ((pos + size) > available)
+            return pos + size;
+        
+        if (id == 0x0549A966)  //Segment Info ID
+        {
+            assert(m_pInfo == NULL);
+            m_pInfo = new  SegmentInfo(this, pos, size);
+            assert(m_pInfo);  //TODO
+            
+            if (m_pTracks)
+                bQuit = true;
+        }
+        else if (id == 0x0654AE6B)  //Tracks ID
+        {
+            assert(m_pTracks == NULL);
+            m_pTracks = new  Tracks(this, pos, size);
+            assert(m_pTracks);  //TODO
+            
+            if (m_pInfo)
+                bQuit = true;
+        }
+        else if (id == 0x0F43B675)  //Cluster ID
+        {
+#if 0
+            if (m_pInfo == NULL)  //TODO: liberalize
+                ;  
+            else if (m_pTracks == NULL)
+                ;
+            else
+                //ParseCluster(idpos, pos, size);            
+                Cluster::Parse(this, m_clusters, pos, size);
+#endif
+            bQuit = true;
+        }
+        
+        m_pos = pos + size;  //consume payload
+    }
+    
+    assert(m_pos <= stop);
+    
+    return 0;  //success
+}
+
+
+long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const
+{
+    pCluster = NULL;
+    pos_ = -1;
+    
+    const long long stop = m_start + m_size;
+    assert(m_pos <= stop);
+    
+    long long pos = m_pos;
+    long long off = -1;
+   
+ 
+    while (pos < stop)
+    {
+        long len;
+        const long long idpos = pos;
+        
+        const long long id = SyncReadUInt(m_pReader, pos, stop, len);
+        
+        if (id < 0)  //error
+            return static_cast<long>(id);
+            
+        if (id == 0)
+            return E_FILE_FORMAT_INVALID;
+            
+        pos += len;  //consume id        
+        assert(pos < stop);
+
+        const long long size = SyncReadUInt(m_pReader, pos, stop, len);
+        
+        if (size < 0)  //error
+            return static_cast<long>(size);
+            
+        pos += len;  //consume size
+        assert(pos <= stop);
+            
+        if (size == 0)  //weird
+            continue;
+            
+        //pos now points to start of payload
+            
+        pos += size;  //consume payload
+        assert(pos <= stop);
+
+        if (off >= 0)
+        {
+            pos_ = idpos;
+            break;
+        }
+
+        if (id == 0x0F43B675)  //Cluster ID
+            off = idpos - m_start;
+    }
+    
+    Segment* const this_ = const_cast<Segment*>(this);
+    const size_t idx = m_clusterCount;
+    
+    if (pos >= stop)
+    {
+        pos_ = stop;
+        
+#if 0        
+        if (off < 0)
+        {
+            pCluster = Cluster::CreateEndOfStream(this_, idx);
+            return 1L;
+        }
+#else
+        if (off < 0)
+            return 1L;
+#endif
+                
+        //Reading 0 bytes at pos might work too -- it would depend 
+        //on how the reader is implemented.
+        
+        unsigned char b;
+
+        const long hr = m_pReader->Read(pos - 1, 1, &b);
+        
+        if (hr < 0)
+            return hr;
+            
+        if (hr != 0L)
+            return E_BUFFER_NOT_FULL;
+    }
+    
+    assert(off >= 0);
+    assert(pos_ >= m_start);
+    assert(pos_ <= stop);
+
+    pCluster = Cluster::Parse(this_, idx, off);
+    return 0L;
+}
+
+
+bool Segment::AddCluster(Cluster* pCluster, long long pos)
+{
+    assert(pos >= m_start);
+    
+    const long long stop = m_start + m_size;
+    assert(pos <= stop);
+
+    if (pCluster)    
+        m_clusters[pos] = pCluster;
+        
+    m_pos = pos;  //m_pos >= stop is now we know we have all clusters
+    
+    return (pos >= stop);
+}
+
+
+long Segment::Load()
+{
+    //Outermost (level 0) segment object has been constructed, 
+    //and pos designates start of payload.  We need to find the
+    //inner (level 1) elements.
+    const long long stop = m_start + m_size;
+#ifdef _DEBUG
+    {
+        long long total, available;
+        
+        long hr = m_pReader->Length(&total, &available);
+        assert(hr >= 0);
+        assert(available >= total);
+        assert(stop <= total);
+    }
+#endif
+    long long index = m_pos;
+    
+    m_clusterCount = 0;
+
+    while (index < stop)
+    {
+        long len = 0;
+
+        long long result = GetUIntLength(m_pReader, index, len);
+       
+        if (result < 0)  //error
+            return static_cast<long>(result);
+            
+        if ((index + len) > stop)
+            return E_FILE_FORMAT_INVALID;
+            
+        const long long idpos = index;
+        const long long id = ReadUInt(m_pReader, idpos, len);
+        
+        if (id < 0)  //error
+            return static_cast<long>(id);
+            
+        index += len;  //consume ID
+        
+        //Read Size
+        result = GetUIntLength(m_pReader, index, len);
+        
+        if (result < 0)  //error
+            return static_cast<long>(result);
+            
+        if ((index + len) > stop)
+            return E_FILE_FORMAT_INVALID;
+            
+        const long long size = ReadUInt(m_pReader, index, len);
+        
+        if (size < 0)  //error
+            return static_cast<long>(size);
+            
+        index += len;  //consume length of size of element
+ 
+        if (id == 0x0F43B675) // Cluster ID 
+            break;
+	
+        if (id == 0x014D9B74) // SeekHead ID 
+        {
+            ParseSeekHead(index, size, NULL); 
+            break;
+        }
+        index += size;
+    }
+        
+    if (m_clusterCount == 0)
+        return -1L;
+
+    while (m_pos < stop)
+    {
+        long long pos = m_pos;
+        
+        long len;
+
+        long long result = GetUIntLength(m_pReader, pos, len);
+        
+        if (result < 0)  //error
+            return static_cast<long>(result);
+            
+        if ((pos + len) > stop)
+            return E_FILE_FORMAT_INVALID;
+            
+        const long long idpos = pos;
+        const long long id = ReadUInt(m_pReader, idpos, len);
+        
+        if (id < 0)  //error
+            return static_cast<long>(id);
+            
+        pos += len;  //consume ID
+        
+        //Read Size
+        result = GetUIntLength(m_pReader, pos, len);
+        
+        if (result < 0)  //error
+            return static_cast<long>(result);
+            
+        if ((pos + len) > stop)
+	        return E_FILE_FORMAT_INVALID;
+            
+        const long long size = ReadUInt(m_pReader, pos, len);
+       
+        if (size < 0)  //error
+            return static_cast<long>(size);
+            
+        pos += len;  //consume length of size of element
+        
+        //Pos now points to start of payload
+        
+        if ((pos + size) > stop)
+            return E_FILE_FORMAT_INVALID;
+            
+        if (id == 0x0F43B675)  //Cluster ID
+            break;
+
+        if (id == 0x014D9B74)  //SeekHead ID
+        {
+            m_clusters = new Cluster*[m_clusterCount];   
+            size_t index = 0;
+            
+            ParseSeekHead(pos, size, &index);            
+            assert(index == m_clusterCount);
+        }            
+        else if (id == 0x0549A966)  //Segment Info ID
+        {
+            assert(m_pInfo == NULL);
+            m_pInfo = new  SegmentInfo(this, pos, size);
+            assert(m_pInfo);  //TODO
+        }
+        else if (id == 0x0654AE6B)  //Tracks ID
+        {
+            assert(m_pTracks == NULL);
+            m_pTracks = new Tracks(this, pos, size);
+            assert(m_pTracks);  //TODO
+        }
+
+        m_pos = pos + size;  //consume payload
+    }
+    
+    assert(m_clusters);
+    
+    //TODO: see notes above.  This check is here (temporarily) to ensure
+    //that the first seekhead has entries for the clusters (because that's
+    //when they're loaded).  In case we are given a file that lists the
+    //clusters in a second seekhead, the worst thing that happens is that
+    //we treat this as an invalid file (which is better then simply
+    //asserting somewhere).  But that's only a work-around.  What we need
+    //to do is be able to handle having multiple seekheads, and having
+    //clusters listed somewhere besides the first seekhead.
+    //    
+    //if (m_clusters == NULL)
+    //    return E_FILE_FORMAT_INVALID;
+        
+    //NOTE: we stop parsing when we reach the first cluster, under the
+    //assumption all clusters are named in some SeekHead.  Clusters
+    //will have been (pre)loaded, so we indicate that we have all clusters
+    //by adjusting the parse position:
+    m_pos = stop;  //means "we have all clusters"
+
+    return 0L;
+}
+
+
+void Segment::ParseSeekHead(long long start, long long size_, size_t* pIndex)
+{
+    long long pos = start;
+    const long long stop = start + size_;
+    while (pos < stop)
+    {
+        long len;
+        
+        const long long id = ReadUInt(m_pReader, pos, len);
+        assert(id >= 0);  //TODO
+        assert((pos + len) <= stop);
+        
+        pos += len;  //consume ID
+        
+        const long long size = ReadUInt(m_pReader, pos, len);
+        assert(size >= 0);
+        assert((pos + len) <= stop);
+        
+        pos += len;  //consume Size field
+        assert((pos + size) <= stop);
+
+        if (id == 0x0DBB)  //SeekEntry ID
+            ParseSeekEntry(pos, size, pIndex);
+        
+        pos += size;  //consume payload
+        assert(pos <= stop);
+    }
+    
+    assert(pos == stop);
+}
+
+
+void Segment::ParseSecondarySeekHead(long long off, size_t* pIndex)
+{
+    assert(off >= 0);
+    assert(off < m_size);
+
+    long long pos = m_start + off;
+    const long long stop = m_start + m_size;
+    
+    long len;
+
+    long long result = GetUIntLength(m_pReader, pos, len);
+    assert(result == 0);
+    assert((pos + len) <= stop);
+    
+    const long long idpos = pos;
+
+    const long long id = ReadUInt(m_pReader, idpos, len);
+    assert(id == 0x014D9B74);  //SeekHead ID
+    
+    pos += len;  //consume ID
+    assert(pos < stop);
+    
+    //Read Size
+    
+    result = GetUIntLength(m_pReader, pos, len);
+    assert(result == 0);
+    assert((pos + len) <= stop);
+    
+    const long long size = ReadUInt(m_pReader, pos, len);
+    assert(size >= 0);
+    
+    pos += len;  //consume length of size of element
+    assert((pos + size) <= stop);
+    
+    //Pos now points to start of payload
+    
+    ParseSeekHead(pos, size, pIndex);
+}
+
+
+void Segment::ParseSeekEntry(long long start, long long size_, size_t* pIndex)
+{
+    long long pos = start;
+
+    const long long stop = start + size_;
+    
+    long len;
+    
+    const long long seekIdId = ReadUInt(m_pReader, pos, len);
+    //seekIdId;
+    assert(seekIdId == 0x13AB);  //SeekID ID
+    assert((pos + len) <= stop);
+    
+    pos += len;  //consume id
+
+    const long long seekIdSize = ReadUInt(m_pReader, pos, len);
+    assert(seekIdSize >= 0);
+    assert((pos + len) <= stop);
+    
+    pos += len;  //consume size
+    
+    const long long seekId = ReadUInt(m_pReader, pos, len);  //payload
+    assert(seekId >= 0);
+    assert(len == seekIdSize);
+    assert((pos + len) <= stop);
+    
+    pos += seekIdSize;  //consume payload
+    
+    const long long seekPosId = ReadUInt(m_pReader, pos, len);
+    //seekPosId;
+    assert(seekPosId == 0x13AC);  //SeekPos ID
+    assert((pos + len) <= stop);
+    
+    pos += len;  //consume id
+    
+    const long long seekPosSize = ReadUInt(m_pReader, pos, len);
+    assert(seekPosSize >= 0);
+    assert((pos + len) <= stop);
+
+    pos += len;  //consume size
+    assert((pos + seekPosSize) <= stop);
+        
+    const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);
+    assert(seekOff >= 0);
+    assert(seekOff < m_size);
+    
+    pos += seekPosSize;  //consume payload
+    assert(pos == stop);
+    
+    const long long seekPos = m_start + seekOff;
+    assert(seekPos < (m_start + m_size));
+   
+    if (seekId == 0x0F43B675)  //cluster id
+    {       
+        if (pIndex == NULL)
+            ++m_clusterCount; 
+        else
+        {
+            assert(m_clusters);
+            assert(m_clusterCount > 0);
+            
+            size_t& index = *pIndex;
+            assert(index < m_clusterCount);
+            
+            Cluster*& pCluster = m_clusters[index];
+            
+            pCluster = Cluster::Parse(this, index, seekOff);
+            assert(pCluster);  //TODO
+            
+            ++index;
+        }
+    }
+    else if (seekId == 0x014D9B74)  //SeekHead ID
+    {
+        ParseSecondarySeekHead(seekOff, pIndex);
+    }
+}
+
+
+long long Segment::Unparsed() const
+{
+    const long long stop = m_start + m_size;
+
+    const long long result = stop - m_pos;
+    assert(result >= 0);
+    
+    return result;
+}
+
+
+#if 0  //NOTE: too inefficient
+long long Segment::Load(long long time_ns)
+{
+    if (Unparsed() <= 0)
+        return 0;
+    
+    while (m_clusters.empty())
+    {
+        const long long result = Parse();
+        
+        if (result)  //error, or not enough bytes available
+            return result;
+            
+        if (Unparsed() <= 0)
+            return 0;
+    }
+    
+    while (m_clusters.back()->GetTime() < time_ns)
+    {
+        const long long result = Parse();
+        
+        if (result)  //error, or not enough bytes available
+            return result;
+            
+        if (Unparsed() <= 0)
+            return 0;
+    }        
+
+    return 0;        
+}
+#endif
+
+
+Cluster* Segment::GetFirst()
+{
+    if ((m_clusters == NULL) || (m_clusterCount <= 0))
+       return &m_eos;
+
+    Cluster* const pCluster = m_clusters[0];
+    assert(pCluster);
+        
+    return pCluster;
+}
+
+
+Cluster* Segment::GetLast()
+{
+    if ((m_clusters == NULL) || (m_clusterCount <= 0))
+        return &m_eos;
+
+    const size_t idx = m_clusterCount - 1;    
+    Cluster* const pCluster = m_clusters[idx];
+    assert(pCluster);
+        
+    return pCluster;
+}
+
+
+unsigned long Segment::GetCount() const
+{
+    //TODO: m_clusterCount should not be long long.
+    return static_cast<unsigned long>(m_clusterCount);
+}
+
+
+Cluster* Segment::GetNext(const Cluster* pCurr)
+{
+    assert(pCurr);
+    assert(pCurr != &m_eos);
+    assert(m_clusters);
+    assert(m_clusterCount > 0);
+
+    size_t idx =  pCurr->m_index;
+    assert(idx < m_clusterCount);
+    assert(pCurr == m_clusters[idx]);
+    
+    idx++;
+    
+    if (idx >= m_clusterCount) 
+        return &m_eos;
+        
+    Cluster* const pNext = m_clusters[idx];
+    assert(pNext);
+    
+    return pNext;
+}
+
+
+Cluster* Segment::GetCluster(long long time_ns)
+{
+    if ((m_clusters == NULL) || (m_clusterCount <= 0))
+        return &m_eos;
+        
+    {
+        Cluster* const pCluster = m_clusters[0];
+        assert(pCluster);
+        assert(pCluster->m_index == 0);
+        
+        if (time_ns <= pCluster->GetTime())
+            return pCluster;
+    }
+    
+    //Binary search of cluster array
+       
+    size_t i = 0;
+    size_t j = m_clusterCount;
+    
+    while (i < j)
+    {
+        //INVARIANT:
+        //[0, i) <= time_ns
+        //[i, j) ?
+        //[j, m_clusterCount)  > time_ns
+        
+        const size_t k = i + (j - i) / 2;
+        assert(k < m_clusterCount);
+
+        Cluster* const pCluster = m_clusters[k];
+        assert(pCluster);
+        assert(pCluster->m_index == k);
+        
+        const long long t = pCluster->GetTime();
+        
+        if (t <= time_ns)
+            i = k + 1;
+        else
+            j = k;
+            
+        assert(i <= j);
+    }
+    
+    assert(i == j);
+    assert(i > 0);
+    assert(i <= m_clusterCount);
+    
+    const size_t k = i - 1;
+    
+    Cluster* const pCluster = m_clusters[k];
+    assert(pCluster);
+    assert(pCluster->m_index == k);
+    assert(pCluster->GetTime() <= time_ns);
+    
+    return pCluster;
+}
+
+
+Tracks* Segment::GetTracks() const
+{
+    return m_pTracks;
+}
+
+
+const SegmentInfo* const Segment::GetInfo() const
+{
+    return m_pInfo;
+}
+
+
+long long Segment::GetDuration() const
+{
+    assert(m_pInfo);
+    return m_pInfo->GetDuration();
+}
+
+
+SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_) :
+    m_pSegment(pSegment),
+    m_start(start),
+    m_size(size_),
+    m_pMuxingAppAsUTF8(NULL),
+    m_pWritingAppAsUTF8(NULL),
+    m_pTitleAsUTF8(NULL)
+{
+    IMkvReader* const pReader = m_pSegment->m_pReader;
+   
+    long long pos = start;
+    const long long stop = start + size_;
+    
+    m_timecodeScale = 1000000;
+    m_duration = 0;
+    
+    
+    while (pos < stop)
+    {
+        if (Match(pReader, pos, 0x0AD7B1, m_timecodeScale))
+            assert(m_timecodeScale > 0);
+
+        else if (Match(pReader, pos, 0x0489, m_duration))
+            assert(m_duration >= 0);
+
+        else if (Match(pReader, pos, 0x0D80, m_pMuxingAppAsUTF8))   //[4D][80] 
+            assert(m_pMuxingAppAsUTF8);
+
+        else if (Match(pReader, pos, 0x1741, m_pWritingAppAsUTF8))  //[57][41]
+            assert(m_pWritingAppAsUTF8);
+            
+        else if (Match(pReader, pos, 0x3BA9, m_pTitleAsUTF8))        //[7B][A9]
+            assert(m_pTitleAsUTF8);
+
+        else
+        {
+            long len;
+            
+            const long long id = ReadUInt(pReader, pos, len);
+            //id;
+            assert(id >= 0);
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume id
+            assert((stop - pos) > 0);
+            
+            const long long size = ReadUInt(pReader, pos, len);
+            assert(size >= 0);
+            assert((pos + len) <= stop);
+            
+            pos += len + size;  //consume size and payload
+            assert(pos <= stop);
+        }
+    }
+    
+    assert(pos == stop);
+}
+
+SegmentInfo::~SegmentInfo()
+{
+    if (m_pMuxingAppAsUTF8)
+    {
+        delete[] m_pMuxingAppAsUTF8;
+        m_pMuxingAppAsUTF8 = NULL;
+    }
+
+    if (m_pWritingAppAsUTF8)
+    {
+        delete[] m_pWritingAppAsUTF8;
+        m_pWritingAppAsUTF8 = NULL;
+    }
+   
+    if (m_pTitleAsUTF8)
+    {
+        delete[] m_pTitleAsUTF8;
+        m_pTitleAsUTF8 = NULL;
+    }
+}
+
+long long SegmentInfo::GetTimeCodeScale() const
+{
+    return m_timecodeScale;
+}
+
+
+long long SegmentInfo::GetDuration() const
+{
+    assert(m_duration >= 0);    
+    assert(m_timecodeScale >= 1);
+    
+    const double dd = double(m_duration) * double(m_timecodeScale);
+    const long long d = static_cast<long long>(dd);
+    
+    return d;
+}
+
+const char* SegmentInfo::GetMuxingAppAsUTF8() const
+{
+    return m_pMuxingAppAsUTF8;
+}
+
+const char* SegmentInfo::GetWritingAppAsUTF8() const
+{
+    return m_pWritingAppAsUTF8;
+}
+
+const char* SegmentInfo::GetTitleAsUTF8() const
+{
+    return m_pTitleAsUTF8;
+}
+
+Track::Track(Segment* pSegment, const Info& i) :
+    m_pSegment(pSegment),
+    m_info(i)
+{
+}
+
+Track::~Track()
+{
+    Info& info = const_cast<Info&>(m_info);
+    info.Clear();
+}
+
+Track::Info::Info():
+    type(-1),
+    number(-1),
+    uid(-1),
+    nameAsUTF8(NULL),
+    codecId(NULL),
+    codecPrivate(NULL),
+    codecPrivateSize(0),
+    codecNameAsUTF8(NULL)
+{
+}
+
+void Track::Info::Clear() 
+{
+    delete[] nameAsUTF8;
+    nameAsUTF8 = NULL;
+
+    delete[] codecId;
+    codecId = NULL;
+
+    delete[] codecPrivate;
+    codecPrivate = NULL;
+
+    delete[] codecNameAsUTF8;
+    codecNameAsUTF8 = NULL;
+}
+
+const BlockEntry* Track::GetEOS() const
+{
+    return &m_eos;
+}
+
+long long Track::GetType() const
+{
+    const unsigned long result = static_cast<unsigned long>(m_info.type);
+    return result;
+}
+
+unsigned long Track::GetNumber() const
+{
+    assert(m_info.number >= 0);
+    const unsigned long result = static_cast<unsigned long>(m_info.number);
+    return result;
+}
+
+const char* Track::GetNameAsUTF8() const
+{
+    return m_info.nameAsUTF8;
+}
+
+const char* Track::GetCodecNameAsUTF8() const
+{  
+    return m_info.codecNameAsUTF8;
+}
+
+
+const char* Track::GetCodecId() const
+{
+    return m_info.codecId;
+}
+
+
+const unsigned char* Track::GetCodecPrivate(size_t *optionalSize) const
+{
+    if (optionalSize) {
+        *optionalSize = m_info.codecPrivateSize;
+    }
+    return m_info.codecPrivate;
+}
+
+
+long Track::GetFirst(const BlockEntry*& pBlockEntry) const
+{
+    Cluster* const pCluster = m_pSegment->GetFirst();
+    
+    //If Segment::GetFirst returns NULL, then this must be a network 
+    //download, and we haven't loaded any clusters yet.  In this case,
+    //returning NULL from Track::GetFirst means the same thing.
+
+    if ((pCluster == NULL) || pCluster->EOS())
+    {
+        pBlockEntry = NULL;
+        return E_BUFFER_NOT_FULL;  //return 1L instead?
+    }
+        
+    pBlockEntry = pCluster->GetFirst();
+    
+    while (pBlockEntry)
+    {
+        const Block* const pBlock = pBlockEntry->GetBlock();
+        assert(pBlock);
+        
+        if (pBlock->GetTrackNumber() == (unsigned long)m_info.number)
+            return 0L;
+            
+        pBlockEntry = pCluster->GetNext(pBlockEntry);
+    }
+    
+    //NOTE: if we get here, it means that we didn't find a block with
+    //a matching track number.  We interpret that as an error (which
+    //might be too conservative).
+
+    pBlockEntry = GetEOS();  //so we can return a non-NULL value
+    return 1L;
+}
+
+
+long Track::GetNext(const BlockEntry* pCurrEntry, const BlockEntry*& pNextEntry) const
+{
+    assert(pCurrEntry);
+    assert(!pCurrEntry->EOS());  //?
+    assert(pCurrEntry->GetBlock()->GetTrackNumber() == (unsigned long)m_info.number);    
+    
+    const Cluster* const pCurrCluster = pCurrEntry->GetCluster();
+    assert(pCurrCluster);
+    assert(!pCurrCluster->EOS());
+    
+    pNextEntry = pCurrCluster->GetNext(pCurrEntry);
+            
+    while (pNextEntry)
+    {    
+        const Block* const pNextBlock = pNextEntry->GetBlock();
+        assert(pNextBlock);
+    
+        if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number)
+            return 0L;
+            
+        pNextEntry = pCurrCluster->GetNext(pNextEntry);
+    }
+
+    Segment* pSegment = pCurrCluster->m_pSegment;    
+    Cluster* const pNextCluster = pSegment->GetNext(pCurrCluster);
+    
+    if ((pNextCluster == NULL) || pNextCluster->EOS())
+    {
+        if (pSegment->Unparsed() <= 0)   //all clusters have been loaded
+        {
+            pNextEntry = GetEOS();
+            return 1L;
+        }
+        
+        pNextEntry = NULL;
+        return E_BUFFER_NOT_FULL;
+    }
+        
+    pNextEntry = pNextCluster->GetFirst();
+    
+    while (pNextEntry)
+    {
+        const Block* const pNextBlock = pNextEntry->GetBlock();
+        assert(pNextBlock);
+        
+        if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number)
+            return 0L;
+            
+        pNextEntry = pNextCluster->GetNext(pNextEntry);
+    }
+    
+    //TODO: what has happened here is that we did not find a block
+    //with a matching track number on the next cluster.  It might
+    //be the case that some cluster beyond the next cluster 
+    //contains a block having a matching track number, but for
+    //now we terminate the search immediately.  We do this so that
+    //we don't end up searching the entire file looking for the
+    //next block.  Another possibility is to try searching for the next
+    //block in a small, fixed number of clusters (intead searching
+    //just the next one), or to terminate the search when when the
+    //there is a large gap in time, or large gap in file position.  It
+    //might very well be the case that the approach we use here is
+    //unnecessarily conservative.
+    
+    //TODO: again, here's a case where we need to return the special
+    //EOS block.  Or something.  It's OK if pNext is NULL, because
+    //we only need it to set the stop time of the media sample.
+    //(The start time is determined from pCurr, which is non-NULL
+    //and non-EOS.)  The problem is when we set pCurr=pNext; when
+    //pCurr has the value NULL we interpret that to mean that we
+    //haven't fully initialized pCurr and we attempt to set it to
+    //point to the first block for this track.  But that's not what
+    //we want at all; we want the next call to PopulateSample to
+    //return end-of-stream, not (re)start from the beginning.
+    //
+    //One work-around is to send EOS immediately.  We would send 
+    //the EOS the next pass anyway, so maybe it's no great loss.  The 
+    //only problem is that if this the stream really does end one
+    //cluster early (relative to other tracks), or the last frame
+    //happens to be a keyframe ("CanSeekToEnd").
+    //
+    //The problem is that we need a way to mark as stream as
+    //"at end of stream" without actually being at end of stream.
+    //We need to give pCurr some value that means "you've reached EOS".
+    //We can't synthesize the special EOS Cluster immediately
+    //(when we first open the file, say), because we use the existance
+    //of that special cluster value to mean that we've read all of 
+    //the clusters (this is a network download, so we can't know apriori
+    //how many we have).
+    //
+    //Or, we could return E_FAIL, and set another bit in the stream
+    //object itself, to indicate that it should send EOS earlier
+    //than when (pCurr=pStop).
+    //
+    //Or, probably the best solution, when we actually load the 
+    //blocks into a cluster: if we notice that there's no block
+    //for a track, we synthesize a nonce EOS block for that track.
+    //That way we always have something to return.  But that will
+    //only work for sequential scan???
+
+    //pNext = NULL;    
+    //return E_FAIL;
+    pNextEntry = GetEOS();
+    return 1L;
+}
+
+
+Track::EOSBlock::EOSBlock()
+{
+}
+
+
+bool Track::EOSBlock::EOS() const
+{
+    return true;
+}
+
+
+Cluster* Track::EOSBlock::GetCluster() const
+{
+    return NULL;
+}
+
+
+size_t Track::EOSBlock::GetIndex() const
+{
+    return 0;
+}
+
+
+const Block* Track::EOSBlock::GetBlock() const
+{
+    return NULL;
+}
+
+
+bool Track::EOSBlock::IsBFrame() const
+{
+    return false;
+}
+
+
+VideoTrack::VideoTrack(Segment* pSegment, const Info& i) :
+    Track(pSegment, i),
+    m_width(-1),
+    m_height(-1),
+    m_rate(-1)
+{
+    assert(i.type == 1);
+    assert(i.number > 0);
+    
+    IMkvReader* const pReader = pSegment->m_pReader;
+    
+    const Settings& s = i.settings;
+    assert(s.start >= 0);
+    assert(s.size >= 0);
+    
+    long long pos = s.start;
+    assert(pos >= 0);
+    
+    const long long stop = pos + s.size;
+    
+    while (pos < stop)
+    {
+#ifdef _DEBUG
+        long len;
+        const long long id = ReadUInt(pReader, pos, len);
+        assert(id >= 0);  //TODO: handle error case
+        assert((pos + len) <= stop);
+#endif
+        if (Match(pReader, pos, 0x30, m_width))         
+            ;
+        else if (Match(pReader, pos, 0x3A, m_height))   
+            ;
+        else if (Match(pReader, pos, 0x0383E3, m_rate)) 
+            ;
+        else
+        {
+            long len;
+            const long long id = ReadUInt(pReader, pos, len);
+            assert(id >= 0);  //TODO: handle error case
+            assert((pos + len) <= stop);
+        
+            pos += len;  //consume id
+            
+            const long long size = ReadUInt(pReader, pos, len);
+            assert(size >= 0);  //TODO: handle error case
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume length of size
+            assert((pos + size) <= stop);
+            
+            //pos now designates start of payload
+            
+            pos += size;  //consume payload
+            assert(pos <= stop);
+        }
+    }
+    
+    return;
+}
+
+
+bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const
+{
+    assert(pBlockEntry);
+    
+    const Block* const pBlock = pBlockEntry->GetBlock();
+    assert(pBlock);    
+    assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number);
+    
+    return pBlock->IsKey();
+}
+
+
+
+long long VideoTrack::GetWidth() const
+{
+    return m_width;
+}
+
+
+long long VideoTrack::GetHeight() const
+{
+    return m_height;
+}
+
+
+double VideoTrack::GetFrameRate() const
+{
+    return m_rate;
+}
+
+
+AudioTrack::AudioTrack(Segment* pSegment, const Info& i) :
+    Track(pSegment, i)
+{
+    assert(i.type == 2);
+    assert(i.number > 0);
+
+    IMkvReader* const pReader = pSegment->m_pReader;
+    
+    const Settings& s = i.settings;
+    assert(s.start >= 0);
+    assert(s.size >= 0);
+    
+    long long pos = s.start;
+    assert(pos >= 0);
+    
+    const long long stop = pos + s.size;
+    
+    while (pos < stop)
+    {
+#ifdef _DEBUG
+        long len;
+        const long long id = ReadUInt(pReader, pos, len);
+        assert(id >= 0);  //TODO: handle error case
+        assert((pos + len) <= stop);
+#endif
+        if (Match(pReader, pos, 0x35, m_rate))            
+            ;
+        else if (Match(pReader, pos, 0x1F, m_channels))   
+            ;
+        else if (Match(pReader, pos, 0x2264, m_bitDepth))  
+            ;            
+        else
+        {
+            long len;
+            const long long id = ReadUInt(pReader, pos, len);
+            assert(id >= 0);  //TODO: handle error case
+            assert((pos + len) <= stop);
+        
+            pos += len;  //consume id
+            
+            const long long size = ReadUInt(pReader, pos, len);
+            assert(size >= 0);  //TODO: handle error case
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume length of size
+            assert((pos + size) <= stop);
+            
+            //pos now designates start of payload
+            
+            pos += size;  //consume payload
+            assert(pos <= stop);
+        }
+    }
+
+    return;
+}
+
+bool AudioTrack::VetEntry(const BlockEntry* pBlockEntry) const
+{
+    assert(pBlockEntry);
+    
+    const Block* const pBlock = pBlockEntry->GetBlock();
+    assert(pBlock);
+    assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number);
+
+    return true;
+}
+
+
+double AudioTrack::GetSamplingRate() const
+{
+    return m_rate;
+}
+
+
+long long AudioTrack::GetChannels() const
+{
+    return m_channels;
+}
+
+long long AudioTrack::GetBitDepth() const
+{
+    return m_bitDepth;
+}
+
+Tracks::Tracks(Segment* pSegment, long long start, long long size_) :
+    m_pSegment(pSegment),
+    m_start(start),
+    m_size(size_),
+    m_trackEntries(NULL),
+    m_trackEntriesEnd(NULL)
+{
+    long long stop = m_start + m_size;
+    IMkvReader* const pReader = m_pSegment->m_pReader;
+    
+    long long pos1 = m_start;
+    int count = 0;
+    
+    while (pos1 < stop)
+    {
+        long len;
+        const long long id = ReadUInt(pReader, pos1, len);
+        assert(id >= 0);
+        assert((pos1 + len) <= stop);
+        
+        pos1 += len;  //consume id
+        
+        const long long size = ReadUInt(pReader, pos1, len);
+        assert(size >= 0);
+        assert((pos1 + len) <= stop);
+        
+        pos1 += len;  //consume length of size
+        
+        //pos now desinates start of element
+        if (id == 0x2E)  //TrackEntry ID
+            ++count;
+            
+        pos1 += size;  //consume payload
+        assert(pos1 <= stop);
+    }    
+
+    if (count <= 0)
+        return;
+
+    m_trackEntries = new Track*[count];
+    m_trackEntriesEnd = m_trackEntries;
+
+    long long pos = m_start;
+
+    while (pos < stop)
+    {
+        long len;
+        const long long id = ReadUInt(pReader, pos, len);
+        assert(id >= 0);
+        assert((pos + len) <= stop);
+        
+        pos += len;  //consume id
+        
+        const long long size1 = ReadUInt(pReader, pos, len);
+        assert(size1 >= 0);
+        assert((pos + len) <= stop);
+        
+        pos += len;  //consume length of size
+        
+        //pos now desinates start of element
+        
+        if (id == 0x2E)  //TrackEntry ID
+            ParseTrackEntry(pos, size1, *m_trackEntriesEnd++);
+            
+        pos += size1;  //consume payload
+        assert(pos <= stop);
+    }    
+}
+
+unsigned long Tracks::GetTracksCount() const
+{
+    const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;
+    assert(result >= 0);
+    
+    return static_cast<unsigned long>(result);
+}
+
+
+void Tracks::ParseTrackEntry(
+    long long start,
+    long long size,
+    Track*& pTrack)
+{
+    IMkvReader* const pReader = m_pSegment->m_pReader;
+    
+    long long pos = start;
+    const long long stop = start + size;
+
+    Track::Info i;
+    
+    Track::Settings videoSettings;
+    videoSettings.start = -1;
+    
+    Track::Settings audioSettings;
+    audioSettings.start = -1;
+    
+    while (pos < stop)
+    {
+#ifdef _DEBUG
+        long len;
+        const long long id = ReadUInt(pReader, pos, len);
+        len;
+        id;
+#endif
+        if (Match(pReader, pos, 0x57, i.number))
+            assert(i.number > 0);
+
+        else if (Match(pReader, pos, 0x33C5, i.uid))           
+            ;  
+
+        else if (Match(pReader, pos, 0x03, i.type))            
+            ;  
+
+        else if (Match(pReader, pos, 0x136E, i.nameAsUTF8))          
+            assert(i.nameAsUTF8);  
+
+        else if (Match(pReader, pos, 0x06, i.codecId))         
+            ;  
+
+        else if (Match(pReader, pos, 0x23A2, i.codecPrivate, &i.codecPrivateSize))  
+            ;  
+
+        else if (Match(pReader, pos, 0x058688, i.codecNameAsUTF8))   
+            assert(i.codecNameAsUTF8);  
+
+        else
+        {
+            long len;
+            
+            const long long id = ReadUInt(pReader, pos, len);
+            assert(id >= 0);  //TODO: handle error case
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume id
+            
+            const long long size = ReadUInt(pReader, pos, len);
+            assert(size >= 0);  //TODO: handle error case
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume length of size
+            const long long start = pos;
+            
+            pos += size;  //consume payload
+            assert(pos <= stop);
+            
+            if (id == 0x60)
+            {
+                videoSettings.start = start;
+                videoSettings.size = size;
+            }
+            else if (id == 0x61)
+            {
+                audioSettings.start = start;
+                audioSettings.size = size;
+            }
+        }
+    }
+    
+    assert(pos == stop);
+    //TODO: propertly vet info.number, to ensure both its existence,
+    //and that it is unique among all tracks.
+    assert(i.number > 0);
+
+    //TODO: vet settings, to ensure that video settings (0x60)
+    //were specified when type = 1, and that audio settings (0x61)
+    //were specified when type = 2.    
+    if (i.type == 1)  //video
+    {
+        assert(audioSettings.start < 0);
+        assert(videoSettings.start >= 0);
+        
+        i.settings = videoSettings;
+        
+        VideoTrack* const t = new VideoTrack(m_pSegment, i);
+        assert(t);  //TODO
+        pTrack = t;    
+    }
+    else if (i.type == 2)  //audio
+    {
+        assert(videoSettings.start < 0);
+        assert(audioSettings.start >= 0);
+        
+        i.settings = audioSettings;
+        
+        AudioTrack* const t = new  AudioTrack(m_pSegment, i);
+        assert(t);  //TODO
+        pTrack = t;  
+    }
+    else
+    {
+        // for now we do not support other track types yet.
+        // TODO: support other track types
+        i.Clear();
+  
+        pTrack = NULL;
+    }
+    
+    return;
+}
+
+
+Tracks::~Tracks()
+{
+    Track** i = m_trackEntries;
+    Track** const j = m_trackEntriesEnd;
+    
+    while (i != j)
+    {
+        Track* pTrack = *i++;
+        delete pTrack;
+        pTrack = NULL;    
+    }
+
+    delete[] m_trackEntries;
+}
+
+
+Track* Tracks::GetTrackByNumber(unsigned long tn) const
+{
+    Track** i = m_trackEntries;
+    Track** const j = m_trackEntriesEnd;
+
+    while (i != j)
+    {
+        Track* const pTrack = *i++;
+       
+        if (pTrack == NULL)
+            continue;
+
+        if (tn == pTrack->GetNumber())
+            return pTrack;
+    }
+
+    return NULL;  //not found
+}
+
+
+Track* Tracks::GetTrackByIndex(unsigned long idx) const
+{
+    const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;
+       
+    if (idx >= static_cast<unsigned long>(count))
+         return NULL;
+
+    return m_trackEntries[idx];
+}
+
+
+void Cluster::Load()
+{
+    assert(m_pSegment);
+    
+    if (m_start > 0)
+    {
+        assert(m_size > 0);
+        assert(m_timecode >= 0);
+        return;
+    }
+    
+    assert(m_size == 0);
+    assert(m_timecode < 0);
+    
+    IMkvReader* const pReader = m_pSegment->m_pReader;
+
+    const long long off = -m_start;  //relative to segment
+    long long pos = m_pSegment->m_start + off;  //absolute
+    
+    long len;
+
+    const long long id_ = ReadUInt(pReader, pos, len);
+    assert(id_ >= 0);
+    assert(id_ == 0x0F43B675);  //Cluster ID
+    
+    pos += len;  //consume id
+    
+    const long long size_ = ReadUInt(pReader, pos, len);
+    assert(size_ >= 0);
+    
+    pos += len;  //consume size
+    
+    m_start = pos;
+    m_size = size_;
+    
+    const long long stop = m_start + size_;
+    
+    long long timecode = -1;
+    
+    while (pos < stop)
+    {
+        if (Match(pReader, pos, 0x67, timecode))
+            break;            
+        else
+        {
+            const long long id = ReadUInt(pReader, pos, len);
+            assert(id >= 0);  //TODO
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume id
+            
+            const long long size = ReadUInt(pReader, pos, len);
+            assert(size >= 0);  //TODO
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume size
+            
+            if (id == 0x20)  //BlockGroup ID
+                break;
+                
+            if (id == 0x23)  //SimpleBlock ID
+                break;
+
+            pos += size;  //consume payload
+            assert(pos <= stop);
+        }
+    }
+    
+    assert(pos <= stop);
+    assert(timecode >= 0);
+    
+    m_timecode = timecode;
+}
+
+
+Cluster* Cluster::Parse(
+    Segment* pSegment,
+    size_t idx,
+    long long off)
+{
+    assert(pSegment);
+    assert(off >= 0);
+    assert(off < pSegment->m_size);
+    Cluster* const pCluster = new Cluster(pSegment, idx, -off);
+    assert(pCluster);
+    
+    return pCluster;
+}
+
+
+Cluster::Cluster() :
+    m_pSegment(NULL),
+    m_index(0),
+    m_start(0),
+    m_size(0),
+    m_timecode(0),
+    m_pEntries(NULL),
+    m_entriesCount(0)
+{
+}
+
+Cluster::Cluster(
+    Segment* pSegment,
+    size_t idx,
+    long long off) :
+    m_pSegment(pSegment),
+    m_index(idx),
+    m_start(off),
+    m_size(0),
+    m_timecode(-1),
+    m_pEntries(NULL),
+    m_entriesCount(0)
+{
+}
+
+
+Cluster::~Cluster()
+{
+#if 0
+    while (!m_pEntries.empty())
+    {
+        BlockEntry* pBlockEntry = m_pEntries.front();
+        assert(pBlockEntry);
+        
+        m_pEntries.pop_front();
+        delete pBlockEntry;
+    }
+#else
+    BlockEntry** i = m_pEntries;
+    BlockEntry** const j = m_pEntries + m_entriesCount;
+    while (i != j)
+    {
+         BlockEntry* p = *i++;
+   
+         assert(p);
+         delete p;
+    }
+ 
+    delete[] m_pEntries;
+#endif
+
+}
+
+bool Cluster::EOS() const
+{
+    return (m_pSegment == 0);
+}
+
+
+void Cluster::LoadBlockEntries()
+{
+    if (m_pEntries)
+        return;
+
+    Load();    
+    assert(m_timecode >= 0);
+    assert(m_start > 0);
+    assert(m_size > 0);
+    
+    IMkvReader* const pReader = m_pSegment->m_pReader;
+    
+    long long pos = m_start;
+    const long long stop = m_start + m_size;
+    long long timecode = -1;
+   
+    long long idx = pos;
+
+    m_entriesCount = 0;
+    
+    while (idx < stop)
+    {
+        if (Match(pReader, idx, 0x67, timecode))
+            assert(timecode == m_timecode);
+        else 
+        {
+            long len;
+            
+            const long long id = ReadUInt(pReader, idx, len);
+            assert(id >= 0);  //TODO
+            assert((idx + len) <= stop);
+            
+            idx += len;  //consume id
+            
+            const long long size = ReadUInt(pReader, idx, len);
+            assert(size >= 0);  //TODO
+            assert((idx + len) <= stop);
+            
+            idx += len;  //consume size
+            
+            if (id == 0x20)  //BlockGroup ID
+                ++m_entriesCount;
+            else if (id == 0x23)  //SimpleBlock ID
+                ++m_entriesCount;
+
+            idx += size;  //consume payload
+
+            assert(idx <= stop);
+        }  
+    }
+
+    if (m_entriesCount == 0)
+        return;
+     
+    m_pEntries = new BlockEntry*[m_entriesCount];
+    size_t index = 0;
+    
+    while (pos < stop)
+    {
+        if (Match(pReader, pos, 0x67, timecode))
+            assert(timecode == m_timecode);
+        else
+        {
+            long len;
+            const long long id = ReadUInt(pReader, pos, len);
+            assert(id >= 0);  //TODO
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume id
+            
+            const long long size = ReadUInt(pReader, pos, len);
+            assert(size >= 0);  //TODO
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume size
+            
+            if (id == 0x20)  //BlockGroup ID
+                ParseBlockGroup(pos, size, index++);
+            else if (id == 0x23)  //SimpleBlock ID
+                ParseSimpleBlock(pos, size, index++);
+
+            pos += size;  //consume payload
+            assert(pos <= stop);
+        }
+    }
+    
+    assert(pos == stop);
+    assert(timecode >= 0);
+    assert(index == m_entriesCount);
+}
+
+
+
+long long Cluster::GetTimeCode()
+{
+    Load();
+    return m_timecode;
+}
+
+
+long long Cluster::GetTime()
+{
+    const long long tc = GetTimeCode();
+    assert(tc >= 0);
+    
+    const SegmentInfo* const pInfo = m_pSegment->GetInfo();
+    assert(pInfo);
+    
+    const long long scale = pInfo->GetTimeCodeScale();
+    assert(scale >= 1);
+    
+    const long long t = m_timecode * scale;
+
+    return t;
+}
+
+
+void Cluster::ParseBlockGroup(long long start, long long size, size_t index)
+{
+    assert(m_pEntries);
+    assert(m_entriesCount);
+    assert(index < m_entriesCount);
+    
+    BlockGroup* const pGroup = new BlockGroup(this, index, start, size);
+    assert(pGroup);  //TODO
+        
+    m_pEntries[index] = pGroup;
+}
+
+
+
+void Cluster::ParseSimpleBlock(long long start, long long size, size_t index)
+{
+    assert(m_pEntries);
+    assert(m_entriesCount);
+    assert(index < m_entriesCount);
+
+    SimpleBlock* const pSimpleBlock = new SimpleBlock(this, index, start, size);
+    assert(pSimpleBlock);  //TODO
+        
+    m_pEntries[index] = pSimpleBlock;
+}
+
+
+const BlockEntry* Cluster::GetFirst()
+{
+    LoadBlockEntries();
+    
+    return m_pEntries[0];
+}
+
+        
+const BlockEntry* Cluster::GetLast()
+{ 
+    if (m_entriesCount == 0)
+        return m_pEntries[0];
+    
+    return m_pEntries[m_entriesCount-1];
+}
+
+        
+const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const
+{
+    assert(pEntry);
+    
+    size_t idx = pEntry->GetIndex();
+    
+    ++idx;
+
+    if (idx == m_entriesCount) 
+      return NULL;
+
+    return m_pEntries[idx];
+
+}
+
+
+const BlockEntry* Cluster::GetEntry(const Track* pTrack)
+{
+
+    assert(pTrack);
+    
+    if (m_pSegment == NULL)  //EOS
+        return pTrack->GetEOS();
+    
+    LoadBlockEntries();
+    
+    BlockEntry* i = *m_pEntries;
+    BlockEntry* j = *m_pEntries + m_entriesCount;
+    while (i != j)
+    {
+        BlockEntry* pEntry = i;
+        i++;
+        assert(pEntry);
+        assert(!pEntry->EOS());
+        
+        const Block* const pBlock = pEntry->GetBlock();
+        assert(pBlock);
+        
+        if (pBlock->GetTrackNumber() != pTrack->GetNumber())
+            continue;
+
+        if (pTrack->VetEntry(pEntry))
+            return pEntry;
+    }
+    
+    return pTrack->GetEOS();  //no satisfactory block found
+}
+
+
+BlockEntry::BlockEntry()
+{
+}
+
+
+BlockEntry::~BlockEntry()
+{
+}
+
+
+
+SimpleBlock::SimpleBlock(
+    Cluster* pCluster, 
+    size_t idx, 
+    long long start, 
+    long long size) :
+    m_pCluster(pCluster),
+    m_index(idx),
+    m_block(start, size, pCluster->m_pSegment->m_pReader)
+{
+}
+
+
+bool SimpleBlock::EOS() const
+{
+    return false;
+}
+
+
+Cluster* SimpleBlock::GetCluster() const
+{
+    return m_pCluster;
+}
+
+
+size_t SimpleBlock::GetIndex() const
+{
+    return m_index;
+}
+
+
+const Block* SimpleBlock::GetBlock() const
+{
+    return &m_block;
+}
+
+
+bool SimpleBlock::IsBFrame() const
+{
+    return false;
+}
+
+
+BlockGroup::BlockGroup(
+    Cluster* pCluster, 
+    size_t idx, 
+    long long start, 
+    long long size_) :
+    m_pCluster(pCluster),
+    m_index(idx),
+    m_prevTimeCode(0),
+    m_nextTimeCode(0),
+    m_pBlock(NULL)  //TODO: accept multiple blocks within a block group
+{
+    IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
+    
+    long long pos = start;
+    const long long stop = start + size_;
+ 
+    bool bSimpleBlock = false;
+    
+    while (pos < stop)
+    {
+        short t;
+    
+        if (Match(pReader, pos, 0x7B, t))
+        {    
+            if (t < 0)
+                m_prevTimeCode = t;
+            else if (t > 0)
+                m_nextTimeCode = t;
+            else
+                assert(false);
+        }
+        else
+        {
+            long len;
+            const long long id = ReadUInt(pReader, pos, len);
+            assert(id >= 0);  //TODO
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume ID
+            
+            const long long size = ReadUInt(pReader, pos, len);
+            assert(size >= 0);  //TODO
+            assert((pos + len) <= stop);
+            
+            pos += len;  //consume size
+            
+            switch (id)
+            {
+                case 0x23:  //SimpleBlock ID
+                    bSimpleBlock = true;
+                    //YES, FALL THROUGH TO NEXT CASE
+
+                case 0x21:  //Block ID
+                    ParseBlock(pos, size);                    
+                    break;
+                    
+                default:
+                    break;
+            }
+                
+            pos += size;  //consume payload
+            assert(pos <= stop);
+        }
+    }
+    
+    assert(pos == stop);
+    assert(m_pBlock);
+    
+    if (!bSimpleBlock)
+        m_pBlock->SetKey(m_prevTimeCode >= 0);
+}
+
+
+BlockGroup::~BlockGroup()
+{
+    delete m_pBlock;
+}
+
+
+void BlockGroup::ParseBlock(long long start, long long size)
+{   
+    IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
+    
+    Block* const pBlock = new Block(start, size, pReader);
+    assert(pBlock);  //TODO
+
+    //TODO: the Matroska spec says you have multiple blocks within the 
+    //same block group, with blocks ranked by priority (the flag bits).
+    //I haven't ever seen such a file (mkvmux certainly doesn't make
+    //one), so until then I'll just assume block groups contain a single
+    //block.
+#if 0    
+    m_blocks.push_back(pBlock);
+#else
+    assert(m_pBlock == NULL);
+    m_pBlock = pBlock;
+#endif
+
+#if 0
+    Track* const pTrack = pBlock->GetTrack();
+    assert(pTrack);
+    
+    pTrack->Insert(pBlock);
+#endif
+}
+
+
+bool BlockGroup::EOS() const
+{
+    return false;
+}
+
+
+Cluster* BlockGroup::GetCluster() const
+{
+    return m_pCluster;
+}
+
+
+size_t BlockGroup::GetIndex() const
+{
+    return m_index;
+}
+
+
+const Block* BlockGroup::GetBlock() const
+{
+    return m_pBlock;
+}
+
+
+short BlockGroup::GetPrevTimeCode() const
+{
+    return m_prevTimeCode;
+}
+
+
+short BlockGroup::GetNextTimeCode() const
+{
+    return m_nextTimeCode;
+}    
+
+
+bool BlockGroup::IsBFrame() const
+{
+    return (m_nextTimeCode > 0);
+}
+
+
+
+Block::Block(long long start, long long size_, IMkvReader* pReader) :
+    m_start(start),
+    m_size(size_)
+{
+    long long pos = start;
+    const long long stop = start + size_;
+
+    long len;
+    
+    m_track = ReadUInt(pReader, pos, len);
+    assert(m_track > 0);
+    assert((pos + len) <= stop);
+    
+    pos += len;  //consume track number
+    assert((stop - pos) >= 2);
+    
+    m_timecode = Unserialize2SInt(pReader, pos);
+
+    pos += 2;
+    assert((stop - pos) >= 1);
+    
+    const long hr = pReader->Read(pos, 1, &m_flags);
+    assert(hr == 0L);
+
+    ++pos;
+    assert(pos <= stop);
+    
+    m_frameOff = pos;
+    
+    const long long frame_size = stop - pos;
+
+    assert(frame_size <= 2147483647L);
+    
+    m_frameSize = static_cast<long>(frame_size);
+}
+
+
+long long Block::GetTimeCode(Cluster* pCluster) const
+{
+    assert(pCluster);
+    
+    const long long tc0 = pCluster->GetTimeCode();
+    assert(tc0 >= 0);
+    
+    const long long tc = tc0 + static_cast<long long>(m_timecode);
+    assert(tc >= 0);
+    
+    return tc;  //unscaled timecode units
+}
+
+
+long long Block::GetTime(Cluster* pCluster) const
+{
+    assert(pCluster);
+    
+    const long long tc = GetTimeCode(pCluster);
+    
+    const Segment* const pSegment = pCluster->m_pSegment;
+    const SegmentInfo* const pInfo = pSegment->GetInfo();
+    assert(pInfo);
+    
+    const long long scale = pInfo->GetTimeCodeScale();
+    assert(scale >= 1);
+    
+    const long long ns = tc * scale;
+
+    return ns;
+}
+
+
+unsigned long Block::GetTrackNumber() const
+{
+    assert(m_track > 0);
+    
+    return static_cast<unsigned long>(m_track);
+}
+
+
+bool Block::IsKey() const
+{
+    return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);
+}
+
+
+void Block::SetKey(bool bKey)
+{
+    if (bKey)
+        m_flags |= static_cast<unsigned char>(1 << 7);
+    else
+        m_flags &= 0x7F;
+}
+
+
+long Block::GetSize() const
+{
+    return m_frameSize;
+}
+
+
+long Block::Read(IMkvReader* pReader, unsigned char* buf) const
+{
+
+    assert(pReader);
+    assert(buf);
+    
+    const long hr = pReader->Read(m_frameOff, m_frameSize, buf);
+    
+    return hr;
+}
+
+
+}  //end namespace mkvparser
diff --git a/media/libstagefright/matroska/mkvparser.hpp b/media/libstagefright/matroska/mkvparser.hpp
new file mode 100644
index 0000000..4d311b4
--- /dev/null
+++ b/media/libstagefright/matroska/mkvparser.hpp
@@ -0,0 +1,428 @@
+#ifndef MKVPARSER_HPP
+#define MKVPARSER_HPP
+
+#include <cstdlib>
+#include <cstdio>
+
+namespace mkvparser
+{
+
+const int E_FILE_FORMAT_INVALID = -2;
+const int E_BUFFER_NOT_FULL = -3;
+
+class IMkvReader
+{
+public:
+    virtual int Read(long long position, long length, unsigned char* buffer) = 0;
+    virtual int Length(long long* total, long long* available) = 0; 	
+protected:
+    virtual ~IMkvReader();
+};
+
+long long GetUIntLength(IMkvReader*, long long, long&);
+long long ReadUInt(IMkvReader*, long long, long&);
+long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&);
+long long UnserializeUInt(IMkvReader*, long long pos, long long size);
+float Unserialize4Float(IMkvReader*, long long);
+double Unserialize8Double(IMkvReader*, long long);
+short Unserialize2SInt(IMkvReader*, long long);
+signed char Unserialize1SInt(IMkvReader*, long long);
+bool Match(IMkvReader*, long long&, unsigned long, long long&);
+bool Match(IMkvReader*, long long&, unsigned long, char*&);
+bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&,
+           size_t *optionalSize = NULL);
+bool Match(IMkvReader*, long long&, unsigned long, double&);
+bool Match(IMkvReader*, long long&, unsigned long, short&);
+
+
+struct EBMLHeader
+{
+    EBMLHeader();
+    ~EBMLHeader();  
+    long long m_version;
+    long long m_readVersion;
+    long long m_maxIdLength;
+    long long m_maxSizeLength;
+    char* m_docType;
+    long long m_docTypeVersion;
+    long long m_docTypeReadVersion;
+    
+    long long Parse(IMkvReader*, long long&);
+};
+
+
+class Segment;
+class Track;
+class Cluster;
+
+class Block
+{
+    Block(const Block&);
+    Block& operator=(const Block&);
+
+public:
+    const long long m_start;
+    const long long m_size;
+    
+    Block(long long start, long long size, IMkvReader*);
+    
+    unsigned long GetTrackNumber() const;
+    
+    long long GetTimeCode(Cluster*) const;  //absolute, but not scaled
+    long long GetTime(Cluster*) const;      //absolute, and scaled (nanosecond units)
+    bool IsKey() const;
+    void SetKey(bool);
+
+    long GetSize() const;
+    long Read(IMkvReader*, unsigned char*) const;
+    
+private:
+    long long m_track;   //Track::Number()
+    short m_timecode;  //relative to cluster
+    unsigned char m_flags;
+    long long m_frameOff;
+    long m_frameSize;    
+
+};
+
+
+class BlockEntry
+{
+    BlockEntry(const BlockEntry&);
+    BlockEntry& operator=(const BlockEntry&);
+    
+public:
+    virtual ~BlockEntry();
+    virtual bool EOS() const = 0;
+    virtual Cluster* GetCluster() const = 0;
+    virtual size_t GetIndex() const = 0;
+    virtual const Block* GetBlock() const = 0;
+    virtual bool IsBFrame() const = 0;
+    
+protected:
+    BlockEntry();
+
+};
+
+
+class SimpleBlock : public BlockEntry
+{
+    SimpleBlock(const SimpleBlock&);
+    SimpleBlock& operator=(const SimpleBlock&);
+
+public:
+    SimpleBlock(Cluster*, size_t, long long start, long long size);
+
+    bool EOS() const;
+    Cluster* GetCluster() const; 
+    size_t GetIndex() const;
+    const Block* GetBlock() const;
+    bool IsBFrame() const;
+
+protected:
+    Cluster* const m_pCluster;
+    const size_t m_index;
+    Block m_block;
+    
+};
+
+
+class BlockGroup : public BlockEntry
+{
+    BlockGroup(const BlockGroup&);
+    BlockGroup& operator=(const BlockGroup&);
+
+public:
+    BlockGroup(Cluster*, size_t, long long, long long);
+    ~BlockGroup();
+    
+    bool EOS() const;
+    Cluster* GetCluster() const; 
+    size_t GetIndex() const;
+    const Block* GetBlock() const;
+    bool IsBFrame() const;
+    
+    short GetPrevTimeCode() const;  //relative to block's time
+    short GetNextTimeCode() const;  //as above
+    
+protected:
+    Cluster* const m_pCluster;
+    const size_t m_index;
+    
+private:
+    BlockGroup(Cluster*, size_t, unsigned long);
+    void ParseBlock(long long start, long long size);
+
+    short m_prevTimeCode;
+    short m_nextTimeCode;
+    
+    //TODO: the Matroska spec says you can have multiple blocks within the 
+    //same block group, with blocks ranked by priority (the flag bits).
+    //For now we just cache a single block.
+#if 0
+    typedef std::deque<Block*> blocks_t;
+    blocks_t m_blocks;  //In practice should contain only a single element.
+#else
+    Block* m_pBlock;
+#endif
+    
+};
+
+
+class Track
+{
+    Track(const Track&);
+    Track& operator=(const Track&);
+
+public:    
+    Segment* const m_pSegment;
+    virtual ~Track();
+    
+    long long GetType() const; 
+    unsigned long GetNumber() const;
+    const char* GetNameAsUTF8() const;
+    const char* GetCodecNameAsUTF8() const;
+    const char* GetCodecId() const;
+    const unsigned char* GetCodecPrivate(
+            size_t *optionalSize = NULL) const;
+    
+    const BlockEntry* GetEOS() const;
+    
+    struct Settings 
+    {
+        long long start;
+        long long size;
+    };
+    
+    struct Info
+    {
+        long long type;
+        long long number;
+        long long uid;
+        char* nameAsUTF8;
+        char* codecId;
+        unsigned char* codecPrivate;
+        size_t codecPrivateSize;
+        char* codecNameAsUTF8;
+        Settings settings;
+        Info();
+        void Clear();
+    };
+    
+    long GetFirst(const BlockEntry*&) const;
+    long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
+    virtual bool VetEntry(const BlockEntry*) const = 0;
+        
+protected:
+    Track(Segment*, const Info&);        
+    const Info m_info;
+
+    class EOSBlock : public BlockEntry
+    {
+    public:
+        EOSBlock();
+
+        bool EOS() const;    
+        Cluster* GetCluster() const;
+        size_t GetIndex() const;
+        const Block* GetBlock() const;
+        bool IsBFrame() const;
+    };
+    
+    EOSBlock m_eos;
+    
+};
+
+
+class VideoTrack : public Track
+{
+    VideoTrack(const VideoTrack&);
+    VideoTrack& operator=(const VideoTrack&);
+    
+public:
+    VideoTrack(Segment*, const Info&);    
+    long long GetWidth() const;
+    long long GetHeight() const;
+    double GetFrameRate() const;
+    
+    bool VetEntry(const BlockEntry*) const;
+
+private:
+    long long m_width;
+    long long m_height;
+    double m_rate;
+    
+};
+
+
+class AudioTrack : public Track
+{
+    AudioTrack(const AudioTrack&);
+    AudioTrack& operator=(const AudioTrack&);
+
+public:
+    AudioTrack(Segment*, const Info&);    
+    double GetSamplingRate() const;
+    long long GetChannels() const;
+    long long GetBitDepth() const;    
+    bool VetEntry(const BlockEntry*) const;
+
+private:
+    double m_rate;
+    long long m_channels;
+    long long m_bitDepth;
+};
+
+
+class Tracks
+{
+    Tracks(const Tracks&);
+    Tracks& operator=(const Tracks&);
+
+public:
+    Segment* const m_pSegment;
+    const long long m_start;
+    const long long m_size;
+    
+    Tracks(Segment*, long long start, long long size);
+    virtual ~Tracks();
+
+    Track* GetTrackByNumber(unsigned long tn) const;
+    Track* GetTrackByIndex(unsigned long idx) const;
+    
+private:
+    Track** m_trackEntries; 
+    Track** m_trackEntriesEnd;
+
+    void ParseTrackEntry(long long, long long, Track*&);
+    
+public:
+    unsigned long GetTracksCount() const;
+};
+
+
+class SegmentInfo
+{
+    SegmentInfo(const SegmentInfo&);
+    SegmentInfo& operator=(const SegmentInfo&);
+    
+public:
+    Segment* const m_pSegment;
+    const long long m_start;
+    const long long m_size;
+    
+    SegmentInfo(Segment*, long long start, long long size);
+    ~SegmentInfo();
+    long long GetTimeCodeScale() const;
+    long long GetDuration() const;  //scaled
+    const char* GetMuxingAppAsUTF8() const;
+    const char* GetWritingAppAsUTF8() const;
+    const char* GetTitleAsUTF8() const;
+    
+private:
+    long long m_timecodeScale;
+    double m_duration;
+    char* m_pMuxingAppAsUTF8;
+    char* m_pWritingAppAsUTF8;
+    char* m_pTitleAsUTF8;
+};
+
+
+class Cluster
+{
+    Cluster(const Cluster&);
+    Cluster& operator=(const Cluster&);
+
+public:
+    Segment* const m_pSegment;
+    const size_t m_index;
+    
+public:    
+    static Cluster* Parse(Segment*, size_t, long long off);
+
+    Cluster();  //EndOfStream
+    ~Cluster();
+    
+    bool EOS() const;
+    
+    long long GetTimeCode();  //absolute, but not scaled
+    long long GetTime();      //absolute, and scaled (nanosecond units)
+
+    const BlockEntry* GetFirst();
+    const BlockEntry* GetLast();
+    const BlockEntry* GetNext(const BlockEntry*) const;    
+    const BlockEntry* GetEntry(const Track*);
+protected:    
+    Cluster(Segment*, size_t, long long off);
+    
+private:
+    long long m_start;
+    long long m_size;    
+    long long m_timecode;
+    BlockEntry** m_pEntries;
+    size_t m_entriesCount;
+   
+    void Load();
+    void LoadBlockEntries();
+    void ParseBlockGroup(long long, long long, size_t);
+    void ParseSimpleBlock(long long, long long, size_t);
+    
+};
+
+
+class Segment
+{
+    Segment(const Segment&);
+    Segment& operator=(const Segment&);
+
+private:
+    Segment(IMkvReader*, long long pos, long long size);
+
+public:
+    IMkvReader* const m_pReader;
+    const long long m_start;  //posn of segment payload
+    const long long m_size;   //size of segment payload
+    Cluster m_eos;  //TODO: make private?
+    
+    static long long CreateInstance(IMkvReader*, long long, Segment*&);
+    ~Segment();
+
+    //for big-bang loading (source filter)
+    long Load();
+
+    //for incremental loading (splitter)    
+    long long Unparsed() const;
+    long long ParseHeaders();
+    long ParseCluster(Cluster*&, long long& newpos) const;
+    bool AddCluster(Cluster*, long long);
+
+    Tracks* GetTracks() const;    
+    const SegmentInfo* const GetInfo() const;
+    long long GetDuration() const;
+    
+    //NOTE: this turned out to be too inefficient.
+    //long long Load(long long time_nanoseconds);
+
+    Cluster* GetFirst();
+    Cluster* GetLast();
+    unsigned long GetCount() const;
+    
+    Cluster* GetNext(const Cluster*);
+    Cluster* GetCluster(long long time_nanoseconds);
+    
+private:
+    long long m_pos;  //absolute file posn; what has been consumed so far    
+    SegmentInfo* m_pInfo;
+    Tracks* m_pTracks;    
+    Cluster** m_clusters;
+    size_t m_clusterCount;
+
+    void ParseSeekHead(long long pos, long long size, size_t*);
+    void ParseSeekEntry(long long pos, long long size, size_t*);
+    void ParseSecondarySeekHead(long long off, size_t*);
+};
+
+
+}  //end namespace mkvparser
+
+#endif  //MKVPARSER_HPP
diff --git a/media/libstagefright/mpeg2ts/ABitReader.cpp b/media/libstagefright/mpeg2ts/ABitReader.cpp
new file mode 100644
index 0000000..24c8df8
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ABitReader.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ABitReader.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+ABitReader::ABitReader(const uint8_t *data, size_t size)
+    : mData(data),
+      mSize(size),
+      mReservoir(0),
+      mNumBitsLeft(0) {
+}
+
+void ABitReader::fillReservoir() {
+    CHECK_GT(mSize, 0u);
+
+    mReservoir = 0;
+    size_t i;
+    for (i = 0; mSize > 0 && i < 4; ++i) {
+        mReservoir = (mReservoir << 8) | *mData;
+
+        ++mData;
+        --mSize;
+    }
+
+    mNumBitsLeft = 8 * i;
+    mReservoir <<= 32 - mNumBitsLeft;
+}
+
+uint32_t ABitReader::getBits(size_t n) {
+    CHECK_LE(n, 32u);
+
+    uint32_t result = 0;
+    while (n > 0) {
+        if (mNumBitsLeft == 0) {
+            fillReservoir();
+        }
+
+        size_t m = n;
+        if (m > mNumBitsLeft) {
+            m = mNumBitsLeft;
+        }
+
+        result = (result << m) | (mReservoir >> (32 - m));
+        mReservoir <<= m;
+        mNumBitsLeft -= m;
+
+        n -= m;
+    }
+
+    return result;
+}
+
+void ABitReader::skipBits(size_t n) {
+    while (n > 32) {
+        getBits(32);
+        n -= 32;
+    }
+
+    if (n > 0) {
+        getBits(n);
+    }
+}
+
+void ABitReader::putBits(uint32_t x, size_t n) {
+    CHECK_LE(mNumBitsLeft + n, 32u);
+
+    mReservoir = (mReservoir >> n) | (x << (32 - n));
+    mNumBitsLeft += n;
+}
+
+size_t ABitReader::numBitsLeft() const {
+    return mSize * 8 + mNumBitsLeft;
+}
+
+const uint8_t *ABitReader::data() const {
+    CHECK_EQ(mNumBitsLeft % 8, 0u);
+
+    return mData - mNumBitsLeft / 8;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/mpeg2ts/ABitReader.h b/media/libstagefright/mpeg2ts/ABitReader.h
new file mode 100644
index 0000000..5135211
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ABitReader.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 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 A_BIT_READER_H_
+
+#define A_BIT_READER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+
+namespace android {
+
+struct ABitReader {
+    ABitReader(const uint8_t *data, size_t size);
+
+    uint32_t getBits(size_t n);
+    void skipBits(size_t n);
+
+    size_t numBitsLeft() const;
+
+    const uint8_t *data() const;
+
+private:
+    const uint8_t *mData;
+    size_t mSize;
+
+    uint32_t mReservoir;  // left-aligned bits
+    size_t mNumBitsLeft;
+
+    void fillReservoir();
+    void putBits(uint32_t x, size_t n);
+
+    DISALLOW_EVIL_CONSTRUCTORS(ABitReader);
+};
+
+}  // namespace android
+
+#endif  // A_BIT_READER_H_
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
new file mode 100644
index 0000000..d05975d
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -0,0 +1,941 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ATSParser.h"
+
+#include "ABitReader.h"
+#include "AnotherPacketSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+static const size_t kTSPacketSize = 188;
+
+struct ATSParser::Program : public RefBase {
+    Program(unsigned programMapPID);
+
+    bool parsePID(
+            unsigned pid, unsigned payload_unit_start_indicator,
+            ABitReader *br);
+
+    sp<MediaSource> getSource(SourceType type);
+
+private:
+    unsigned mProgramMapPID;
+    KeyedVector<unsigned, sp<Stream> > mStreams;
+
+    void parseProgramMap(ABitReader *br);
+
+    DISALLOW_EVIL_CONSTRUCTORS(Program);
+};
+
+struct ATSParser::Stream : public RefBase {
+    Stream(unsigned elementaryPID, unsigned streamType);
+
+    void parse(
+            unsigned payload_unit_start_indicator,
+            ABitReader *br);
+
+    sp<MediaSource> getSource(SourceType type);
+
+protected:
+    virtual ~Stream();
+
+private:
+    unsigned mElementaryPID;
+    unsigned mStreamType;
+
+    sp<ABuffer> mBuffer;
+    sp<AnotherPacketSource> mSource;
+    bool mPayloadStarted;
+
+    void flush();
+    void parsePES(ABitReader *br);
+
+    void onPayloadData(
+            unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
+            const uint8_t *data, size_t size);
+
+    DISALLOW_EVIL_CONSTRUCTORS(Stream);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::Program::Program(unsigned programMapPID)
+    : mProgramMapPID(programMapPID) {
+}
+
+bool ATSParser::Program::parsePID(
+        unsigned pid, unsigned payload_unit_start_indicator,
+        ABitReader *br) {
+    if (pid == mProgramMapPID) {
+        if (payload_unit_start_indicator) {
+            unsigned skip = br->getBits(8);
+            br->skipBits(skip * 8);
+        }
+
+        parseProgramMap(br);
+        return true;
+    }
+
+    ssize_t index = mStreams.indexOfKey(pid);
+    if (index < 0) {
+        return false;
+    }
+
+    mStreams.editValueAt(index)->parse(
+            payload_unit_start_indicator, br);
+
+    return true;
+}
+
+void ATSParser::Program::parseProgramMap(ABitReader *br) {
+    unsigned table_id = br->getBits(8);
+    LOG(VERBOSE) << "  table_id = " << table_id;
+    CHECK_EQ(table_id, 0x02u);
+
+    unsigned section_syntax_indictor = br->getBits(1);
+    LOG(VERBOSE) << "  section_syntax_indictor = " << section_syntax_indictor;
+    CHECK_EQ(section_syntax_indictor, 1u);
+
+    CHECK_EQ(br->getBits(1), 0u);
+    LOG(VERBOSE) << "  reserved = " << br->getBits(2);
+
+    unsigned section_length = br->getBits(12);
+    LOG(VERBOSE) << "  section_length = " << section_length;
+    CHECK((section_length & 0xc00) == 0);
+    CHECK_LE(section_length, 1021u);
+
+    LOG(VERBOSE) << "  program_number = " << br->getBits(16);
+    LOG(VERBOSE) << "  reserved = " << br->getBits(2);
+    LOG(VERBOSE) << "  version_number = " << br->getBits(5);
+    LOG(VERBOSE) << "  current_next_indicator = " << br->getBits(1);
+    LOG(VERBOSE) << "  section_number = " << br->getBits(8);
+    LOG(VERBOSE) << "  last_section_number = " << br->getBits(8);
+    LOG(VERBOSE) << "  reserved = " << br->getBits(3);
+
+    LOG(VERBOSE) << "  PCR_PID = "
+              << StringPrintf("0x%04x", br->getBits(13));
+
+    LOG(VERBOSE) << "  reserved = " << br->getBits(4);
+
+    unsigned program_info_length = br->getBits(12);
+    LOG(VERBOSE) << "  program_info_length = " << program_info_length;
+    CHECK((program_info_length & 0xc00) == 0);
+
+    br->skipBits(program_info_length * 8);  // skip descriptors
+
+    // infoBytesRemaining is the number of bytes that make up the
+    // variable length section of ES_infos. It does not include the
+    // final CRC.
+    size_t infoBytesRemaining = section_length - 9 - program_info_length - 4;
+
+    while (infoBytesRemaining > 0) {
+        CHECK_GE(infoBytesRemaining, 5u);
+
+        unsigned streamType = br->getBits(8);
+        LOG(VERBOSE) << "    stream_type = "
+                  << StringPrintf("0x%02x", streamType);
+
+        LOG(VERBOSE) << "    reserved = " << br->getBits(3);
+
+        unsigned elementaryPID = br->getBits(13);
+        LOG(VERBOSE) << "    elementary_PID = "
+                  << StringPrintf("0x%04x", elementaryPID);
+
+        LOG(VERBOSE) << "    reserved = " << br->getBits(4);
+
+        unsigned ES_info_length = br->getBits(12);
+        LOG(VERBOSE) << "    ES_info_length = " << ES_info_length;
+        CHECK((ES_info_length & 0xc00) == 0);
+
+        CHECK_GE(infoBytesRemaining - 5, ES_info_length);
+
+#if 0
+        br->skipBits(ES_info_length * 8);  // skip descriptors
+#else
+        unsigned info_bytes_remaining = ES_info_length;
+        while (info_bytes_remaining >= 2) {
+            LOG(VERBOSE) << "      tag = " << StringPrintf("0x%02x", br->getBits(8));
+
+            unsigned descLength = br->getBits(8);
+            LOG(VERBOSE) << "      len = " << descLength;
+
+            CHECK_GE(info_bytes_remaining, 2 + descLength);
+
+            br->skipBits(descLength * 8);
+
+            info_bytes_remaining -= descLength + 2;
+        }
+        CHECK_EQ(info_bytes_remaining, 0u);
+#endif
+
+        ssize_t index = mStreams.indexOfKey(elementaryPID);
+#if 0  // XXX revisit
+        CHECK_LT(index, 0);
+        mStreams.add(elementaryPID, new Stream(elementaryPID, streamType));
+#else
+        if (index < 0) {
+            mStreams.add(elementaryPID, new Stream(elementaryPID, streamType));
+        }
+#endif
+
+        infoBytesRemaining -= 5 + ES_info_length;
+    }
+
+    CHECK_EQ(infoBytesRemaining, 0u);
+
+    LOG(VERBOSE) << "  CRC = " << StringPrintf("0x%08x", br->getBits(32));
+}
+
+sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
+    for (size_t i = 0; i < mStreams.size(); ++i) {
+        sp<MediaSource> source = mStreams.editValueAt(i)->getSource(type);
+        if (source != NULL) {
+            return source;
+        }
+    }
+
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::Stream::Stream(unsigned elementaryPID, unsigned streamType)
+    : mElementaryPID(elementaryPID),
+      mStreamType(streamType),
+      mBuffer(new ABuffer(65536)),
+      mPayloadStarted(false) {
+    mBuffer->setRange(0, 0);
+}
+
+ATSParser::Stream::~Stream() {
+}
+
+void ATSParser::Stream::parse(
+        unsigned payload_unit_start_indicator, ABitReader *br) {
+    if (payload_unit_start_indicator) {
+        if (mPayloadStarted) {
+            // Otherwise we run the danger of receiving the trailing bytes
+            // of a PES packet that we never saw the start of and assuming
+            // we have a a complete PES packet.
+
+            flush();
+        }
+
+        mPayloadStarted = true;
+    }
+
+    if (!mPayloadStarted) {
+        return;
+    }
+
+    size_t payloadSizeBits = br->numBitsLeft();
+    CHECK_EQ(payloadSizeBits % 8, 0u);
+
+    CHECK_LE(mBuffer->size() + payloadSizeBits / 8, mBuffer->capacity());
+
+    memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
+    mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
+}
+
+void ATSParser::Stream::parsePES(ABitReader *br) {
+    unsigned packet_startcode_prefix = br->getBits(24);
+
+    LOG(VERBOSE) << "packet_startcode_prefix = "
+              << StringPrintf("0x%08x", packet_startcode_prefix);
+
+    CHECK_EQ(packet_startcode_prefix, 0x000001u);
+
+    unsigned stream_id = br->getBits(8);
+    LOG(VERBOSE) << "stream_id = " << StringPrintf("0x%02x", stream_id);
+
+    unsigned PES_packet_length = br->getBits(16);
+    LOG(VERBOSE) << "PES_packet_length = " << PES_packet_length;
+
+    if (stream_id != 0xbc  // program_stream_map
+            && stream_id != 0xbe  // padding_stream
+            && stream_id != 0xbf  // private_stream_2
+            && stream_id != 0xf0  // ECM
+            && stream_id != 0xf1  // EMM
+            && stream_id != 0xff  // program_stream_directory
+            && stream_id != 0xf2  // DSMCC
+            && stream_id != 0xf8) {  // H.222.1 type E
+        CHECK_EQ(br->getBits(2), 2u);
+
+        LOG(VERBOSE) << "PES_scrambling_control = " << br->getBits(2);
+        LOG(VERBOSE) << "PES_priority = " << br->getBits(1);
+        LOG(VERBOSE) << "data_alignment_indicator = " << br->getBits(1);
+        LOG(VERBOSE) << "copyright = " << br->getBits(1);
+        LOG(VERBOSE) << "original_or_copy = " << br->getBits(1);
+
+        unsigned PTS_DTS_flags = br->getBits(2);
+        LOG(VERBOSE) << "PTS_DTS_flags = " << PTS_DTS_flags;
+
+        unsigned ESCR_flag = br->getBits(1);
+        LOG(VERBOSE) << "ESCR_flag = " << ESCR_flag;
+
+        unsigned ES_rate_flag = br->getBits(1);
+        LOG(VERBOSE) << "ES_rate_flag = " << ES_rate_flag;
+
+        unsigned DSM_trick_mode_flag = br->getBits(1);
+        LOG(VERBOSE) << "DSM_trick_mode_flag = " << DSM_trick_mode_flag;
+
+        unsigned additional_copy_info_flag = br->getBits(1);
+        LOG(VERBOSE) << "additional_copy_info_flag = "
+                  << additional_copy_info_flag;
+
+        LOG(VERBOSE) << "PES_CRC_flag = " << br->getBits(1);
+        LOG(VERBOSE) << "PES_extension_flag = " << br->getBits(1);
+
+        unsigned PES_header_data_length = br->getBits(8);
+        LOG(VERBOSE) << "PES_header_data_length = " << PES_header_data_length;
+
+        unsigned optional_bytes_remaining = PES_header_data_length;
+
+        uint64_t PTS = 0, DTS = 0;
+
+        if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
+            CHECK_GE(optional_bytes_remaining, 5u);
+
+            CHECK_EQ(br->getBits(4), PTS_DTS_flags);
+
+            PTS = ((uint64_t)br->getBits(3)) << 30;
+            CHECK_EQ(br->getBits(1), 1u);
+            PTS |= ((uint64_t)br->getBits(15)) << 15;
+            CHECK_EQ(br->getBits(1), 1u);
+            PTS |= br->getBits(15);
+            CHECK_EQ(br->getBits(1), 1u);
+
+            LOG(VERBOSE) << "PTS = " << PTS;
+            // LOG(INFO) << "PTS = " << PTS / 90000.0f << " secs";
+
+            optional_bytes_remaining -= 5;
+
+            if (PTS_DTS_flags == 3) {
+                CHECK_GE(optional_bytes_remaining, 5u);
+
+                CHECK_EQ(br->getBits(4), 1u);
+
+                DTS = ((uint64_t)br->getBits(3)) << 30;
+                CHECK_EQ(br->getBits(1), 1u);
+                DTS |= ((uint64_t)br->getBits(15)) << 15;
+                CHECK_EQ(br->getBits(1), 1u);
+                DTS |= br->getBits(15);
+                CHECK_EQ(br->getBits(1), 1u);
+
+                LOG(VERBOSE) << "DTS = " << DTS;
+
+                optional_bytes_remaining -= 5;
+            }
+        }
+
+        if (ESCR_flag) {
+            CHECK_GE(optional_bytes_remaining, 6u);
+
+            br->getBits(2);
+
+            uint64_t ESCR = ((uint64_t)br->getBits(3)) << 30;
+            CHECK_EQ(br->getBits(1), 1u);
+            ESCR |= ((uint64_t)br->getBits(15)) << 15;
+            CHECK_EQ(br->getBits(1), 1u);
+            ESCR |= br->getBits(15);
+            CHECK_EQ(br->getBits(1), 1u);
+
+            LOG(VERBOSE) << "ESCR = " << ESCR;
+            LOG(VERBOSE) << "ESCR_extension = " << br->getBits(9);
+
+            CHECK_EQ(br->getBits(1), 1u);
+
+            optional_bytes_remaining -= 6;
+        }
+
+        if (ES_rate_flag) {
+            CHECK_GE(optional_bytes_remaining, 3u);
+
+            CHECK_EQ(br->getBits(1), 1u);
+            LOG(VERBOSE) << "ES_rate = " << br->getBits(22);
+            CHECK_EQ(br->getBits(1), 1u);
+
+            optional_bytes_remaining -= 3;
+        }
+
+        br->skipBits(optional_bytes_remaining * 8);
+
+        // ES data follows.
+
+        onPayloadData(
+                PTS_DTS_flags, PTS, DTS,
+                br->data(), br->numBitsLeft() / 8);
+
+        if (PES_packet_length != 0) {
+            CHECK_GE(PES_packet_length, PES_header_data_length + 3);
+
+            unsigned dataLength =
+                PES_packet_length - 3 - PES_header_data_length;
+
+            CHECK_EQ(br->numBitsLeft(), dataLength * 8);
+
+            br->skipBits(dataLength * 8);
+        } else {
+            size_t payloadSizeBits = br->numBitsLeft();
+            CHECK((payloadSizeBits % 8) == 0);
+
+            LOG(VERBOSE) << "There's " << (payloadSizeBits / 8)
+                         << " bytes of payload.";
+        }
+    } else if (stream_id == 0xbe) {  // padding_stream
+        CHECK_NE(PES_packet_length, 0u);
+        br->skipBits(PES_packet_length * 8);
+    } else {
+        CHECK_NE(PES_packet_length, 0u);
+        br->skipBits(PES_packet_length * 8);
+    }
+}
+
+void ATSParser::Stream::flush() {
+    if (mBuffer->size() == 0) {
+        return;
+    }
+
+    LOG(VERBOSE) << "flushing stream "
+                 << StringPrintf("0x%04x", mElementaryPID)
+                 << " size = " << mBuffer->size();
+
+    ABitReader br(mBuffer->data(), mBuffer->size());
+    parsePES(&br);
+
+    mBuffer->setRange(0, 0);
+}
+
+static sp<ABuffer> FindNAL(
+        const uint8_t *data, size_t size, unsigned nalType,
+        size_t *stopOffset) {
+    bool foundStart = false;
+    size_t startOffset = 0;
+
+    size_t offset = 0;
+    for (;;) {
+        while (offset + 3 < size
+                && memcmp("\x00\x00\x00\x01", &data[offset], 4)) {
+            ++offset;
+        }
+
+        if (foundStart) {
+            size_t nalSize;
+            if (offset + 3 >= size) {
+                nalSize = size - startOffset;
+            } else {
+                nalSize = offset - startOffset;
+            }
+
+            sp<ABuffer> nal = new ABuffer(nalSize);
+            memcpy(nal->data(), &data[startOffset], nalSize);
+
+            if (stopOffset != NULL) {
+                *stopOffset = startOffset + nalSize;
+            }
+
+            return nal;
+        }
+
+        if (offset + 4 >= size) {
+            return NULL;
+        }
+
+        if ((data[offset + 4] & 0x1f) == nalType) {
+            foundStart = true;
+            startOffset = offset + 4;
+        }
+
+        offset += 4;
+    }
+}
+
+static unsigned parseUE(ABitReader *br) {
+    unsigned numZeroes = 0;
+    while (br->getBits(1) == 0) {
+        ++numZeroes;
+    }
+
+    unsigned x = br->getBits(numZeroes);
+
+    return x + (1u << numZeroes) - 1;
+}
+
+// Determine video dimensions from the sequence parameterset.
+static void FindDimensions(
+        const sp<ABuffer> seqParamSet, int32_t *width, int32_t *height) {
+    ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1);
+
+    unsigned profile_idc = br.getBits(8);
+    br.skipBits(16);
+    parseUE(&br);  // seq_parameter_set_id
+
+    if (profile_idc == 100 || profile_idc == 110
+            || profile_idc == 122 || profile_idc == 144) {
+        TRESPASS();
+    }
+
+    parseUE(&br);  // log2_max_frame_num_minus4
+    unsigned pic_order_cnt_type = parseUE(&br);
+
+    if (pic_order_cnt_type == 0) {
+        parseUE(&br);  // log2_max_pic_order_cnt_lsb_minus4
+    } else if (pic_order_cnt_type == 1) {
+        br.getBits(1);  // delta_pic_order_always_zero_flag
+        parseUE(&br);  // offset_for_non_ref_pic
+        parseUE(&br);  // offset_for_top_to_bottom_field
+
+        unsigned num_ref_frames_in_pic_order_cnt_cycle = parseUE(&br);
+        for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) {
+            parseUE(&br);  // offset_for_ref_frame
+        }
+    }
+
+    parseUE(&br);  // num_ref_frames
+    br.getBits(1);  // gaps_in_frame_num_value_allowed_flag
+
+    unsigned pic_width_in_mbs_minus1 = parseUE(&br);
+    unsigned pic_height_in_map_units_minus1 = parseUE(&br);
+    unsigned frame_mbs_only_flag = br.getBits(1);
+
+    *width = pic_width_in_mbs_minus1 * 16 + 16;
+
+    *height = (2 - frame_mbs_only_flag)
+        * (pic_height_in_map_units_minus1 * 16 + 16);
+}
+
+static sp<ABuffer> MakeAVCCodecSpecificData(
+        const sp<ABuffer> &buffer, int32_t *width, int32_t *height) {
+    const uint8_t *data = buffer->data();
+    size_t size = buffer->size();
+
+    sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL);
+    if (seqParamSet == NULL) {
+        return NULL;
+    }
+
+    FindDimensions(seqParamSet, width, height);
+
+    size_t stopOffset;
+    sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset);
+    CHECK(picParamSet != NULL);
+
+    buffer->setRange(stopOffset, size - stopOffset);
+    LOG(INFO) << "buffer has " << buffer->size() << " bytes left.";
+
+    size_t csdSize =
+        1 + 3 + 1 + 1
+        + 2 * 1 + seqParamSet->size()
+        + 1 + 2 * 1 + picParamSet->size();
+
+    sp<ABuffer> csd = new ABuffer(csdSize);
+    uint8_t *out = csd->data();
+
+    *out++ = 0x01;  // configurationVersion
+    memcpy(out, seqParamSet->data() + 1, 3);  // profile/level...
+    out += 3;
+    *out++ = (0x3f << 2) | 1;  // lengthSize == 2 bytes
+    *out++ = 0xe0 | 1;
+
+    *out++ = seqParamSet->size() >> 8;
+    *out++ = seqParamSet->size() & 0xff;
+    memcpy(out, seqParamSet->data(), seqParamSet->size());
+    out += seqParamSet->size();
+
+    *out++ = 1;
+
+    *out++ = picParamSet->size() >> 8;
+    *out++ = picParamSet->size() & 0xff;
+    memcpy(out, picParamSet->data(), picParamSet->size());
+
+    return csd;
+}
+
+static bool getNextNALUnit(
+        const uint8_t **_data, size_t *_size,
+        const uint8_t **nalStart, size_t *nalSize) {
+    const uint8_t *data = *_data;
+    size_t size = *_size;
+
+    *nalStart = NULL;
+    *nalSize = 0;
+
+    if (size == 0) {
+        return false;
+    }
+
+    size_t offset = 0;
+    for (;;) {
+        CHECK_LT(offset + 2, size);
+
+        if (!memcmp("\x00\x00\x01", &data[offset], 3)) {
+            break;
+        }
+
+        CHECK_EQ((unsigned)data[offset], 0x00u);
+        ++offset;
+    }
+
+    offset += 3;
+    size_t startOffset = offset;
+
+    while (offset + 2 < size
+            && memcmp("\x00\x00\x00", &data[offset], 3)
+            && memcmp("\x00\x00\x01", &data[offset], 3)) {
+        ++offset;
+    }
+
+    if (offset + 2 >= size) {
+        *nalStart = &data[startOffset];
+        *nalSize = size - startOffset;
+
+        *_data = NULL;
+        *_size = 0;
+
+        return true;
+    }
+
+    size_t endOffset = offset;
+
+    while (offset + 2 < size && memcmp("\x00\x00\x01", &data[offset], 3)) {
+        CHECK_EQ((unsigned)data[offset], 0x00u);
+        ++offset;
+    }
+
+    CHECK_LT(offset + 2, size);
+
+    *nalStart = &data[startOffset];
+    *nalSize = endOffset - startOffset;
+
+    *_data = &data[offset];
+    *_size = size - offset;
+
+    return true;
+}
+
+sp<ABuffer> MakeCleanAVCData(const uint8_t *data, size_t size) {
+    const uint8_t *tmpData = data;
+    size_t tmpSize = size;
+
+    size_t totalSize = 0;
+    const uint8_t *nalStart;
+    size_t nalSize;
+    while (getNextNALUnit(&tmpData, &tmpSize, &nalStart, &nalSize)) {
+        totalSize += 4 + nalSize;
+    }
+
+    sp<ABuffer> buffer = new ABuffer(totalSize);
+    size_t offset = 0;
+    while (getNextNALUnit(&data, &size, &nalStart, &nalSize)) {
+        memcpy(buffer->data() + offset, "\x00\x00\x00\x01", 4);
+        memcpy(buffer->data() + offset + 4, nalStart, nalSize);
+
+        offset += 4 + nalSize;
+    }
+
+    return buffer;
+}
+
+static sp<ABuffer> FindMPEG2ADTSConfig(
+        const sp<ABuffer> &buffer, int32_t *sampleRate, int32_t *channelCount) {
+    ABitReader br(buffer->data(), buffer->size());
+
+    CHECK_EQ(br.getBits(12), 0xfffu);
+    CHECK_EQ(br.getBits(1), 0u);
+    CHECK_EQ(br.getBits(2), 0u);
+    br.getBits(1);  // protection_absent
+    unsigned profile = br.getBits(2);
+    LOG(INFO) << "profile = " << profile;
+    CHECK_NE(profile, 3u);
+    unsigned sampling_freq_index = br.getBits(4);
+    br.getBits(1);  // private_bit
+    unsigned channel_configuration = br.getBits(3);
+    CHECK_NE(channel_configuration, 0u);
+
+    LOG(INFO) << "sampling_freq_index = " << sampling_freq_index;
+    LOG(INFO) << "channel_configuration = " << channel_configuration;
+
+    CHECK_LE(sampling_freq_index, 11u);
+    static const int32_t kSamplingFreq[] = {
+        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+        16000, 12000, 11025, 8000
+    };
+    *sampleRate = kSamplingFreq[sampling_freq_index];
+
+    *channelCount = channel_configuration;
+
+    static const uint8_t kStaticESDS[] = {
+        0x03, 22,
+        0x00, 0x00,     // ES_ID
+        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+        0x04, 17,
+        0x40,                       // Audio ISO/IEC 14496-3
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+
+        0x05, 2,
+        // AudioSpecificInfo follows
+
+        // oooo offf fccc c000
+        // o - audioObjectType
+        // f - samplingFreqIndex
+        // c - channelConfig
+    };
+    sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
+    memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
+
+    csd->data()[sizeof(kStaticESDS)] =
+        ((profile + 1) << 3) | (sampling_freq_index >> 1);
+
+    csd->data()[sizeof(kStaticESDS) + 1] =
+        ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
+
+    hexdump(csd->data(), csd->size());
+    return csd;
+}
+
+void ATSParser::Stream::onPayloadData(
+        unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
+        const uint8_t *data, size_t size) {
+    LOG(VERBOSE) << "onPayloadData mStreamType="
+                 << StringPrintf("0x%02x", mStreamType);
+
+    sp<ABuffer> buffer;
+
+    if (mStreamType == 0x1b) {
+        buffer = MakeCleanAVCData(data, size);
+    } else {
+        // hexdump(data, size);
+
+        buffer = new ABuffer(size);
+        memcpy(buffer->data(), data, size);
+    }
+
+    if (mSource == NULL) {
+        sp<MetaData> meta = new MetaData;
+
+        if (mStreamType == 0x1b) {
+            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+
+            int32_t width, height;
+            sp<ABuffer> csd = MakeAVCCodecSpecificData(buffer, &width, &height);
+
+            if (csd == NULL) {
+                return;
+            }
+
+            meta->setData(kKeyAVCC, 0, csd->data(), csd->size());
+            meta->setInt32(kKeyWidth, width);
+            meta->setInt32(kKeyHeight, height);
+        } else {
+            CHECK_EQ(mStreamType, 0x0fu);
+
+            meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+            int32_t sampleRate, channelCount;
+            sp<ABuffer> csd =
+                FindMPEG2ADTSConfig(buffer, &sampleRate, &channelCount);
+
+            LOG(INFO) << "sampleRate = " << sampleRate;
+            LOG(INFO) << "channelCount = " << channelCount;
+
+            meta->setInt32(kKeySampleRate, sampleRate);
+            meta->setInt32(kKeyChannelCount, channelCount);
+
+            meta->setData(kKeyESDS, 0, csd->data(), csd->size());
+        }
+
+        LOG(INFO) << "created source!";
+        mSource = new AnotherPacketSource(meta);
+
+        // fall through
+    }
+
+    CHECK(PTS_DTS_flags == 2 || PTS_DTS_flags == 3);
+    buffer->meta()->setInt64("time", (PTS * 100) / 9);
+
+    if (mStreamType == 0x0f) {
+        // WHY???
+        buffer->setRange(7, buffer->size() - 7);
+    }
+
+    mSource->queueAccessUnit(buffer);
+}
+
+sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
+    if ((type == AVC_VIDEO && mStreamType == 0x1b)
+        || (type == MPEG2ADTS_AUDIO && mStreamType == 0x0f)) {
+        return mSource;
+    }
+
+    return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::ATSParser() {
+}
+
+ATSParser::~ATSParser() {
+}
+
+void ATSParser::feedTSPacket(const void *data, size_t size) {
+    CHECK_EQ(size, kTSPacketSize);
+
+    ABitReader br((const uint8_t *)data, kTSPacketSize);
+    parseTS(&br);
+}
+
+void ATSParser::parseProgramAssociationTable(ABitReader *br) {
+    unsigned table_id = br->getBits(8);
+    LOG(VERBOSE) << "  table_id = " << table_id;
+    CHECK_EQ(table_id, 0x00u);
+
+    unsigned section_syntax_indictor = br->getBits(1);
+    LOG(VERBOSE) << "  section_syntax_indictor = " << section_syntax_indictor;
+    CHECK_EQ(section_syntax_indictor, 1u);
+
+    CHECK_EQ(br->getBits(1), 0u);
+    LOG(VERBOSE) << "  reserved = " << br->getBits(2);
+
+    unsigned section_length = br->getBits(12);
+    LOG(VERBOSE) << "  section_length = " << section_length;
+    CHECK((section_length & 0xc00) == 0);
+
+    LOG(VERBOSE) << "  transport_stream_id = " << br->getBits(16);
+    LOG(VERBOSE) << "  reserved = " << br->getBits(2);
+    LOG(VERBOSE) << "  version_number = " << br->getBits(5);
+    LOG(VERBOSE) << "  current_next_indicator = " << br->getBits(1);
+    LOG(VERBOSE) << "  section_number = " << br->getBits(8);
+    LOG(VERBOSE) << "  last_section_number = " << br->getBits(8);
+
+    size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
+    CHECK_EQ((numProgramBytes % 4), 0u);
+
+    for (size_t i = 0; i < numProgramBytes / 4; ++i) {
+        unsigned program_number = br->getBits(16);
+        LOG(VERBOSE) << "    program_number = " << program_number;
+
+        LOG(VERBOSE) << "    reserved = " << br->getBits(3);
+
+        if (program_number == 0) {
+            LOG(VERBOSE) << "    network_PID = "
+                      << StringPrintf("0x%04x", br->getBits(13));
+        } else {
+            unsigned programMapPID = br->getBits(13);
+
+            LOG(VERBOSE) << "    program_map_PID = "
+                      << StringPrintf("0x%04x", programMapPID);
+
+            mPrograms.push(new Program(programMapPID));
+        }
+    }
+
+    LOG(VERBOSE) << "  CRC = " << StringPrintf("0x%08x", br->getBits(32));
+}
+
+void ATSParser::parsePID(
+        ABitReader *br, unsigned PID,
+        unsigned payload_unit_start_indicator) {
+    if (PID == 0) {
+        if (payload_unit_start_indicator) {
+            unsigned skip = br->getBits(8);
+            br->skipBits(skip * 8);
+        }
+        parseProgramAssociationTable(br);
+        return;
+    }
+
+    bool handled = false;
+    for (size_t i = 0; i < mPrograms.size(); ++i) {
+        if (mPrograms.editItemAt(i)->parsePID(
+                    PID, payload_unit_start_indicator, br)) {
+            handled = true;
+            break;
+        }
+    }
+
+    if (!handled) {
+        LOG(WARNING) << "PID " << StringPrintf("0x%04x", PID)
+                     << " not handled.";
+    }
+}
+
+void ATSParser::parseAdaptationField(ABitReader *br) {
+    unsigned adaptation_field_length = br->getBits(8);
+    if (adaptation_field_length > 0) {
+        br->skipBits(adaptation_field_length * 8);  // XXX
+    }
+}
+
+void ATSParser::parseTS(ABitReader *br) {
+    LOG(VERBOSE) << "---";
+
+    unsigned sync_byte = br->getBits(8);
+    CHECK_EQ(sync_byte, 0x47u);
+
+    LOG(VERBOSE) << "transport_error_indicator = " << br->getBits(1);
+
+    unsigned payload_unit_start_indicator = br->getBits(1);
+    LOG(VERBOSE) << "payload_unit_start_indicator = "
+                 << payload_unit_start_indicator;
+
+    LOG(VERBOSE) << "transport_priority = " << br->getBits(1);
+
+    unsigned PID = br->getBits(13);
+    LOG(VERBOSE) << "PID = " << StringPrintf("0x%04x", PID);
+
+    LOG(VERBOSE) << "transport_scrambling_control = " << br->getBits(2);
+
+    unsigned adaptation_field_control = br->getBits(2);
+    LOG(VERBOSE) << "adaptation_field_control = " << adaptation_field_control;
+
+    LOG(VERBOSE) << "continuity_counter = " << br->getBits(4);
+
+    if (adaptation_field_control == 2 || adaptation_field_control == 3) {
+        parseAdaptationField(br);
+    }
+
+    if (adaptation_field_control == 1 || adaptation_field_control == 3) {
+        parsePID(br, PID, payload_unit_start_indicator);
+    }
+}
+
+sp<MediaSource> ATSParser::getSource(SourceType type) {
+    for (size_t i = 0; i < mPrograms.size(); ++i) {
+        sp<MediaSource> source = mPrograms.editItemAt(i)->getSource(type);
+
+        if (source != NULL) {
+            return source;
+        }
+    }
+
+    return NULL;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
new file mode 100644
index 0000000..1e22e7b
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 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 A_TS_PARSER_H_
+
+#define A_TS_PARSER_H_
+
+#include <sys/types.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Vector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABitReader;
+struct MediaSource;
+
+struct ATSParser : public RefBase {
+    ATSParser();
+
+    void feedTSPacket(const void *data, size_t size);
+
+    enum SourceType {
+        AVC_VIDEO,
+        MPEG2ADTS_AUDIO
+    };
+    sp<MediaSource> getSource(SourceType type);
+
+protected:
+    virtual ~ATSParser();
+
+private:
+    struct Program;
+    struct Stream;
+
+    Vector<sp<Program> > mPrograms;
+
+    void parseProgramAssociationTable(ABitReader *br);
+    void parseProgramMap(ABitReader *br);
+    void parsePES(ABitReader *br);
+
+    void parsePID(
+        ABitReader *br, unsigned PID,
+        unsigned payload_unit_start_indicator);
+
+    void parseAdaptationField(ABitReader *br);
+    void parseTS(ABitReader *br);
+
+    DISALLOW_EVIL_CONSTRUCTORS(ATSParser);
+};
+
+}  // namespace android
+
+#endif  // A_TS_PARSER_H_
diff --git a/media/libstagefright/mpeg2ts/Android.mk b/media/libstagefright/mpeg2ts/Android.mk
new file mode 100644
index 0000000..b6772eb
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=                 \
+        ABitReader.cpp            \
+        AnotherPacketSource.cpp   \
+        ATSParser.cpp             \
+        MPEG2TSExtractor.cpp      \
+
+LOCAL_C_INCLUDES:= \
+	$(JNI_H_INCLUDE) \
+	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+        $(TOP)/frameworks/base/media/libstagefright
+
+LOCAL_MODULE:= libstagefright_mpeg2ts
+
+ifeq ($(TARGET_ARCH),arm)
+    LOCAL_CFLAGS += -Wno-psabi
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
new file mode 100644
index 0000000..3d51177
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "AnotherPacketSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
+    : mFormat(meta),
+      mEOSResult(OK) {
+}
+
+AnotherPacketSource::~AnotherPacketSource() {
+}
+
+status_t AnotherPacketSource::start(MetaData *params) {
+    return OK;
+}
+
+status_t AnotherPacketSource::stop() {
+    return OK;
+}
+
+sp<MetaData> AnotherPacketSource::getFormat() {
+    return mFormat;
+}
+
+status_t AnotherPacketSource::read(
+        MediaBuffer **out, const ReadOptions *) {
+    *out = NULL;
+
+    Mutex::Autolock autoLock(mLock);
+    while (mEOSResult == OK && mBuffers.empty()) {
+        mCondition.wait(mLock);
+    }
+
+    if (!mBuffers.empty()) {
+        const sp<ABuffer> buffer = *mBuffers.begin();
+
+        uint64_t timeUs;
+        CHECK(buffer->meta()->findInt64(
+                    "time", (int64_t *)&timeUs));
+
+        MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
+        mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+        // hexdump(buffer->data(), buffer->size());
+
+        memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
+        *out = mediaBuffer;
+
+        mBuffers.erase(mBuffers.begin());
+        return OK;
+    }
+
+    return mEOSResult;
+}
+
+void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
+    int32_t damaged;
+    if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
+        // LOG(VERBOSE) << "discarding damaged AU";
+        return;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+    mBuffers.push_back(buffer);
+    mCondition.signal();
+}
+
+void AnotherPacketSource::signalEOS(status_t result) {
+    CHECK(result != OK);
+
+    Mutex::Autolock autoLock(mLock);
+    mEOSResult = result;
+    mCondition.signal();
+}
+
+bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) {
+    Mutex::Autolock autoLock(mLock);
+    if (!mBuffers.empty()) {
+        return true;
+    }
+
+    *finalResult = mEOSResult;
+    return false;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
new file mode 100644
index 0000000..ce83d21
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 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 ANOTHER_PACKET_SOURCE_H_
+
+#define ANOTHER_PACKET_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+
+namespace android {
+
+struct ABuffer;
+
+struct AnotherPacketSource : public MediaSource {
+    AnotherPacketSource(const sp<MetaData> &meta);
+
+    virtual status_t start(MetaData *params = NULL);
+    virtual status_t stop();
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+    bool hasBufferAvailable(status_t *finalResult);
+
+    void queueAccessUnit(const sp<ABuffer> &buffer);
+    void signalEOS(status_t result);
+
+protected:
+    virtual ~AnotherPacketSource();
+
+private:
+    Mutex mLock;
+    Condition mCondition;
+
+    sp<MetaData> mFormat;
+    List<sp<ABuffer> > mBuffers;
+    status_t mEOSResult;
+
+    DISALLOW_EVIL_CONSTRUCTORS(AnotherPacketSource);
+};
+
+
+}  // namespace android
+
+#endif  // ANOTHER_PACKET_SOURCE_H_
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
new file mode 100644
index 0000000..b287c95
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2010 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 "MPEG2TSExtractor"
+#include <utils/Log.h>
+
+#include "include/MPEG2TSExtractor.h"
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/String8.h>
+
+#include "AnotherPacketSource.h"
+#include "ATSParser.h"
+
+namespace android {
+
+struct MPEG2TSSource : public MediaSource {
+    MPEG2TSSource(
+            const sp<MPEG2TSExtractor> &extractor,
+            const sp<AnotherPacketSource> &impl);
+
+    virtual status_t start(MetaData *params = NULL);
+    virtual status_t stop();
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+private:
+    sp<MPEG2TSExtractor> mExtractor;
+    sp<AnotherPacketSource> mImpl;
+
+    DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource);
+};
+
+MPEG2TSSource::MPEG2TSSource(
+        const sp<MPEG2TSExtractor> &extractor,
+        const sp<AnotherPacketSource> &impl)
+    : mExtractor(extractor),
+      mImpl(impl) {
+}
+
+status_t MPEG2TSSource::start(MetaData *params) {
+    return mImpl->start(params);
+}
+
+status_t MPEG2TSSource::stop() {
+    return mImpl->stop();
+}
+
+sp<MetaData> MPEG2TSSource::getFormat() {
+    return mImpl->getFormat();
+}
+
+status_t MPEG2TSSource::read(
+        MediaBuffer **out, const ReadOptions *options) {
+    *out = NULL;
+
+    status_t finalResult;
+    while (!mImpl->hasBufferAvailable(&finalResult)) {
+        if (finalResult != OK) {
+            return ERROR_END_OF_STREAM;
+        }
+
+        status_t err = mExtractor->feedMore();
+        if (err != OK) {
+            mImpl->signalEOS(err);
+        }
+    }
+
+    return mImpl->read(out, options);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source)
+    : mDataSource(source),
+      mParser(new ATSParser),
+      mOffset(0) {
+    init();
+}
+
+size_t MPEG2TSExtractor::countTracks() {
+    return mSourceImpls.size();
+}
+
+sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) {
+    if (index >= mSourceImpls.size()) {
+        return NULL;
+    }
+
+    return new MPEG2TSSource(this, mSourceImpls.editItemAt(index));
+}
+
+sp<MetaData> MPEG2TSExtractor::getTrackMetaData(
+        size_t index, uint32_t flags) {
+    return index < mSourceImpls.size()
+        ? mSourceImpls.editItemAt(index)->getFormat() : NULL;
+}
+
+sp<MetaData> MPEG2TSExtractor::getMetaData() {
+    sp<MetaData> meta = new MetaData;
+    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+    return meta;
+}
+
+void MPEG2TSExtractor::init() {
+    bool haveAudio = false;
+    bool haveVideo = false;
+
+    while (feedMore() == OK) {
+        ATSParser::SourceType type;
+        if (haveAudio && haveVideo) {
+            break;
+        }
+        if (haveVideo) {
+            type = ATSParser::MPEG2ADTS_AUDIO;
+        } else {
+            type = ATSParser::AVC_VIDEO;
+        }
+        sp<AnotherPacketSource> impl =
+            (AnotherPacketSource *)mParser->getSource(type).get();
+
+        if (impl != NULL) {
+            if (type == ATSParser::MPEG2ADTS_AUDIO) {
+                haveAudio = true;
+            } else {
+                haveVideo = true;
+            }
+            mSourceImpls.push(impl);
+        }
+    }
+
+    LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo);
+}
+
+status_t MPEG2TSExtractor::feedMore() {
+    Mutex::Autolock autoLock(mLock);
+
+    static const size_t kTSPacketSize = 188;
+
+    uint8_t packet[kTSPacketSize];
+    ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
+
+    if (n < (ssize_t)kTSPacketSize) {
+        return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
+    }
+
+    mOffset += kTSPacketSize;
+    mParser->feedTSPacket(packet, kTSPacketSize);
+
+    return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SniffMPEG2TS(
+        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+#if 0
+    char header;
+    if (source->readAt(0, &header, 1) != 1 || header != 0x47) {
+        return false;
+    }
+
+    *confidence = 0.05f;
+    mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+    return true;
+#else
+    // For now we're going to never identify this type of stream, since we'd
+    // just base our decision on a single byte...
+    // Instead you can instantiate an MPEG2TSExtractor by explicitly stating
+    // its proper mime type in the call to MediaExtractor::Create(...).
+    return false;
+#endif
+}
+
+}  // namespace android
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 132e31b..6de761f 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -43,7 +43,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 struct OMX::CallbackDispatcher : public RefBase {
-    CallbackDispatcher(OMX *owner);
+    CallbackDispatcher(OMXNodeInstance *owner);
 
     void post(const omx_message &msg);
 
@@ -53,7 +53,7 @@
 private:
     Mutex mLock;
 
-    OMX *mOwner;
+    OMXNodeInstance *mOwner;
     bool mDone;
     Condition mQueueChanged;
     List<omx_message> mQueue;
@@ -69,7 +69,7 @@
     CallbackDispatcher &operator=(const CallbackDispatcher &);
 };
 
-OMX::CallbackDispatcher::CallbackDispatcher(OMX *owner)
+OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
     : mOwner(owner),
       mDone(false) {
     pthread_attr_t attr;
@@ -101,12 +101,11 @@
 }
 
 void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
-    OMXNodeInstance *instance = mOwner->findInstance(msg.node);
-    if (instance == NULL) {
+    if (mOwner == NULL) {
         LOGV("Would have dispatched a message to a node that's already gone.");
         return;
     }
-    instance->onMessage(msg);
+    mOwner->onMessage(msg);
 }
 
 // static
@@ -145,7 +144,6 @@
 
 OMX::OMX()
     : mMaster(new OMXMaster),
-      mDispatcher(new CallbackDispatcher(this)),
       mNodeCounter(0) {
 }
 
@@ -166,6 +164,10 @@
         instance = mLiveNodes.editValueAt(index);
         mLiveNodes.removeItemsAt(index);
 
+        index = mDispatchers.indexOfKey(instance->nodeID());
+        CHECK(index >= 0);
+        mDispatchers.removeItemsAt(index);
+
         invalidateNodeID_l(instance->nodeID());
     }
 
@@ -226,6 +228,7 @@
     }
 
     *node = makeNodeID(instance);
+    mDispatchers.add(*node, new CallbackDispatcher(instance));
 
     instance->setHandle(*node, handle);
 
@@ -241,6 +244,11 @@
     ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
     CHECK(index >= 0);
     mLiveNodes.removeItemsAt(index);
+
+    index = mDispatchers.indexOfKey(node);
+    CHECK(index >= 0);
+    mDispatchers.removeItemsAt(index);
+
     instance->observer()->asBinder()->unlinkToDeath(this);
 
     return instance->freeNode(mMaster);
@@ -341,7 +349,7 @@
     msg.u.event_data.data1 = nData1;
     msg.u.event_data.data2 = nData2;
 
-    mDispatcher->post(msg);
+    findDispatcher(node)->post(msg);
 
     return OMX_ErrorNone;
 }
@@ -355,7 +363,7 @@
     msg.node = node;
     msg.u.buffer_data.buffer = pBuffer;
 
-    mDispatcher->post(msg);
+    findDispatcher(node)->post(msg);
 
     return OMX_ErrorNone;
 }
@@ -375,7 +383,7 @@
     msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
     msg.u.extended_buffer_data.data_ptr = pBuffer->pBuffer;
 
-    mDispatcher->post(msg);
+    findDispatcher(node)->post(msg);
 
     return OMX_ErrorNone;
 }
@@ -397,6 +405,14 @@
     return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
 }
 
+sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
+    Mutex::Autolock autoLock(mLock);
+
+    ssize_t index = mDispatchers.indexOfKey(node);
+
+    return index < 0 ? NULL : mDispatchers.valueAt(index);
+}
+
 void OMX::invalidateNodeID(node_id node) {
     Mutex::Autolock autoLock(mLock);
     invalidateNodeID_l(node);
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 9a45bea..56b169a 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXMaster"
+#include <utils/Log.h>
+
 #include "OMXMaster.h"
 
 #include <dlfcn.h>
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index c1a010c..5db516e 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -264,6 +264,8 @@
         return UNKNOWN_ERROR;
     }
 
+    CHECK_EQ(header->pAppPrivate, buffer_meta);
+
     *buffer = header;
 
     addActiveBuffer(portIndex, *buffer);
@@ -294,6 +296,8 @@
         return UNKNOWN_ERROR;
     }
 
+    CHECK_EQ(header->pAppPrivate, buffer_meta);
+
     *buffer = header;
     *buffer_data = header->pBuffer;
 
@@ -325,6 +329,8 @@
         return UNKNOWN_ERROR;
     }
 
+    CHECK_EQ(header->pAppPrivate, buffer_meta);
+
     *buffer = header;
 
     addActiveBuffer(portIndex, *buffer);
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index ee117e5..8bf4336 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -17,7 +15,3 @@
 LOCAL_MODULE:= omx_tests
 
 include $(BUILD_EXECUTABLE)
-
-endif
-
-
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
new file mode 100644
index 0000000..3dfb200
--- /dev/null
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "AAVCAssembler.h"
+
+#include "ARTPSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+#include <stdint.h>
+
+#define BE_VERBOSE      0
+
+namespace android {
+
+// static
+AAVCAssembler::AAVCAssembler(const sp<AMessage> &notify)
+    : mNotifyMsg(notify),
+      mAccessUnitRTPTime(0),
+      mNextExpectedSeqNoValid(false),
+      mNextExpectedSeqNo(0),
+      mAccessUnitDamaged(false) {
+}
+
+AAVCAssembler::~AAVCAssembler() {
+}
+
+ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
+        const sp<ARTPSource> &source) {
+    List<sp<ABuffer> > *queue = source->queue();
+
+    if (queue->empty()) {
+        return NOT_ENOUGH_DATA;
+    }
+
+    if (mNextExpectedSeqNoValid) {
+        List<sp<ABuffer> >::iterator it = queue->begin();
+        while (it != queue->end()) {
+            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
+                break;
+            }
+
+            it = queue->erase(it);
+        }
+
+        if (queue->empty()) {
+            return NOT_ENOUGH_DATA;
+        }
+    }
+
+    sp<ABuffer> buffer = *queue->begin();
+
+    if (!mNextExpectedSeqNoValid) {
+        mNextExpectedSeqNoValid = true;
+        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
+    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
+#if BE_VERBOSE
+        LOG(VERBOSE) << "Not the sequence number I expected";
+#endif
+
+        return WRONG_SEQUENCE_NUMBER;
+    }
+
+    const uint8_t *data = buffer->data();
+    size_t size = buffer->size();
+
+    if (size < 1 || (data[0] & 0x80)) {
+        // Corrupt.
+
+        LOG(ERROR) << "Ignoring corrupt buffer.";
+        queue->erase(queue->begin());
+
+        ++mNextExpectedSeqNo;
+        return MALFORMED_PACKET;
+    }
+
+    unsigned nalType = data[0] & 0x1f;
+    if (nalType >= 1 && nalType <= 23) {
+        addSingleNALUnit(buffer);
+        queue->erase(queue->begin());
+        ++mNextExpectedSeqNo;
+        return OK;
+    } else if (nalType == 28) {
+        // FU-A
+        return addFragmentedNALUnit(queue);
+    } else if (nalType == 24) {
+        // STAP-A
+        bool success = addSingleTimeAggregationPacket(buffer);
+        queue->erase(queue->begin());
+        ++mNextExpectedSeqNo;
+
+        return success ? OK : MALFORMED_PACKET;
+    } else {
+        LOG(ERROR) << "Ignoring unsupported buffer (nalType=" << nalType << ")";
+
+        queue->erase(queue->begin());
+        ++mNextExpectedSeqNo;
+
+        return MALFORMED_PACKET;
+    }
+}
+
+void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
+#if BE_VERBOSE
+    LOG(VERBOSE) << "addSingleNALUnit of size " << buffer->size();
+    hexdump(buffer->data(), buffer->size());
+#endif
+
+    uint32_t rtpTime;
+    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+    if (!mNALUnits.empty() && rtpTime != mAccessUnitRTPTime) {
+        submitAccessUnit();
+    }
+    mAccessUnitRTPTime = rtpTime;
+
+    mNALUnits.push_back(buffer);
+}
+
+bool AAVCAssembler::addSingleTimeAggregationPacket(const sp<ABuffer> &buffer) {
+    const uint8_t *data = buffer->data();
+    size_t size = buffer->size();
+
+    if (size < 3) {
+        LOG(ERROR) << "Discarding too small STAP-A packet.";
+        return false;
+    }
+
+    ++data;
+    --size;
+    while (size >= 2) {
+        size_t nalSize = (data[0] << 8) | data[1];
+
+        if (size < nalSize + 2) {
+            LOG(ERROR) << "Discarding malformed STAP-A packet.";
+            return false;
+        }
+
+        sp<ABuffer> unit = new ABuffer(nalSize);
+        memcpy(unit->data(), &data[2], nalSize);
+
+        PropagateTimes(buffer, unit);
+
+        addSingleNALUnit(unit);
+
+        data += 2 + nalSize;
+        size -= 2 + nalSize;
+    }
+
+    if (size != 0) {
+        LOG(WARNING) << "Unexpected padding at end of STAP-A packet.";
+    }
+
+    return true;
+}
+
+ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
+        List<sp<ABuffer> > *queue) {
+    CHECK(!queue->empty());
+
+    sp<ABuffer> buffer = *queue->begin();
+    const uint8_t *data = buffer->data();
+    size_t size = buffer->size();
+
+    CHECK(size > 0);
+    unsigned indicator = data[0];
+
+    CHECK((indicator & 0x1f) == 28);
+
+    if (size < 2) {
+        LOG(ERROR) << "Ignoring malformed FU buffer (size = " << size << ")";
+
+        queue->erase(queue->begin());
+        ++mNextExpectedSeqNo;
+        return MALFORMED_PACKET;
+    }
+
+    if (!(data[1] & 0x80)) {
+        // Start bit not set on the first buffer.
+
+#if BE_VERBOSE
+        LOG(ERROR) << "Start bit not set on first buffer";
+#endif
+
+        queue->erase(queue->begin());
+        ++mNextExpectedSeqNo;
+        return MALFORMED_PACKET;
+    }
+
+    uint32_t nalType = data[1] & 0x1f;
+    uint32_t nri = (data[0] >> 5) & 3;
+
+    uint32_t expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
+    size_t totalSize = size - 2;
+    size_t totalCount = 1;
+    bool complete = false;
+
+    if (data[1] & 0x40) {
+        // Huh? End bit also set on the first buffer.
+
+#if BE_VERBOSE
+        LOG(WARNING) << "Grrr. This isn't fragmented at all.";
+#endif
+
+        complete = true;
+    } else {
+        List<sp<ABuffer> >::iterator it = ++queue->begin();
+        while (it != queue->end()) {
+#if BE_VERBOSE
+            LOG(VERBOSE) << "sequence length " << totalCount;
+#endif
+
+            const sp<ABuffer> &buffer = *it;
+
+            const uint8_t *data = buffer->data();
+            size_t size = buffer->size();
+
+            if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
+#if BE_VERBOSE
+                LOG(VERBOSE) << "sequence not complete, expected seqNo "
+                     << expectedSeqNo << ", got "
+                     << (uint32_t)buffer->int32Data();
+#endif
+
+                return WRONG_SEQUENCE_NUMBER;
+            }
+
+            if (size < 2
+                    || data[0] != indicator
+                    || (data[1] & 0x1f) != nalType
+                    || (data[1] & 0x80)) {
+                LOG(ERROR) << "Ignoring malformed FU buffer.\n";
+
+                // Delete the whole start of the FU.
+
+                it = queue->begin();
+                for (size_t i = 0; i <= totalCount; ++i) {
+                    it = queue->erase(it);
+                }
+
+                mNextExpectedSeqNo = expectedSeqNo + 1;
+
+                return MALFORMED_PACKET;
+            }
+
+            totalSize += size - 2;
+            ++totalCount;
+
+            expectedSeqNo = expectedSeqNo + 1;
+
+            if (data[1] & 0x40) {
+                // This is the last fragment.
+                complete = true;
+                break;
+            }
+
+            ++it;
+        }
+    }
+
+    if (!complete) {
+        return NOT_ENOUGH_DATA;
+    }
+
+    mNextExpectedSeqNo = expectedSeqNo;
+
+    // We found all the fragments that make up the complete NAL unit.
+
+    // Leave room for the header. So far totalSize did not include the
+    // header byte.
+    ++totalSize;
+
+    sp<ABuffer> unit = new ABuffer(totalSize);
+    PropagateTimes(buffer, unit);
+
+    unit->data()[0] = (nri << 5) | nalType;
+
+    size_t offset = 1;
+    List<sp<ABuffer> >::iterator it = queue->begin();
+    for (size_t i = 0; i < totalCount; ++i) {
+        const sp<ABuffer> &buffer = *it;
+
+#if BE_VERBOSE
+        LOG(VERBOSE) << "piece #" << (i + 1) << "/" << totalCount;
+        hexdump(buffer->data(), buffer->size());
+#endif
+
+        memcpy(unit->data() + offset, buffer->data() + 2, buffer->size() - 2);
+        offset += buffer->size() - 2;
+
+        it = queue->erase(it);
+    }
+
+    unit->setRange(0, totalSize);
+
+    addSingleNALUnit(unit);
+
+#if BE_VERBOSE
+    LOG(VERBOSE) << "successfully assembled a NAL unit from fragments.";
+#endif
+
+    return OK;
+}
+
+void AAVCAssembler::submitAccessUnit() {
+    CHECK(!mNALUnits.empty());
+
+#if BE_VERBOSE
+    LOG(VERBOSE) << "Access unit complete (" << mNALUnits.size() << " nal units)";
+#endif
+
+    uint64_t ntpTime;
+    CHECK((*mNALUnits.begin())->meta()->findInt64(
+                "ntp-time", (int64_t *)&ntpTime));
+
+    size_t totalSize = 0;
+    for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
+         it != mNALUnits.end(); ++it) {
+        totalSize += 4 + (*it)->size();
+    }
+
+    sp<ABuffer> accessUnit = new ABuffer(totalSize);
+    size_t offset = 0;
+    for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
+         it != mNALUnits.end(); ++it) {
+        memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4);
+        offset += 4;
+
+        sp<ABuffer> nal = *it;
+        memcpy(accessUnit->data() + offset, nal->data(), nal->size());
+        offset += nal->size();
+    }
+
+    accessUnit->meta()->setInt64("ntp-time", ntpTime);
+
+#if 0
+    printf(mAccessUnitDamaged ? "X" : ".");
+    fflush(stdout);
+#endif
+
+    if (mAccessUnitDamaged) {
+        accessUnit->meta()->setInt32("damaged", true);
+    }
+
+    mNALUnits.clear();
+    mAccessUnitDamaged = false;
+
+    sp<AMessage> msg = mNotifyMsg->dup();
+    msg->setObject("access-unit", accessUnit);
+    msg->post();
+}
+
+ARTPAssembler::AssemblyStatus AAVCAssembler::assembleMore(
+        const sp<ARTPSource> &source) {
+    AssemblyStatus status = addNALUnit(source);
+    if (status == MALFORMED_PACKET) {
+        mAccessUnitDamaged = true;
+    }
+    return status;
+}
+
+void AAVCAssembler::packetLost() {
+    CHECK(mNextExpectedSeqNoValid);
+    ++mNextExpectedSeqNo;
+
+    mAccessUnitDamaged = true;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/rtsp/AAVCAssembler.h b/media/libstagefright/rtsp/AAVCAssembler.h
new file mode 100644
index 0000000..1e97520
--- /dev/null
+++ b/media/libstagefright/rtsp/AAVCAssembler.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 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 A_AVC_ASSEMBLER_H_
+
+#define A_AVC_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+#include <utils/List.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+
+struct AAVCAssembler : public ARTPAssembler {
+    AAVCAssembler(const sp<AMessage> &notify);
+
+protected:
+    virtual ~AAVCAssembler();
+
+    virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+    virtual void packetLost();
+
+private:
+    sp<AMessage> mNotifyMsg;
+
+    uint32_t mAccessUnitRTPTime;
+    bool mNextExpectedSeqNoValid;
+    uint32_t mNextExpectedSeqNo;
+    bool mAccessUnitDamaged;
+    List<sp<ABuffer> > mNALUnits;
+
+    AssemblyStatus addNALUnit(const sp<ARTPSource> &source);
+    void addSingleNALUnit(const sp<ABuffer> &buffer);
+    AssemblyStatus addFragmentedNALUnit(List<sp<ABuffer> > *queue);
+    bool addSingleTimeAggregationPacket(const sp<ABuffer> &buffer);
+
+    void submitAccessUnit();
+
+    DISALLOW_EVIL_CONSTRUCTORS(AAVCAssembler);
+};
+
+}  // namespace android
+
+#endif  // A_AVC_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
new file mode 100644
index 0000000..7e55106
--- /dev/null
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "AMPEG4AudioAssembler.h"
+
+#include "ARTPSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+namespace android {
+
+AMPEG4AudioAssembler::AMPEG4AudioAssembler(const sp<AMessage> &notify)
+    : mNotifyMsg(notify),
+      mAccessUnitRTPTime(0),
+      mNextExpectedSeqNoValid(false),
+      mNextExpectedSeqNo(0),
+      mAccessUnitDamaged(false) {
+}
+
+AMPEG4AudioAssembler::~AMPEG4AudioAssembler() {
+}
+
+ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::assembleMore(
+        const sp<ARTPSource> &source) {
+    AssemblyStatus status = addPacket(source);
+    if (status == MALFORMED_PACKET) {
+        mAccessUnitDamaged = true;
+    }
+    return status;
+}
+
+ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::addPacket(
+        const sp<ARTPSource> &source) {
+    List<sp<ABuffer> > *queue = source->queue();
+
+    if (queue->empty()) {
+        return NOT_ENOUGH_DATA;
+    }
+
+    if (mNextExpectedSeqNoValid) {
+        List<sp<ABuffer> >::iterator it = queue->begin();
+        while (it != queue->end()) {
+            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
+                break;
+            }
+
+            it = queue->erase(it);
+        }
+
+        if (queue->empty()) {
+            return NOT_ENOUGH_DATA;
+        }
+    }
+
+    sp<ABuffer> buffer = *queue->begin();
+
+    if (!mNextExpectedSeqNoValid) {
+        mNextExpectedSeqNoValid = true;
+        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
+    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
+#if VERBOSE
+        LOG(VERBOSE) << "Not the sequence number I expected";
+#endif
+
+        return WRONG_SEQUENCE_NUMBER;
+    }
+
+    uint32_t rtpTime;
+    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
+        submitAccessUnit();
+    }
+    mAccessUnitRTPTime = rtpTime;
+
+    mPackets.push_back(buffer);
+
+    queue->erase(queue->begin());
+    ++mNextExpectedSeqNo;
+
+    return OK;
+}
+
+void AMPEG4AudioAssembler::submitAccessUnit() {
+    CHECK(!mPackets.empty());
+
+#if VERBOSE
+    LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)";
+#endif
+
+    uint64_t ntpTime;
+    CHECK((*mPackets.begin())->meta()->findInt64(
+                "ntp-time", (int64_t *)&ntpTime));
+
+    size_t totalSize = 0;
+    List<sp<ABuffer> >::iterator it = mPackets.begin();
+    while (it != mPackets.end()) {
+        const sp<ABuffer> &unit = *it;
+
+        size_t n = 0;
+        while (unit->data()[n] == 0xff) {
+            ++n;
+        }
+        ++n;
+
+        totalSize += unit->size() - n;
+        ++it;
+    }
+
+    sp<ABuffer> accessUnit = new ABuffer(totalSize);
+    size_t offset = 0;
+    it = mPackets.begin();
+    while (it != mPackets.end()) {
+        const sp<ABuffer> &unit = *it;
+
+        size_t n = 0;
+        while (unit->data()[n] == 0xff) {
+            ++n;
+        }
+        ++n;
+
+        memcpy((uint8_t *)accessUnit->data() + offset,
+               unit->data() + n, unit->size() - n);
+
+        offset += unit->size() - n;
+
+        ++it;
+    }
+
+    accessUnit->meta()->setInt64("ntp-time", ntpTime);
+
+#if 0
+    printf(mAccessUnitDamaged ? "X" : ".");
+    fflush(stdout);
+#endif
+
+    if (mAccessUnitDamaged) {
+        accessUnit->meta()->setInt32("damaged", true);
+    }
+
+    mPackets.clear();
+    mAccessUnitDamaged = false;
+
+    sp<AMessage> msg = mNotifyMsg->dup();
+    msg->setObject("access-unit", accessUnit);
+    msg->post();
+}
+
+void AMPEG4AudioAssembler::packetLost() {
+    CHECK(mNextExpectedSeqNoValid);
+    ++mNextExpectedSeqNo;
+
+    mAccessUnitDamaged = true;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h
new file mode 100644
index 0000000..5c2a2dd
--- /dev/null
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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 A_MPEG4_AUDIO_ASSEMBLER_H_
+
+#define A_MPEG4_AUDIO_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+#include <utils/List.h>
+
+#include <stdint.h>
+
+namespace android {
+
+struct AMessage;
+
+struct AMPEG4AudioAssembler : public ARTPAssembler {
+    AMPEG4AudioAssembler(const sp<AMessage> &notify);
+
+protected:
+    virtual ~AMPEG4AudioAssembler();
+
+    virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+    virtual void packetLost();
+
+private:
+    sp<AMessage> mNotifyMsg;
+    uint32_t mAccessUnitRTPTime;
+    bool mNextExpectedSeqNoValid;
+    uint32_t mNextExpectedSeqNo;
+    bool mAccessUnitDamaged;
+    List<sp<ABuffer> > mPackets;
+
+    AssemblyStatus addPacket(const sp<ARTPSource> &source);
+    void submitAccessUnit();
+
+    DISALLOW_EVIL_CONSTRUCTORS(AMPEG4AudioAssembler);
+};
+
+}  // namespace android
+
+#endif  // A_MPEG4_AUDIO_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
new file mode 100644
index 0000000..2869d54
--- /dev/null
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "APacketSource.h"
+
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+    value->clear();
+
+    size_t keyLen = strlen(key);
+
+    for (;;) {
+        const char *colonPos = strchr(s, ';');
+
+        size_t len =
+            (colonPos == NULL) ? strlen(s) : colonPos - s;
+
+        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
+            value->setTo(&s[keyLen + 1], len - keyLen - 1);
+            return true;
+        }
+
+        if (colonPos == NULL) {
+            return false;
+        }
+
+        s = colonPos + 1;
+    }
+}
+
+static sp<ABuffer> decodeHex(const AString &s) {
+    if ((s.size() % 2) != 0) {
+        return NULL;
+    }
+
+    size_t outLen = s.size() / 2;
+    sp<ABuffer> buffer = new ABuffer(outLen);
+    uint8_t *out = buffer->data();
+
+    uint8_t accum = 0;
+    for (size_t i = 0; i < s.size(); ++i) {
+        char c = s.c_str()[i];
+        unsigned value;
+        if (c >= '0' && c <= '9') {
+            value = c - '0';
+        } else if (c >= 'a' && c <= 'f') {
+            value = c - 'a' + 10;
+        } else if (c >= 'A' && c <= 'F') {
+            value = c - 'A' + 10;
+        } else {
+            return NULL;
+        }
+
+        accum = (accum << 4) | value;
+
+        if (i & 1) {
+            *out++ = accum;
+
+            accum = 0;
+        }
+    }
+
+    return buffer;
+}
+
+static sp<ABuffer> MakeAVCCodecSpecificData(const char *params) {
+    AString val;
+    CHECK(GetAttribute(params, "profile-level-id", &val));
+
+    sp<ABuffer> profileLevelID = decodeHex(val);
+    CHECK(profileLevelID != NULL);
+    CHECK_EQ(profileLevelID->size(), 3u);
+
+    Vector<sp<ABuffer> > paramSets;
+
+    size_t numSeqParameterSets = 0;
+    size_t totalSeqParameterSetSize = 0;
+    size_t numPicParameterSets = 0;
+    size_t totalPicParameterSetSize = 0;
+
+    CHECK(GetAttribute(params, "sprop-parameter-sets", &val));
+    size_t start = 0;
+    for (;;) {
+        ssize_t commaPos = val.find(",", start);
+        size_t end = (commaPos < 0) ? val.size() : commaPos;
+
+        AString nalString(val, start, end - start);
+        sp<ABuffer> nal = decodeBase64(nalString);
+        CHECK(nal != NULL);
+        CHECK_GT(nal->size(), 0u);
+        CHECK_LE(nal->size(), 65535u);
+
+        uint8_t nalType = nal->data()[0] & 0x1f;
+        if (numSeqParameterSets == 0) {
+            CHECK_EQ((unsigned)nalType, 7u);
+        } else if (numPicParameterSets > 0) {
+            CHECK_EQ((unsigned)nalType, 8u);
+        }
+        if (nalType == 7) {
+            ++numSeqParameterSets;
+            totalSeqParameterSetSize += nal->size();
+        } else  {
+            CHECK_EQ((unsigned)nalType, 8u);
+            ++numPicParameterSets;
+            totalPicParameterSetSize += nal->size();
+        }
+
+        paramSets.push(nal);
+
+        if (commaPos < 0) {
+            break;
+        }
+
+        start = commaPos + 1;
+    }
+
+    CHECK_LT(numSeqParameterSets, 32u);
+    CHECK_LE(numPicParameterSets, 255u);
+
+    size_t csdSize =
+        1 + 3 + 1 + 1
+        + 2 * numSeqParameterSets + totalSeqParameterSetSize
+        + 1 + 2 * numPicParameterSets + totalPicParameterSetSize;
+
+    sp<ABuffer> csd = new ABuffer(csdSize);
+    uint8_t *out = csd->data();
+
+    *out++ = 0x01;  // configurationVersion
+    memcpy(out, profileLevelID->data(), 3);
+    out += 3;
+    *out++ = (0x3f << 2) | 1;  // lengthSize == 2 bytes
+    *out++ = 0xe0 | numSeqParameterSets;
+
+    for (size_t i = 0; i < numSeqParameterSets; ++i) {
+        sp<ABuffer> nal = paramSets.editItemAt(i);
+
+        *out++ = nal->size() >> 8;
+        *out++ = nal->size() & 0xff;
+
+        memcpy(out, nal->data(), nal->size());
+
+        out += nal->size();
+    }
+
+    *out++ = numPicParameterSets;
+
+    for (size_t i = 0; i < numPicParameterSets; ++i) {
+        sp<ABuffer> nal = paramSets.editItemAt(i + numSeqParameterSets);
+
+        *out++ = nal->size() >> 8;
+        *out++ = nal->size() & 0xff;
+
+        memcpy(out, nal->data(), nal->size());
+
+        out += nal->size();
+    }
+
+    hexdump(csd->data(), csd->size());
+
+    return csd;
+}
+
+sp<ABuffer> MakeAACCodecSpecificData(const char *params) {
+    AString val;
+    CHECK(GetAttribute(params, "config", &val));
+
+    sp<ABuffer> config = decodeHex(val);
+    CHECK(config != NULL);
+    CHECK_GE(config->size(), 4u);
+
+    const uint8_t *data = config->data();
+    uint32_t x = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+    x = (x >> 1) & 0xffff;
+
+    static const uint8_t kStaticESDS[] = {
+        0x03, 22,
+        0x00, 0x00,     // ES_ID
+        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+        0x04, 17,
+        0x40,                       // Audio ISO/IEC 14496-3
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+
+        0x05, 2,
+        // AudioSpecificInfo follows
+    };
+
+    sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
+    memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
+    csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff;
+    csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff;
+
+    hexdump(csd->data(), csd->size());
+
+    return csd;
+}
+
+APacketSource::APacketSource(
+        const sp<ASessionDescription> &sessionDesc, size_t index)
+    : mFormat(new MetaData),
+      mEOSResult(OK) {
+    unsigned long PT;
+    AString desc;
+    AString params;
+    sessionDesc->getFormatType(index, &PT, &desc, &params);
+
+    int64_t durationUs;
+    if (sessionDesc->getDurationUs(&durationUs)) {
+        mFormat->setInt64(kKeyDuration, durationUs);
+    } else {
+        mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll);
+    }
+
+    if (!strncmp(desc.c_str(), "H264/", 5)) {
+        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+
+        int32_t width, height;
+        sessionDesc->getDimensions(index, PT, &width, &height);
+
+        mFormat->setInt32(kKeyWidth, width);
+        mFormat->setInt32(kKeyHeight, height);
+
+        sp<ABuffer> codecSpecificData =
+            MakeAVCCodecSpecificData(params.c_str());
+
+        mFormat->setData(
+                kKeyAVCC, 0,
+                codecSpecificData->data(), codecSpecificData->size());
+
+    } else if (!strncmp(desc.c_str(), "MP4A-LATM", 9)) {
+        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+        int32_t sampleRate, numChannels;
+        ASessionDescription::ParseFormatDesc(
+                desc.c_str(), &sampleRate, &numChannels);
+
+        mFormat->setInt32(kKeySampleRate, sampleRate);
+        mFormat->setInt32(kKeyChannelCount, numChannels);
+
+        sp<ABuffer> codecSpecificData =
+            MakeAACCodecSpecificData(params.c_str());
+
+        mFormat->setData(
+                kKeyESDS, 0,
+                codecSpecificData->data(), codecSpecificData->size());
+    } else {
+        TRESPASS();
+    }
+}
+
+APacketSource::~APacketSource() {
+}
+
+status_t APacketSource::start(MetaData *params) {
+    return OK;
+}
+
+status_t APacketSource::stop() {
+    return OK;
+}
+
+sp<MetaData> APacketSource::getFormat() {
+    return mFormat;
+}
+
+status_t APacketSource::read(
+        MediaBuffer **out, const ReadOptions *) {
+    *out = NULL;
+
+    Mutex::Autolock autoLock(mLock);
+    while (mEOSResult == OK && mBuffers.empty()) {
+        mCondition.wait(mLock);
+    }
+
+    if (!mBuffers.empty()) {
+        const sp<ABuffer> buffer = *mBuffers.begin();
+
+        uint64_t ntpTime;
+        CHECK(buffer->meta()->findInt64(
+                    "ntp-time", (int64_t *)&ntpTime));
+
+        int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
+
+        MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
+        mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+        memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
+        *out = mediaBuffer;
+
+        mBuffers.erase(mBuffers.begin());
+        return OK;
+    }
+
+    return mEOSResult;
+}
+
+void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
+    int32_t damaged;
+    if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
+        // LOG(VERBOSE) << "discarding damaged AU";
+        return;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+    mBuffers.push_back(buffer);
+    mCondition.signal();
+}
+
+void APacketSource::signalEOS(status_t result) {
+    CHECK(result != OK);
+
+    Mutex::Autolock autoLock(mLock);
+    mEOSResult = result;
+    mCondition.signal();
+}
+
+}  // namespace android
diff --git a/media/libstagefright/rtsp/APacketSource.h b/media/libstagefright/rtsp/APacketSource.h
new file mode 100644
index 0000000..4040eee
--- /dev/null
+++ b/media/libstagefright/rtsp/APacketSource.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 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 A_PACKET_SOURCE_H_
+
+#define A_PACKET_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+
+namespace android {
+
+struct ABuffer;
+struct ASessionDescription;
+
+struct APacketSource : public MediaSource {
+    APacketSource(const sp<ASessionDescription> &sessionDesc, size_t index);
+
+    virtual status_t start(MetaData *params = NULL);
+    virtual status_t stop();
+    virtual sp<MetaData> getFormat();
+
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+    void queueAccessUnit(const sp<ABuffer> &buffer);
+    void signalEOS(status_t result);
+
+protected:
+    virtual ~APacketSource();
+
+private:
+    Mutex mLock;
+    Condition mCondition;
+
+    sp<MetaData> mFormat;
+    List<sp<ABuffer> > mBuffers;
+    status_t mEOSResult;
+
+    DISALLOW_EVIL_CONSTRUCTORS(APacketSource);
+};
+
+
+}  // namespace android
+
+#endif  // A_PACKET_SOURCE_H_
diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp
new file mode 100644
index 0000000..24225b8
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ARTPAssembler.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <stdint.h>
+
+namespace android {
+
+static int64_t getNowUs() {
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+
+    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
+}
+
+ARTPAssembler::ARTPAssembler()
+    : mFirstFailureTimeUs(-1) {
+}
+
+void ARTPAssembler::PropagateTimes(
+        const sp<ABuffer> &from, const sp<ABuffer> &to) {
+    uint32_t rtpTime;
+    CHECK(from->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+    uint64_t ntpTime = 0;
+    CHECK(from->meta()->findInt64("ntp-time", (int64_t *)&ntpTime));
+
+    to->meta()->setInt32("rtp-time", rtpTime);
+    to->meta()->setInt64("ntp-time", ntpTime);
+}
+
+void ARTPAssembler::onPacketReceived(const sp<ARTPSource> &source) {
+    AssemblyStatus status;
+    for (;;) {
+        status = assembleMore(source);
+
+        if (status == WRONG_SEQUENCE_NUMBER) {
+            if (mFirstFailureTimeUs >= 0) {
+                if (getNowUs() - mFirstFailureTimeUs > 10000ll) {
+                    mFirstFailureTimeUs = -1;
+
+                    // LOG(VERBOSE) << "waited too long for packet.";
+                    packetLost();
+                    continue;
+                }
+            } else {
+                mFirstFailureTimeUs = getNowUs();
+            }
+            break;
+        } else {
+            mFirstFailureTimeUs = -1;
+
+            if (status == NOT_ENOUGH_DATA) {
+                break;
+            }
+        }
+    }
+}
+
+}  // namespace android
diff --git a/media/libstagefright/rtsp/ARTPAssembler.h b/media/libstagefright/rtsp/ARTPAssembler.h
new file mode 100644
index 0000000..892bd65
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPAssembler.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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 A_RTP_ASSEMBLER_H_
+
+#define A_RTP_ASSEMBLER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct ARTPSource;
+
+struct ARTPAssembler : public RefBase {
+    enum AssemblyStatus {
+        MALFORMED_PACKET,
+        WRONG_SEQUENCE_NUMBER,
+        NOT_ENOUGH_DATA,
+        OK
+    };
+
+    ARTPAssembler();
+
+    void onPacketReceived(const sp<ARTPSource> &source);
+
+protected:
+    static void PropagateTimes(
+        const sp<ABuffer> &from, const sp<ABuffer> &to);
+
+    virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source) = 0;
+    virtual void packetLost() = 0;
+
+private:
+    int64_t mFirstFailureTimeUs;
+
+    DISALLOW_EVIL_CONSTRUCTORS(ARTPAssembler);
+};
+
+}  // namespace android
+
+#endif  // A_RTP_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
new file mode 100644
index 0000000..a4413f0
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ARTPConnection.h"
+
+#include "ARTPSource.h"
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#define VERBOSE         0
+
+#if VERBOSE
+#include "hexdump.h"
+#endif
+
+namespace android {
+
+static uint16_t u16at(const uint8_t *data) {
+    return data[0] << 8 | data[1];
+}
+
+static uint32_t u32at(const uint8_t *data) {
+    return u16at(data) << 16 | u16at(&data[2]);
+}
+
+static uint64_t u64at(const uint8_t *data) {
+    return (uint64_t)(u32at(data)) << 32 | u32at(&data[4]);
+}
+
+// static
+const int64_t ARTPConnection::kSelectTimeoutUs = 1000ll;
+
+struct ARTPConnection::StreamInfo {
+    int mRTPSocket;
+    int mRTCPSocket;
+    sp<ASessionDescription> mSessionDesc;
+    size_t mIndex;
+    sp<AMessage> mNotifyMsg;
+};
+
+ARTPConnection::ARTPConnection()
+    : mPollEventPending(false) {
+}
+
+ARTPConnection::~ARTPConnection() {
+}
+
+void ARTPConnection::addStream(
+        int rtpSocket, int rtcpSocket,
+        const sp<ASessionDescription> &sessionDesc,
+        size_t index,
+        const sp<AMessage> &notify) {
+    sp<AMessage> msg = new AMessage(kWhatAddStream, id());
+    msg->setInt32("rtp-socket", rtpSocket);
+    msg->setInt32("rtcp-socket", rtcpSocket);
+    msg->setObject("session-desc", sessionDesc);
+    msg->setSize("index", index);
+    msg->setMessage("notify", notify);
+    msg->post();
+}
+
+void ARTPConnection::removeStream(int rtpSocket, int rtcpSocket) {
+    sp<AMessage> msg = new AMessage(kWhatRemoveStream, id());
+    msg->setInt32("rtp-socket", rtpSocket);
+    msg->setInt32("rtcp-socket", rtcpSocket);
+    msg->post();
+}
+
+static void bumpSocketBufferSize(int s) {
+    int size = 256 * 1024;
+    CHECK_EQ(setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)), 0);
+}
+
+// static
+void ARTPConnection::MakePortPair(
+        int *rtpSocket, int *rtcpSocket, unsigned *rtpPort) {
+    *rtpSocket = socket(AF_INET, SOCK_DGRAM, 0);
+    CHECK_GE(*rtpSocket, 0);
+
+    bumpSocketBufferSize(*rtpSocket);
+
+    *rtcpSocket = socket(AF_INET, SOCK_DGRAM, 0);
+    CHECK_GE(*rtcpSocket, 0);
+
+    bumpSocketBufferSize(*rtcpSocket);
+
+    unsigned start = (rand() * 1000)/ RAND_MAX + 15550;
+    start &= ~1;
+
+    for (unsigned port = start; port < 65536; port += 2) {
+        struct sockaddr_in addr;
+        memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+        addr.sin_family = AF_INET;
+        addr.sin_addr.s_addr = INADDR_ANY;
+        addr.sin_port = htons(port);
+
+        if (bind(*rtpSocket,
+                 (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
+            continue;
+        }
+
+        addr.sin_port = htons(port + 1);
+
+        if (bind(*rtcpSocket,
+                 (const struct sockaddr *)&addr, sizeof(addr)) == 0) {
+            *rtpPort = port;
+            return;
+        }
+    }
+
+    TRESPASS();
+}
+
+void ARTPConnection::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatAddStream:
+        {
+            onAddStream(msg);
+            break;
+        }
+
+        case kWhatRemoveStream:
+        {
+            onRemoveStream(msg);
+            break;
+        }
+
+        case kWhatPollStreams:
+        {
+            onPollStreams();
+            break;
+        }
+
+        default:
+        {
+            TRESPASS();
+            break;
+        }
+    }
+}
+
+void ARTPConnection::onAddStream(const sp<AMessage> &msg) {
+    mStreams.push_back(StreamInfo());
+    StreamInfo *info = &*--mStreams.end();
+
+    int32_t s;
+    CHECK(msg->findInt32("rtp-socket", &s));
+    info->mRTPSocket = s;
+    CHECK(msg->findInt32("rtcp-socket", &s));
+    info->mRTCPSocket = s;
+
+    sp<RefBase> obj;
+    CHECK(msg->findObject("session-desc", &obj));
+    info->mSessionDesc = static_cast<ASessionDescription *>(obj.get());
+
+    CHECK(msg->findSize("index", &info->mIndex));
+    CHECK(msg->findMessage("notify", &info->mNotifyMsg));
+
+    postPollEvent();
+}
+
+void ARTPConnection::onRemoveStream(const sp<AMessage> &msg) {
+    int32_t rtpSocket, rtcpSocket;
+    CHECK(msg->findInt32("rtp-socket", &rtpSocket));
+    CHECK(msg->findInt32("rtcp-socket", &rtcpSocket));
+
+    List<StreamInfo>::iterator it = mStreams.begin();
+    while (it != mStreams.end()
+           && (it->mRTPSocket != rtpSocket || it->mRTCPSocket != rtcpSocket)) {
+        ++it;
+    }
+
+    if (it == mStreams.end()) {
+        TRESPASS();
+    }
+
+    mStreams.erase(it);
+}
+
+void ARTPConnection::postPollEvent() {
+    if (mPollEventPending) {
+        return;
+    }
+
+    sp<AMessage> msg = new AMessage(kWhatPollStreams, id());
+    msg->post();
+
+    mPollEventPending = true;
+}
+
+void ARTPConnection::onPollStreams() {
+    mPollEventPending = false;
+
+    if (mStreams.empty()) {
+        return;
+    }
+
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = kSelectTimeoutUs;
+
+    fd_set rs;
+    FD_ZERO(&rs);
+
+    int maxSocket = -1;
+    for (List<StreamInfo>::iterator it = mStreams.begin();
+         it != mStreams.end(); ++it) {
+        FD_SET(it->mRTPSocket, &rs);
+        FD_SET(it->mRTCPSocket, &rs);
+
+        if (it->mRTPSocket > maxSocket) {
+            maxSocket = it->mRTPSocket;
+        }
+        if (it->mRTCPSocket > maxSocket) {
+            maxSocket = it->mRTCPSocket;
+        }
+    }
+
+    int res = select(maxSocket + 1, &rs, NULL, NULL, &tv);
+    CHECK_GE(res, 0);
+
+    if (res > 0) {
+        for (List<StreamInfo>::iterator it = mStreams.begin();
+             it != mStreams.end(); ++it) {
+            if (FD_ISSET(it->mRTPSocket, &rs)) {
+                receive(&*it, true);
+            }
+            if (FD_ISSET(it->mRTCPSocket, &rs)) {
+                receive(&*it, false);
+            }
+        }
+    }
+
+    postPollEvent();
+}
+
+status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
+    sp<ABuffer> buffer = new ABuffer(65536);
+
+    struct sockaddr_in from;
+    socklen_t fromSize = sizeof(from);
+
+    ssize_t nbytes = recvfrom(
+            receiveRTP ? s->mRTPSocket : s->mRTCPSocket,
+            buffer->data(),
+            buffer->capacity(),
+            0,
+            (struct sockaddr *)&from,
+            &fromSize);
+
+    if (nbytes < 0) {
+        return -1;
+    }
+
+    buffer->setRange(0, nbytes);
+
+    status_t err;
+    if (receiveRTP) {
+        err = parseRTP(s, buffer);
+    } else {
+        err = parseRTCP(s, buffer);
+    }
+
+    return err;
+}
+
+status_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
+    size_t size = buffer->size();
+
+    if (size < 12) {
+        // Too short to be a valid RTP header.
+        return -1;
+    }
+
+    const uint8_t *data = buffer->data();
+
+    if ((data[0] >> 6) != 2) {
+        // Unsupported version.
+        return -1;
+    }
+
+    if (data[0] & 0x20) {
+        // Padding present.
+
+        size_t paddingLength = data[size - 1];
+
+        if (paddingLength + 12 > size) {
+            // If we removed this much padding we'd end up with something
+            // that's too short to be a valid RTP header.
+            return -1;
+        }
+
+        size -= paddingLength;
+    }
+
+    int numCSRCs = data[0] & 0x0f;
+
+    size_t payloadOffset = 12 + 4 * numCSRCs;
+
+    if (size < payloadOffset) {
+        // Not enough data to fit the basic header and all the CSRC entries.
+        return -1;
+    }
+
+    if (data[0] & 0x10) {
+        // Header eXtension present.
+
+        if (size < payloadOffset + 4) {
+            // Not enough data to fit the basic header, all CSRC entries
+            // and the first 4 bytes of the extension header.
+
+            return -1;
+        }
+
+        const uint8_t *extensionData = &data[payloadOffset];
+
+        size_t extensionLength =
+            4 * (extensionData[2] << 8 | extensionData[3]);
+
+        if (size < payloadOffset + 4 + extensionLength) {
+            return -1;
+        }
+
+        payloadOffset += 4 + extensionLength;
+    }
+
+    uint32_t srcId = u32at(&data[8]);
+
+    sp<ARTPSource> source;
+    ssize_t index = mSources.indexOfKey(srcId);
+    if (index < 0) {
+        index = mSources.size();
+
+        source = new ARTPSource(
+                srcId, s->mSessionDesc, s->mIndex, s->mNotifyMsg);
+
+        mSources.add(srcId, source);
+    } else {
+        source = mSources.valueAt(index);
+    }
+
+    uint32_t rtpTime = u32at(&data[4]);
+
+    sp<AMessage> meta = buffer->meta();
+    meta->setInt32("ssrc", srcId);
+    meta->setInt32("rtp-time", rtpTime);
+    meta->setInt32("PT", data[1] & 0x7f);
+    meta->setInt32("M", data[1] >> 7);
+
+    buffer->setInt32Data(u16at(&data[2]));
+
+#if VERBOSE
+    printf("RTP = {\n"
+           "  PT: %d\n"
+           "  sequence number: %d\n"
+           "  RTP-time: 0x%08x\n"
+           "  M: %d\n"
+           "  SSRC: 0x%08x\n"
+           "}\n",
+           data[1] & 0x7f,
+           u16at(&data[2]),
+           rtpTime,
+           data[1] >> 7,
+           srcId);
+
+    // hexdump(&data[payloadOffset], size - payloadOffset);
+#endif
+
+    buffer->setRange(payloadOffset, size - payloadOffset);
+
+    source->processRTPPacket(buffer);
+
+    return OK;
+}
+
+status_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) {
+    const uint8_t *data = buffer->data();
+    size_t size = buffer->size();
+
+    while (size > 0) {
+        if (size < 8) {
+            // Too short to be a valid RTCP header
+            return -1;
+        }
+
+        if ((data[0] >> 6) != 2) {
+            // Unsupported version.
+            return -1;
+        }
+
+        if (data[0] & 0x20) {
+            // Padding present.
+
+            size_t paddingLength = data[size - 1];
+
+            if (paddingLength + 12 > size) {
+                // If we removed this much padding we'd end up with something
+                // that's too short to be a valid RTP header.
+                return -1;
+            }
+
+            size -= paddingLength;
+        }
+
+        size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
+
+        if (size < headerLength) {
+            // Only received a partial packet?
+            return -1;
+        }
+
+        switch (data[1]) {
+            case 200:
+            {
+                parseSR(s, data, headerLength);
+                break;
+            }
+
+            default:
+            {
+#if VERBOSE
+                printf("Unknown RTCP packet type %d of size %ld\n",
+                       data[1], headerLength);
+
+                hexdump(data, headerLength);
+#endif
+                break;
+            }
+        }
+
+        data += headerLength;
+        size -= headerLength;
+    }
+
+    return OK;
+}
+
+status_t ARTPConnection::parseSR(
+        StreamInfo *s, const uint8_t *data, size_t size) {
+    size_t RC = data[0] & 0x1f;
+
+    if (size < (7 + RC * 6) * 4) {
+        // Packet too short for the minimal SR header.
+        return -1;
+    }
+
+    uint32_t id = u32at(&data[4]);
+    uint64_t ntpTime = u64at(&data[8]);
+    uint32_t rtpTime = u32at(&data[16]);
+
+#if VERBOSE
+    printf("SR = {\n"
+           "  SSRC:      0x%08x\n"
+           "  NTP-time:  0x%016llx\n"
+           "  RTP-time:  0x%08x\n"
+           "}\n",
+           id, ntpTime, rtpTime);
+#endif
+
+    sp<ARTPSource> source;
+    ssize_t index = mSources.indexOfKey(id);
+    if (index < 0) {
+        index = mSources.size();
+
+        source = new ARTPSource(
+                id, s->mSessionDesc, s->mIndex, s->mNotifyMsg);
+
+        mSources.add(id, source);
+    } else {
+        source = mSources.valueAt(index);
+    }
+
+    source->timeUpdate(rtpTime, ntpTime);
+
+    return 0;
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
new file mode 100644
index 0000000..c77e3a4
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 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 A_RTP_CONNECTION_H_
+
+#define A_RTP_CONNECTION_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+#include <utils/List.h>
+
+namespace android {
+
+struct ABuffer;
+struct ARTPSource;
+struct ASessionDescription;
+
+struct ARTPConnection : public AHandler {
+    ARTPConnection();
+
+    void addStream(
+            int rtpSocket, int rtcpSocket,
+            const sp<ASessionDescription> &sessionDesc, size_t index,
+            const sp<AMessage> &notify);
+
+    void removeStream(int rtpSocket, int rtcpSocket);
+
+    // Creates a pair of UDP datagram sockets bound to adjacent ports
+    // (the rtpSocket is bound to an even port, the rtcpSocket to the
+    // next higher port).
+    static void MakePortPair(
+            int *rtpSocket, int *rtcpSocket, unsigned *rtpPort);
+
+protected:
+    virtual ~ARTPConnection();
+    virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+    enum {
+        kWhatAddStream,
+        kWhatRemoveStream,
+        kWhatPollStreams,
+    };
+
+    static const int64_t kSelectTimeoutUs;
+
+    struct StreamInfo;
+    List<StreamInfo> mStreams;
+
+    KeyedVector<uint32_t, sp<ARTPSource> > mSources;
+
+    bool mPollEventPending;
+
+    void onAddStream(const sp<AMessage> &msg);
+    void onRemoveStream(const sp<AMessage> &msg);
+    void onPollStreams();
+
+    status_t receive(StreamInfo *info, bool receiveRTP);
+
+    status_t parseRTP(StreamInfo *info, const sp<ABuffer> &buffer);
+    status_t parseRTCP(StreamInfo *info, const sp<ABuffer> &buffer);
+    status_t parseSR(StreamInfo *info, const uint8_t *data, size_t size);
+
+    void postPollEvent();
+
+    DISALLOW_EVIL_CONSTRUCTORS(ARTPConnection);
+};
+
+}  // namespace android
+
+#endif  // A_RTP_CONNECTION_H_
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
new file mode 100644
index 0000000..f05daa8
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ARTPSource.h"
+
+#include "AAVCAssembler.h"
+#include "AMPEG4AudioAssembler.h"
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#define VERBOSE         0
+
+namespace android {
+
+ARTPSource::ARTPSource(
+        uint32_t id,
+        const sp<ASessionDescription> &sessionDesc, size_t index,
+        const sp<AMessage> &notify)
+    : mID(id),
+      mHighestSeqNumber(0),
+      mNumBuffersReceived(0),
+      mNumTimes(0) {
+    unsigned long PT;
+    AString desc;
+    AString params;
+    sessionDesc->getFormatType(index, &PT, &desc, &params);
+
+    if (!strncmp(desc.c_str(), "H264/", 5)) {
+        mAssembler = new AAVCAssembler(notify);
+    } else if (!strncmp(desc.c_str(), "MP4A-LATM", 9)) {
+        mAssembler = new AMPEG4AudioAssembler(notify);
+    } else {
+        TRESPASS();
+    }
+}
+
+static uint32_t AbsDiff(uint32_t seq1, uint32_t seq2) {
+    return seq1 > seq2 ? seq1 - seq2 : seq2 - seq1;
+}
+
+void ARTPSource::processRTPPacket(const sp<ABuffer> &buffer) {
+    if (queuePacket(buffer) && mNumTimes == 2 && mAssembler != NULL) {
+        mAssembler->onPacketReceived(this);
+    }
+
+    dump();
+}
+
+void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
+#if VERBOSE
+    LOG(VERBOSE) << "timeUpdate";
+#endif
+
+    if (mNumTimes == 2) {
+        mNTPTime[0] = mNTPTime[1];
+        mRTPTime[0] = mRTPTime[1];
+        mNumTimes = 1;
+    }
+    mNTPTime[mNumTimes] = ntpTime;
+    mRTPTime[mNumTimes++] = rtpTime;
+
+    if (mNumTimes == 2) {
+        for (List<sp<ABuffer> >::iterator it = mQueue.begin();
+             it != mQueue.end(); ++it) {
+            sp<AMessage> meta = (*it)->meta();
+
+            uint32_t rtpTime;
+            CHECK(meta->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+            meta->setInt64("ntp-time", RTP2NTP(rtpTime));
+        }
+    }
+}
+
+bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
+    uint32_t seqNum = (uint32_t)buffer->int32Data();
+
+    if (mNumTimes == 2) {
+        sp<AMessage> meta = buffer->meta();
+
+        uint32_t rtpTime;
+        CHECK(meta->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+        meta->setInt64("ntp-time", RTP2NTP(rtpTime));
+    }
+
+    if (mNumBuffersReceived++ == 0) {
+        mHighestSeqNumber = seqNum;
+        mQueue.push_back(buffer);
+        return true;
+    }
+
+    // Only the lower 16-bit of the sequence numbers are transmitted,
+    // derive the high-order bits by choosing the candidate closest
+    // to the highest sequence number (extended to 32 bits) received so far.
+
+    uint32_t seq1 = seqNum | (mHighestSeqNumber & 0xffff0000);
+    uint32_t seq2 = seqNum | ((mHighestSeqNumber & 0xffff0000) + 0x10000);
+    uint32_t seq3 = seqNum | ((mHighestSeqNumber & 0xffff0000) - 0x10000);
+    uint32_t diff1 = AbsDiff(seq1, mHighestSeqNumber);
+    uint32_t diff2 = AbsDiff(seq2, mHighestSeqNumber);
+    uint32_t diff3 = AbsDiff(seq3, mHighestSeqNumber);
+
+    if (diff1 < diff2) {
+        if (diff1 < diff3) {
+            // diff1 < diff2 ^ diff1 < diff3
+            seqNum = seq1;
+        } else {
+            // diff3 <= diff1 < diff2
+            seqNum = seq3;
+        }
+    } else if (diff2 < diff3) {
+        // diff2 <= diff1 ^ diff2 < diff3
+        seqNum = seq2;
+    } else {
+        // diff3 <= diff2 <= diff1
+        seqNum = seq3;
+    }
+
+    if (seqNum > mHighestSeqNumber) {
+        mHighestSeqNumber = seqNum;
+    }
+
+    buffer->setInt32Data(seqNum);
+
+    List<sp<ABuffer> >::iterator it = mQueue.begin();
+    while (it != mQueue.end() && (uint32_t)(*it)->int32Data() < seqNum) {
+        ++it;
+    }
+
+    if (it != mQueue.end() && (uint32_t)(*it)->int32Data() == seqNum) {
+        LOG(WARNING) << "Discarding duplicate buffer";
+        return false;
+    }
+
+    mQueue.insert(it, buffer);
+
+    return true;
+}
+
+void ARTPSource::dump() const {
+    if ((mNumBuffersReceived % 128) != 0) {
+        return;
+    }
+
+#if 0
+    if (mAssembler == NULL) {
+        char tmp[20];
+        sprintf(tmp, "0x%08x", mID);
+
+        int32_t numMissing = 0;
+
+        if (!mQueue.empty()) {
+            List<sp<ABuffer> >::const_iterator it = mQueue.begin();
+            uint32_t expectedSeqNum = (uint32_t)(*it)->int32Data();
+            ++expectedSeqNum;
+            ++it;
+
+            for (; it != mQueue.end(); ++it) {
+                uint32_t seqNum = (uint32_t)(*it)->int32Data();
+                CHECK_GE(seqNum, expectedSeqNum);
+
+                if (seqNum != expectedSeqNum) {
+                    numMissing += seqNum - expectedSeqNum;
+                    expectedSeqNum = seqNum;
+                }
+
+                ++expectedSeqNum;
+            }
+        }
+
+        LOG(VERBOSE) << "[" << tmp << "] Missing " << numMissing
+             << " / " << (mNumBuffersReceived + numMissing) << " packets. ("
+             << (100.0 * numMissing / (mNumBuffersReceived + numMissing))
+             << " %%)";
+    }
+#endif
+
+#if 0
+    AString out;
+    
+    out.append(tmp);
+    out.append(" [");
+
+    List<sp<ABuffer> >::const_iterator it = mQueue.begin();
+    while (it != mQueue.end()) {
+        uint32_t start = (uint32_t)(*it)->int32Data();
+
+        out.append(start);
+
+        ++it;
+        uint32_t expected = start + 1;
+
+        while (it != mQueue.end()) {
+            uint32_t seqNum = (uint32_t)(*it)->int32Data();
+
+            if (seqNum != expected) {
+                if (expected > start + 1) {
+                    out.append("-");
+                    out.append(expected - 1);
+                }
+                out.append(", ");
+                break;
+            }
+
+            ++it;
+            ++expected;
+        }
+
+        if (it == mQueue.end()) {
+            if (expected > start + 1) {
+                out.append("-");
+                out.append(expected - 1);
+            }
+        }
+    }
+
+    out.append("]");
+
+    LOG(VERBOSE) << out;
+#endif
+}
+
+uint64_t ARTPSource::RTP2NTP(uint32_t rtpTime) const {
+    CHECK_EQ(mNumTimes, 2u);
+
+    return mNTPTime[0] + (double)(mNTPTime[1] - mNTPTime[0])
+            * ((double)rtpTime - (double)mRTPTime[0])
+            / (double)(mRTPTime[1] - mRTPTime[0]);
+}
+
+}  // namespace android
+
+
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
new file mode 100644
index 0000000..b93cd56
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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 A_RTP_SOURCE_H_
+
+#define A_RTP_SOURCE_H_
+
+#include <stdint.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+struct ARTPAssembler;
+struct ASessionDescription;
+
+struct ARTPSource : public RefBase {
+    ARTPSource(
+            uint32_t id,
+            const sp<ASessionDescription> &sessionDesc, size_t index,
+            const sp<AMessage> &notify);
+
+    void processRTPPacket(const sp<ABuffer> &buffer);
+    void timeUpdate(uint32_t rtpTime, uint64_t ntpTime);
+
+    List<sp<ABuffer> > *queue() { return &mQueue; }
+
+private:
+    uint32_t mID;
+    uint32_t mHighestSeqNumber;
+    int32_t mNumBuffersReceived;
+
+    List<sp<ABuffer> > mQueue;
+    sp<ARTPAssembler> mAssembler;
+
+    size_t mNumTimes;
+    uint64_t mNTPTime[2];
+    uint32_t mRTPTime[2];
+
+    uint64_t RTP2NTP(uint32_t rtpTime) const;
+
+    bool queuePacket(const sp<ABuffer> &buffer);
+    void dump() const;
+
+    DISALLOW_EVIL_CONSTRUCTORS(ARTPSource);
+};
+
+}  // namespace android
+
+#endif  // A_RTP_SOURCE_H_
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
new file mode 100644
index 0000000..e9162c0
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ARTSPConnection.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+namespace android {
+
+// static
+const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
+
+ARTSPConnection::ARTSPConnection()
+    : mState(DISCONNECTED),
+      mSocket(-1),
+      mConnectionID(0),
+      mNextCSeq(0),
+      mReceiveResponseEventPending(false) {
+}
+
+ARTSPConnection::~ARTSPConnection() {
+    if (mSocket >= 0) {
+        LOG(ERROR) << "Connection is still open, closing the socket.";
+        close(mSocket);
+        mSocket = -1;
+    }
+}
+
+void ARTSPConnection::connect(const char *url, const sp<AMessage> &reply) {
+    sp<AMessage> msg = new AMessage(kWhatConnect, id());
+    msg->setString("url", url);
+    msg->setMessage("reply", reply);
+    msg->post();
+}
+
+void ARTSPConnection::disconnect(const sp<AMessage> &reply) {
+    sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
+    msg->setMessage("reply", reply);
+    msg->post();
+}
+
+void ARTSPConnection::sendRequest(
+        const char *request, const sp<AMessage> &reply) {
+    sp<AMessage> msg = new AMessage(kWhatSendRequest, id());
+    msg->setString("request", request);
+    msg->setMessage("reply", reply);
+    msg->post();
+}
+
+void ARTSPConnection::onMessageReceived(const sp<AMessage> &msg) {
+    switch (msg->what()) {
+        case kWhatConnect:
+            onConnect(msg);
+            break;
+
+        case kWhatDisconnect:
+            onDisconnect(msg);
+            break;
+
+        case kWhatCompleteConnection:
+            onCompleteConnection(msg);
+            break;
+
+        case kWhatSendRequest:
+            onSendRequest(msg);
+            break;
+
+        case kWhatReceiveResponse:
+            onReceiveResponse();
+            break;
+
+        default:
+            TRESPASS();
+            break;
+    }
+}
+
+// static
+bool ARTSPConnection::ParseURL(
+        const char *url, AString *host, unsigned *port, AString *path) {
+    host->clear();
+    *port = 0;
+    path->clear();
+
+    if (strncasecmp("rtsp://", url, 7)) {
+        return false;
+    }
+
+    const char *slashPos = strchr(&url[7], '/');
+
+    if (slashPos == NULL) {
+        host->setTo(&url[7]);
+        path->setTo("/");
+    } else {
+        host->setTo(&url[7], slashPos - &url[7]);
+        path->setTo(slashPos);
+    }
+
+    char *colonPos = strchr(host->c_str(), ':');
+
+    if (colonPos != NULL) {
+        unsigned long x;
+        if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
+            return false;
+        }
+
+        *port = x;
+
+        size_t colonOffset = colonPos - host->c_str();
+        size_t trailing = host->size() - colonOffset;
+        host->erase(colonOffset, trailing);
+    } else {
+        *port = 554;
+    }
+
+    return true;
+}
+
+void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
+    ++mConnectionID;
+
+    if (mState != DISCONNECTED) {
+        close(mSocket);
+        mSocket = -1;
+
+        flushPendingRequests();
+    }
+
+    mState = CONNECTING;
+
+    mSocket = socket(AF_INET, SOCK_STREAM, 0);
+
+    // Make socket non-blocking.
+    int flags = fcntl(mSocket, F_GETFL, 0);
+    CHECK_NE(flags, -1);
+    CHECK_NE(fcntl(mSocket, F_SETFL, flags | O_NONBLOCK), -1);
+
+    AString url;
+    CHECK(msg->findString("url", &url));
+
+    AString host, path;
+    unsigned port;
+    CHECK(ParseURL(url.c_str(), &host, &port, &path));
+
+    struct hostent *ent = gethostbyname(host.c_str());
+    CHECK(ent != NULL);
+
+    struct sockaddr_in remote;
+    memset(remote.sin_zero, 0, sizeof(remote.sin_zero));
+    remote.sin_family = AF_INET;
+    remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
+    remote.sin_port = htons(port);
+
+    int err = ::connect(
+            mSocket, (const struct sockaddr *)&remote, sizeof(remote));
+
+    sp<AMessage> reply;
+    CHECK(msg->findMessage("reply", &reply));
+
+    reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr));
+
+    if (err < 0) {
+        if (errno == EINPROGRESS) {
+            sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id());
+            msg->setMessage("reply", reply);
+            msg->setInt32("connection-id", mConnectionID);
+            msg->post();
+            return;
+        }
+
+        reply->setInt32("result", -errno);
+        mState = DISCONNECTED;
+
+        close(mSocket);
+        mSocket = -1;
+    } else {
+        reply->setInt32("result", OK);
+        mState = CONNECTED;
+        mNextCSeq = 1;
+
+        postReceiveReponseEvent();
+    }
+
+    reply->post();
+}
+
+void ARTSPConnection::onDisconnect(const sp<AMessage> &msg) {
+    if (mState == CONNECTED || mState == CONNECTING) {
+        close(mSocket);
+        mSocket = -1;
+
+        flushPendingRequests();
+    } 
+
+    sp<AMessage> reply;
+    CHECK(msg->findMessage("reply", &reply));
+
+    reply->setInt32("result", OK);
+    mState = DISCONNECTED;
+
+    reply->post();
+}
+
+void ARTSPConnection::onCompleteConnection(const sp<AMessage> &msg) {
+    sp<AMessage> reply;
+    CHECK(msg->findMessage("reply", &reply));
+
+    int32_t connectionID;
+    CHECK(msg->findInt32("connection-id", &connectionID));
+
+    if ((connectionID != mConnectionID) || mState != CONNECTING) {
+        // While we were attempting to connect, the attempt was
+        // cancelled.
+        reply->setInt32("result", -ECONNABORTED);
+        reply->post();
+        return;
+    }
+
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = kSelectTimeoutUs;
+
+    fd_set ws;
+    FD_ZERO(&ws);
+    FD_SET(mSocket, &ws);
+
+    int res = select(mSocket + 1, NULL, &ws, NULL, &tv);
+    CHECK_GE(res, 0);
+
+    if (res == 0) {
+        // Timed out. Not yet connected.
+
+        msg->post();
+        return;
+    }
+
+    int err;
+    socklen_t optionLen = sizeof(err);
+    CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
+    CHECK_EQ(optionLen, (socklen_t)sizeof(err));
+
+    if (err != 0) {
+        LOG(ERROR) << "err = " << err << " (" << strerror(err) << ")";
+
+        reply->setInt32("result", -err);
+
+        mState = DISCONNECTED;
+        close(mSocket);
+        mSocket = -1;
+    } else {
+        reply->setInt32("result", OK);
+        mState = CONNECTED;
+        mNextCSeq = 1;
+
+        postReceiveReponseEvent();
+    }
+
+    reply->post();
+}
+
+void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
+    sp<AMessage> reply;
+    CHECK(msg->findMessage("reply", &reply));
+
+    if (mState != CONNECTED) {
+        reply->setInt32("result", -ENOTCONN);
+        reply->post();
+        return;
+    }
+
+    AString request;
+    CHECK(msg->findString("request", &request));
+
+    // Find the boundary between headers and the body.
+    ssize_t i = request.find("\r\n\r\n");
+    CHECK_GE(i, 0);
+
+    int32_t cseq = mNextCSeq++;
+
+    AString cseqHeader = "CSeq: ";
+    cseqHeader.append(cseq);
+    cseqHeader.append("\r\n");
+
+    request.insert(cseqHeader, i + 2);
+
+    LOG(VERBOSE) << request;
+
+    size_t numBytesSent = 0;
+    while (numBytesSent < request.size()) {
+        ssize_t n =
+            send(mSocket, request.c_str() + numBytesSent,
+                 request.size() - numBytesSent, 0);
+
+        if (n == 0) {
+            // Server closed the connection.
+            TRESPASS();
+        } else if (n < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+
+            TRESPASS();
+        }
+
+        numBytesSent += (size_t)n;
+    }
+
+    mPendingRequests.add(cseq, reply);
+}
+
+void ARTSPConnection::onReceiveResponse() {
+    mReceiveResponseEventPending = false;
+
+    if (mState != CONNECTED) {
+        return;
+    }
+
+    struct timeval tv;
+    tv.tv_sec = 0;
+    tv.tv_usec = kSelectTimeoutUs;
+
+    fd_set rs;
+    FD_ZERO(&rs);
+    FD_SET(mSocket, &rs);
+
+    int res = select(mSocket + 1, &rs, NULL, NULL, &tv);
+    CHECK_GE(res, 0);
+
+    if (res == 1) {
+        if (!receiveRTSPReponse()) {
+            // Something horrible, irreparable has happened.
+            flushPendingRequests();
+            return;
+        }
+    }
+
+    postReceiveReponseEvent();
+}
+
+void ARTSPConnection::flushPendingRequests() {
+    for (size_t i = 0; i < mPendingRequests.size(); ++i) {
+        sp<AMessage> reply = mPendingRequests.valueAt(i);
+
+        reply->setInt32("result", -ECONNABORTED);
+        reply->post();
+    }
+
+    mPendingRequests.clear();
+}
+
+void ARTSPConnection::postReceiveReponseEvent() {
+    if (mReceiveResponseEventPending) {
+        return;
+    }
+
+    sp<AMessage> msg = new AMessage(kWhatReceiveResponse, id());
+    msg->post();
+
+    mReceiveResponseEventPending = true;
+}
+
+bool ARTSPConnection::receiveLine(AString *line) {
+    line->clear();
+
+    bool sawCR = false;
+    for (;;) {
+        char c;
+        ssize_t n = recv(mSocket, &c, 1, 0);
+        if (n == 0) {
+            // Server closed the connection.
+            return false;
+        } else if (n < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+
+            TRESPASS();
+        }
+
+        if (sawCR && c == '\n') {
+            line->erase(line->size() - 1, 1);
+            return true;
+        }
+
+        line->append(&c, 1);
+
+        sawCR = (c == '\r');
+    }
+}
+
+bool ARTSPConnection::receiveRTSPReponse() {
+    sp<ARTSPResponse> response = new ARTSPResponse;
+
+    if (!receiveLine(&response->mStatusLine)) {
+        return false;
+    }
+
+    LOG(INFO) << "status: " << response->mStatusLine;
+
+    ssize_t space1 = response->mStatusLine.find(" ");
+    if (space1 < 0) {
+        return false;
+    }
+    ssize_t space2 = response->mStatusLine.find(" ", space1 + 1);
+    if (space2 < 0) {
+        return false;
+    }
+
+    AString statusCodeStr(
+            response->mStatusLine, space1 + 1, space2 - space1 - 1);
+
+    if (!ParseSingleUnsignedLong(
+                statusCodeStr.c_str(), &response->mStatusCode)
+            || response->mStatusCode < 100 || response->mStatusCode > 999) {
+        return false;
+    }
+
+    AString line;
+    for (;;) {
+        if (!receiveLine(&line)) {
+            break;
+        }
+
+        if (line.empty()) {
+            break;
+        }
+
+        LOG(VERBOSE) << "line: " << line;
+
+        ssize_t colonPos = line.find(":");
+        if (colonPos < 0) {
+            // Malformed header line.
+            return false;
+        }
+
+        AString key(line, 0, colonPos);
+        key.trim();
+        key.tolower();
+
+        line.erase(0, colonPos + 1);
+        line.trim();
+
+        response->mHeaders.add(key, line);
+    }
+
+    unsigned long contentLength = 0;
+
+    ssize_t i = response->mHeaders.indexOfKey("content-length");
+
+    if (i >= 0) {
+        AString value = response->mHeaders.valueAt(i);
+        if (!ParseSingleUnsignedLong(value.c_str(), &contentLength)) {
+            return false;
+        }
+    }
+
+    if (contentLength > 0) {
+        response->mContent = new ABuffer(contentLength);
+
+        size_t numBytesRead = 0;
+        while (numBytesRead < contentLength) {
+            ssize_t n = recv(
+                    mSocket, response->mContent->data() + numBytesRead,
+                    contentLength - numBytesRead, 0);
+
+            if (n == 0) {
+                // Server closed the connection.
+                TRESPASS();
+            } else if (n < 0) {
+                if (errno == EINTR) {
+                    continue;
+                }
+
+                TRESPASS();
+            }
+
+            numBytesRead += (size_t)n;
+        }
+    }
+
+    return notifyResponseListener(response);
+}
+
+// static
+bool ARTSPConnection::ParseSingleUnsignedLong(
+        const char *from, unsigned long *x) {
+    char *end;
+    *x = strtoul(from, &end, 10);
+
+    if (end == from || *end != '\0') {
+        return false;
+    }
+
+    return true;
+}
+
+bool ARTSPConnection::notifyResponseListener(
+        const sp<ARTSPResponse> &response) {
+    ssize_t i = response->mHeaders.indexOfKey("cseq");
+
+    if (i < 0) {
+        return true;
+    }
+
+    AString value = response->mHeaders.valueAt(i);
+
+    unsigned long cseq;
+    if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
+        return false;
+    }
+
+    i = mPendingRequests.indexOfKey(cseq);
+
+    if (i < 0) {
+        // Unsolicited response?
+        TRESPASS();
+    }
+
+    sp<AMessage> reply = mPendingRequests.valueAt(i);
+    mPendingRequests.removeItemsAt(i);
+
+    reply->setInt32("result", OK);
+    reply->setObject("response", response);
+    reply->post();
+
+    return true;
+}
+
+}  // namespace android
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
new file mode 100644
index 0000000..3577a2f
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 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 A_RTSP_CONNECTION_H_
+
+#define A_RTSP_CONNECTION_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+struct ABuffer;
+
+struct ARTSPResponse : public RefBase {
+    unsigned long mStatusCode;
+    AString mStatusLine;
+    KeyedVector<AString,AString> mHeaders;
+    sp<ABuffer> mContent;
+};
+
+struct ARTSPConnection : public AHandler {
+    ARTSPConnection();
+
+    void connect(const char *url, const sp<AMessage> &reply);
+    void disconnect(const sp<AMessage> &reply);
+
+    void sendRequest(const char *request, const sp<AMessage> &reply);
+
+protected:
+    virtual ~ARTSPConnection();
+    virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+    enum State {
+        DISCONNECTED,
+        CONNECTING,
+        CONNECTED,
+    };
+
+    enum {
+        kWhatConnect            = 'conn',
+        kWhatDisconnect         = 'disc',
+        kWhatCompleteConnection = 'comc',
+        kWhatSendRequest        = 'sreq',
+        kWhatReceiveResponse    = 'rres',
+    };
+
+    static const int64_t kSelectTimeoutUs;
+
+    State mState;
+    int mSocket;
+    int32_t mConnectionID;
+    int32_t mNextCSeq;
+    bool mReceiveResponseEventPending;
+
+    KeyedVector<int32_t, sp<AMessage> > mPendingRequests;
+
+    void onConnect(const sp<AMessage> &msg);
+    void onDisconnect(const sp<AMessage> &msg);
+    void onCompleteConnection(const sp<AMessage> &msg);
+    void onSendRequest(const sp<AMessage> &msg);
+    void onReceiveResponse();
+
+    void flushPendingRequests();
+    void postReceiveReponseEvent();
+
+    // Return false iff something went unrecoverably wrong.
+    bool receiveRTSPReponse();
+    bool receiveLine(AString *line);
+    bool notifyResponseListener(const sp<ARTSPResponse> &response);
+
+    static bool ParseURL(
+            const char *url, AString *host, unsigned *port, AString *path);
+
+    static bool ParseSingleUnsignedLong(
+            const char *from, unsigned long *x);
+
+    DISALLOW_EVIL_CONSTRUCTORS(ARTSPConnection);
+};
+
+}  // namespace android
+
+#endif  // A_RTSP_CONNECTION_H_
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
new file mode 100644
index 0000000..195323e
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ARTSPController.h"
+
+#include "MyHandler.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+ARTSPController::ARTSPController(const sp<ALooper> &looper)
+    : mLooper(looper) {
+}
+
+ARTSPController::~ARTSPController() {
+}
+
+status_t ARTSPController::connect(const char *url) {
+    if (mHandler != NULL) {
+        return ERROR_ALREADY_CONNECTED;
+    }
+
+    mHandler = new MyHandler(url, mLooper);
+    mHandler->connect();
+
+    sleep(10);
+
+    return OK;
+}
+
+void ARTSPController::disconnect() {
+    if (mHandler == NULL) {
+        return;
+    }
+
+    mHandler->disconnect();
+    mHandler.clear();
+}
+
+size_t ARTSPController::countTracks() {
+    if (mHandler == NULL) {
+        return 0;
+    }
+
+    return mHandler->countTracks();
+}
+
+sp<MediaSource> ARTSPController::getTrack(size_t index) {
+    CHECK(mHandler != NULL);
+
+    return mHandler->getPacketSource(index);
+}
+
+sp<MetaData> ARTSPController::getTrackMetaData(
+        size_t index, uint32_t flags) {
+    CHECK(mHandler != NULL);
+
+    return mHandler->getPacketSource(index)->getFormat();
+}
+
+}  // namespace android
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
new file mode 100644
index 0000000..ca4c55e
--- /dev/null
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <stdlib.h>
+
+namespace android {
+
+ASessionDescription::ASessionDescription()
+    : mIsValid(false) {
+}
+
+ASessionDescription::~ASessionDescription() {
+}
+
+bool ASessionDescription::setTo(const void *data, size_t size) {
+    mIsValid = parse(data, size);
+
+    if (!mIsValid) {
+        mTracks.clear();
+        mFormats.clear();
+    }
+
+    return mIsValid;
+}
+
+bool ASessionDescription::parse(const void *data, size_t size) {
+    mTracks.clear();
+    mFormats.clear();
+
+    mTracks.push(Attribs());
+    mFormats.push(AString("[root]"));
+
+    AString desc((const char *)data, size);
+    LOG(VERBOSE) << desc;
+
+    size_t i = 0;
+    for (;;) {
+        ssize_t eolPos = desc.find("\r\n", i);
+        if (eolPos < 0) {
+            break;
+        }
+
+        AString line(desc, i, eolPos - i);
+
+        if (line.size() < 2 || line.c_str()[1] != '=') {
+            return false;
+        }
+
+        switch (line.c_str()[0]) {
+            case 'v':
+            {
+                if (strcmp(line.c_str(), "v=0")) {
+                    return false;
+                }
+                break;
+            }
+
+            case 'a':
+            case 'b':
+            {
+                AString key, value;
+
+                ssize_t colonPos = line.find(":", 2);
+                if (colonPos < 0) {
+                    key = line;
+                } else {
+                    key.setTo(line, 0, colonPos);
+
+                    if (key == "a=fmtp" || key == "a=rtpmap"
+                            || key == "a=framesize") {
+                        ssize_t spacePos = line.find(" ", colonPos + 1);
+                        if (spacePos < 0) {
+                            return false;
+                        }
+
+                        key.setTo(line, 0, spacePos);
+
+                        colonPos = spacePos;
+                    }
+
+                    value.setTo(line, colonPos + 1, line.size() - colonPos - 1);
+                }
+
+                key.trim();
+                value.trim();
+
+                LOG(VERBOSE) << "adding '" << key << "' => '" << value << "'";
+
+                mTracks.editItemAt(mTracks.size() - 1).add(key, value);
+                break;
+            }
+
+            case 'm':
+            {
+                LOG(VERBOSE) << "new section '" << AString(line, 2, line.size() - 2) << "'";
+
+                mTracks.push(Attribs());
+                mFormats.push(AString(line, 2, line.size() - 2));
+                break;
+            }
+        }
+
+        i = eolPos + 2;
+    }
+
+    return true;
+}
+
+bool ASessionDescription::isValid() const {
+    return mIsValid;
+}
+
+size_t ASessionDescription::countTracks() const {
+    return mTracks.size();
+}
+
+void ASessionDescription::getFormat(size_t index, AString *value) const {
+    CHECK_GE(index, 0u);
+    CHECK_LT(index, mTracks.size());
+
+    *value = mFormats.itemAt(index);
+}
+
+bool ASessionDescription::findAttribute(
+        size_t index, const char *key, AString *value) const {
+    CHECK_GE(index, 0u);
+    CHECK_LT(index, mTracks.size());
+
+    value->clear();
+
+    const Attribs &track = mTracks.itemAt(index);
+    ssize_t i = track.indexOfKey(AString(key));
+
+    if (i < 0) {
+        return false;
+    }
+
+    *value = track.valueAt(i);
+
+    return true;
+}
+
+void ASessionDescription::getFormatType(
+        size_t index, unsigned long *PT,
+        AString *desc, AString *params) const {
+    AString format;
+    getFormat(index, &format);
+
+    char *lastSpacePos = strrchr(format.c_str(), ' ');
+    CHECK(lastSpacePos != NULL);
+
+    char *end;
+    unsigned long x = strtoul(lastSpacePos + 1, &end, 10);
+    CHECK_GT(end, lastSpacePos + 1);
+    CHECK_EQ(*end, '\0');
+
+    *PT = x;
+
+    char key[20];
+    sprintf(key, "a=rtpmap:%lu", x);
+
+    CHECK(findAttribute(index, key, desc));
+
+    sprintf(key, "a=fmtp:%lu", x);
+    if (!findAttribute(index, key, params)) {
+        params->clear();
+    }
+}
+
+void ASessionDescription::getDimensions(
+        size_t index, unsigned long PT,
+        int32_t *width, int32_t *height) const {
+    char key[20];
+    sprintf(key, "a=framesize:%lu", PT);
+    AString value;
+    CHECK(findAttribute(index, key, &value));
+
+    const char *s = value.c_str();
+    char *end;
+    *width = strtoul(s, &end, 10);
+    CHECK_GT(end, s);
+    CHECK_EQ(*end, '-');
+
+    s = end + 1;
+    *height = strtoul(s, &end, 10);
+    CHECK_GT(end, s);
+    CHECK_EQ(*end, '\0');
+}
+
+bool ASessionDescription::getDurationUs(int64_t *durationUs) const {
+    *durationUs = 0;
+
+    CHECK(mIsValid);
+
+    AString value;
+    if (!findAttribute(0, "a=range", &value)) {
+        return false;
+    }
+
+    if (value == "npt=now-") {
+        return false;
+    }
+
+    if (strncmp(value.c_str(), "npt=", 4)) {
+        return false;
+    }
+
+    const char *s = value.c_str() + 4;
+    char *end;
+    double from = strtod(s, &end);
+    CHECK_GT(end, s);
+    CHECK_EQ(*end, '-');
+
+    s = end + 1;
+    double to = strtod(s, &end);
+    CHECK_GT(end, s);
+    CHECK_EQ(*end, '\0');
+
+    CHECK_GE(to, from);
+
+    *durationUs = (int64_t)((to - from) * 1E6);
+
+    return true;
+}
+
+// static
+void ASessionDescription::ParseFormatDesc(
+        const char *desc, int32_t *timescale, int32_t *numChannels) {
+    const char *slash1 = strchr(desc, '/');
+    CHECK(slash1 != NULL);
+
+    const char *s = slash1 + 1;
+    char *end;
+    unsigned long x = strtoul(s, &end, 10);
+    CHECK_GT(end, s);
+    CHECK(*end == '\0' || *end == '/');
+
+    *timescale = x;
+    *numChannels = 1;
+
+    if (*end == '/') {
+        s = end + 1;
+        unsigned long x = strtoul(s, &end, 10);
+        CHECK_GT(end, s);
+        CHECK_EQ(*end, '\0');
+
+        *numChannels = x;
+    }
+}
+
+}  // namespace android
+
diff --git a/media/libstagefright/rtsp/ASessionDescription.h b/media/libstagefright/rtsp/ASessionDescription.h
new file mode 100644
index 0000000..b26980f
--- /dev/null
+++ b/media/libstagefright/rtsp/ASessionDescription.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 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 A_SESSION_DESCRIPTION_H_
+
+#define A_SESSION_DESCRIPTION_H_
+
+#include <sys/types.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AString;
+
+struct ASessionDescription : public RefBase {
+    ASessionDescription();
+
+    bool setTo(const void *data, size_t size);
+    bool isValid() const;
+
+    // Actually, 1 + number of tracks, as index 0 is reserved for the
+    // session description root-level attributes.
+    size_t countTracks() const;
+    void getFormat(size_t index, AString *value) const;
+
+    void getFormatType(
+            size_t index, unsigned long *PT,
+            AString *desc, AString *params) const;
+
+    void getDimensions(
+            size_t index, unsigned long PT,
+            int32_t *width, int32_t *height) const;
+
+    bool getDurationUs(int64_t *durationUs) const;
+
+    static void ParseFormatDesc(
+            const char *desc, int32_t *timescale, int32_t *numChannels);
+
+    bool findAttribute(size_t index, const char *key, AString *value) const;
+
+protected:
+    virtual ~ASessionDescription();
+
+private:
+    typedef KeyedVector<AString,AString> Attribs;
+
+    bool mIsValid;
+    Vector<Attribs> mTracks;
+    Vector<AString> mFormats;
+
+    bool parse(const void *data, size_t size);
+
+    DISALLOW_EVIL_CONSTRUCTORS(ASessionDescription);
+};
+
+}  // namespace android
+
+#endif  // A_SESSION_DESCRIPTION_H_
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
new file mode 100644
index 0000000..4608fa0
--- /dev/null
+++ b/media/libstagefright/rtsp/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=       \
+        ARTSPController.cpp         \
+        AAVCAssembler.cpp           \
+        AMPEG4AudioAssembler.cpp    \
+        APacketSource.cpp           \
+        ARTPAssembler.cpp           \
+        ARTPConnection.cpp          \
+        ARTPSource.cpp              \
+        ARTSPConnection.cpp         \
+        ASessionDescription.cpp     \
+
+LOCAL_C_INCLUDES:= \
+	$(JNI_H_INCLUDE) \
+	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+        $(TOP)/frameworks/base/media/libstagefright/include \
+
+LOCAL_MODULE:= libstagefright_rtsp
+
+ifeq ($(TARGET_ARCH),arm)
+    LOCAL_CFLAGS += -Wno-psabi
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
new file mode 100644
index 0000000..044393f
--- /dev/null
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2010 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 MY_HANDLER_H_
+
+#define MY_HANDLER_H_
+
+#include "APacketSource.h"
+#include "ARTPConnection.h"
+#include "ARTSPConnection.h"
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+struct MyHandler : public AHandler {
+    MyHandler(const char *url, const sp<ALooper> &looper)
+        : mLooper(looper),
+          mNetLooper(new ALooper),
+          mConn(new ARTSPConnection),
+          mRTPConn(new ARTPConnection),
+          mSessionURL(url),
+          mSetupTracksSuccessful(false),
+          mFirstAccessUnit(true),
+          mFirstAccessUnitNTP(-1) {
+
+        mNetLooper->start(false /* runOnCallingThread */,
+                          false /* canCallJava */,
+                          PRIORITY_HIGHEST);
+    }
+
+    void connect() {
+        mLooper->registerHandler(this);
+        mLooper->registerHandler(mConn);
+        (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn);
+        sp<AMessage> reply = new AMessage('conn', id());
+
+        mConn->connect(mSessionURL.c_str(), reply);
+    }
+
+    void disconnect() {
+        sp<AMessage> reply = new AMessage('disc', id());
+        mConn->disconnect(reply);
+    }
+
+    virtual void onMessageReceived(const sp<AMessage> &msg) {
+        switch (msg->what()) {
+            case 'conn':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "connection request completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                if (result == OK) {
+                    AString request;
+                    request = "DESCRIBE ";
+                    request.append(mSessionURL);
+                    request.append(" RTSP/1.0\r\n");
+                    request.append("Accept: application/sdp\r\n");
+                    request.append("\r\n");
+
+                    sp<AMessage> reply = new AMessage('desc', id());
+                    mConn->sendRequest(request.c_str(), reply);
+                }
+                break;
+            }
+
+            case 'disc':
+            {
+                LOG(INFO) << "disconnect completed";
+
+                (new AMessage('quit', id()))->post();
+                break;
+            }
+
+            case 'desc':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "DESCRIBE completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                if (result == OK) {
+                    sp<RefBase> obj;
+                    CHECK(msg->findObject("response", &obj));
+                    sp<ARTSPResponse> response =
+                        static_cast<ARTSPResponse *>(obj.get());
+
+                    if (response->mStatusCode == 302) {
+                        ssize_t i = response->mHeaders.indexOfKey("location");
+                        CHECK_GE(i, 0);
+
+                        mSessionURL = response->mHeaders.valueAt(i);
+
+                        AString request;
+                        request = "DESCRIBE ";
+                        request.append(mSessionURL);
+                        request.append(" RTSP/1.0\r\n");
+                        request.append("Accept: application/sdp\r\n");
+                        request.append("\r\n");
+
+                        sp<AMessage> reply = new AMessage('desc', id());
+                        mConn->sendRequest(request.c_str(), reply);
+                        break;
+                    }
+
+                    CHECK_EQ(response->mStatusCode, 200u);
+
+                    mSessionDesc = new ASessionDescription;
+
+                    mSessionDesc->setTo(
+                            response->mContent->data(),
+                            response->mContent->size());
+
+                    CHECK(mSessionDesc->isValid());
+
+                    ssize_t i = response->mHeaders.indexOfKey("content-base");
+                    if (i >= 0) {
+                        mBaseURL = response->mHeaders.valueAt(i);
+                    } else {
+                        i = response->mHeaders.indexOfKey("content-location");
+                        if (i >= 0) {
+                            mBaseURL = response->mHeaders.valueAt(i);
+                        } else {
+                            mBaseURL = mSessionURL;
+                        }
+                    }
+
+                    CHECK_GT(mSessionDesc->countTracks(), 1u);
+                    setupTrack(1);
+                } else {
+                    sp<AMessage> reply = new AMessage('disc', id());
+                    mConn->disconnect(reply);
+                }
+                break;
+            }
+
+            case 'setu':
+            {
+                size_t index;
+                CHECK(msg->findSize("index", &index));
+
+                size_t trackIndex;
+                CHECK(msg->findSize("track-index", &trackIndex));
+
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "SETUP(" << index << ") completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                TrackInfo *track = &mTracks.editItemAt(trackIndex);
+
+                if (result == OK) {
+                    sp<RefBase> obj;
+                    CHECK(msg->findObject("response", &obj));
+                    sp<ARTSPResponse> response =
+                        static_cast<ARTSPResponse *>(obj.get());
+
+                    CHECK_EQ(response->mStatusCode, 200u);
+
+                    ssize_t i = response->mHeaders.indexOfKey("session");
+                    CHECK_GE(i, 0);
+
+                    if (index == 1) {
+                        mSessionID = response->mHeaders.valueAt(i);
+                        i = mSessionID.find(";");
+                        if (i >= 0) {
+                            // Remove options, i.e. ";timeout=90"
+                            mSessionID.erase(i, mSessionID.size() - i);
+                        }
+                    }
+
+                    sp<AMessage> notify = new AMessage('accu', id());
+                    notify->setSize("track-index", trackIndex);
+
+                    mRTPConn->addStream(
+                            track->mRTPSocket, track->mRTCPSocket,
+                            mSessionDesc, index,
+                            notify);
+
+                    track->mPacketSource =
+                        new APacketSource(mSessionDesc, index);
+
+                    mSetupTracksSuccessful = true;
+
+                    ++index;
+                    if (index < mSessionDesc->countTracks()) {
+                        setupTrack(index);
+                        break;
+                    }
+                } else {
+                    close(track->mRTPSocket);
+                    close(track->mRTCPSocket);
+
+                    mTracks.removeItemsAt(mTracks.size() - 1);
+                }
+
+                if (mSetupTracksSuccessful) {
+                    AString request = "PLAY ";
+                    request.append(mSessionURL);
+                    request.append(" RTSP/1.0\r\n");
+
+                    request.append("Session: ");
+                    request.append(mSessionID);
+                    request.append("\r\n");
+
+                    request.append("\r\n");
+
+                    sp<AMessage> reply = new AMessage('play', id());
+                    mConn->sendRequest(request.c_str(), reply);
+                } else {
+                    sp<AMessage> reply = new AMessage('disc', id());
+                    mConn->disconnect(reply);
+                }
+                break;
+            }
+
+            case 'play':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "PLAY completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                if (result == OK) {
+                    sp<RefBase> obj;
+                    CHECK(msg->findObject("response", &obj));
+                    sp<ARTSPResponse> response =
+                        static_cast<ARTSPResponse *>(obj.get());
+
+                    CHECK_EQ(response->mStatusCode, 200u);
+
+                    sp<AMessage> msg = new AMessage('abor', id());
+                    msg->post(60000000ll);
+                } else {
+                    sp<AMessage> reply = new AMessage('disc', id());
+                    mConn->disconnect(reply);
+                }
+
+                break;
+            }
+
+            case 'abor':
+            {
+                for (size_t i = 0; i < mTracks.size(); ++i) {
+                    mTracks.editItemAt(i).mPacketSource->signalEOS(
+                            ERROR_END_OF_STREAM);
+                }
+
+                sp<AMessage> reply = new AMessage('tear', id());
+
+                AString request;
+                request = "TEARDOWN ";
+
+                // XXX should use aggregate url from SDP here...
+                request.append(mSessionURL);
+                request.append(" RTSP/1.0\r\n");
+
+                request.append("Session: ");
+                request.append(mSessionID);
+                request.append("\r\n");
+
+                request.append("\r\n");
+
+                mConn->sendRequest(request.c_str(), reply);
+                break;
+            }
+
+            case 'tear':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "TEARDOWN completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                sp<AMessage> reply = new AMessage('disc', id());
+                mConn->disconnect(reply);
+                break;
+            }
+
+            case 'quit':
+            {
+                break;
+            }
+
+            case 'accu':
+            {
+                size_t trackIndex;
+                CHECK(msg->findSize("track-index", &trackIndex));
+
+                sp<RefBase> obj;
+                CHECK(msg->findObject("access-unit", &obj));
+
+                sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get());
+
+                uint64_t ntpTime;
+                CHECK(accessUnit->meta()->findInt64(
+                            "ntp-time", (int64_t *)&ntpTime));
+
+                if (mFirstAccessUnit) {
+                    mFirstAccessUnit = false;
+                    mFirstAccessUnitNTP = ntpTime;
+                }
+                if (ntpTime > mFirstAccessUnitNTP) {
+                    ntpTime -= mFirstAccessUnitNTP;
+                } else {
+                    ntpTime = 0;
+                }
+
+                accessUnit->meta()->setInt64("ntp-time", ntpTime);
+
+#if 0
+                int32_t damaged;
+                if (accessUnit->meta()->findInt32("damaged", &damaged)
+                        && damaged != 0) {
+                    LOG(INFO) << "ignoring damaged AU";
+                } else
+#endif
+                {
+                    TrackInfo *track = &mTracks.editItemAt(trackIndex);
+                    track->mPacketSource->queueAccessUnit(accessUnit);
+                }
+                break;
+            }
+
+            default:
+                TRESPASS();
+                break;
+        }
+    }
+
+    sp<APacketSource> getPacketSource(size_t index) {
+        CHECK_GE(index, 0u);
+        CHECK_LT(index, mTracks.size());
+
+        return mTracks.editItemAt(index).mPacketSource;
+    }
+
+    size_t countTracks() const {
+        return mTracks.size();
+    }
+
+private:
+    sp<ALooper> mLooper;
+    sp<ALooper> mNetLooper;
+    sp<ARTSPConnection> mConn;
+    sp<ARTPConnection> mRTPConn;
+    sp<ASessionDescription> mSessionDesc;
+    AString mSessionURL;
+    AString mBaseURL;
+    AString mSessionID;
+    bool mSetupTracksSuccessful;
+    bool mFirstAccessUnit;
+    uint64_t mFirstAccessUnitNTP;
+
+    struct TrackInfo {
+        int mRTPSocket;
+        int mRTCPSocket;
+
+        sp<APacketSource> mPacketSource;
+    };
+    Vector<TrackInfo> mTracks;
+
+    void setupTrack(size_t index) {
+        AString url;
+        CHECK(mSessionDesc->findAttribute(index, "a=control", &url));
+
+        AString trackURL;
+        CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL));
+
+        mTracks.push(TrackInfo());
+        TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1);
+
+        unsigned rtpPort;
+        ARTPConnection::MakePortPair(
+                &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
+
+        AString request = "SETUP ";
+        request.append(trackURL);
+        request.append(" RTSP/1.0\r\n");
+
+        request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
+        request.append(rtpPort);
+        request.append("-");
+        request.append(rtpPort + 1);
+        request.append("\r\n");
+
+        if (index > 1) {
+            request.append("Session: ");
+            request.append(mSessionID);
+            request.append("\r\n");
+        }
+
+        request.append("\r\n");
+
+        sp<AMessage> reply = new AMessage('setu', id());
+        reply->setSize("index", index);
+        reply->setSize("track-index", mTracks.size() - 1);
+        mConn->sendRequest(request.c_str(), reply);
+    }
+
+    static bool MakeURL(const char *baseURL, const char *url, AString *out) {
+        out->clear();
+
+        if (strncasecmp("rtsp://", baseURL, 7)) {
+            // Base URL must be absolute
+            return false;
+        }
+
+        if (!strncasecmp("rtsp://", url, 7)) {
+            // "url" is already an absolute URL, ignore base URL.
+            out->setTo(url);
+            return true;
+        }
+
+        size_t n = strlen(baseURL);
+        if (baseURL[n - 1] == '/') {
+            out->setTo(baseURL);
+            out->append(url);
+        } else {
+            char *slashPos = strrchr(baseURL, '/');
+
+            if (slashPos > &baseURL[6]) {
+                out->setTo(baseURL, slashPos - baseURL);
+            } else {
+                out->setTo(baseURL);
+            }
+
+            out->append("/");
+            out->append(url);
+        }
+
+        return true;
+    }
+
+    DISALLOW_EVIL_CONSTRUCTORS(MyHandler);
+};
+
+}  // namespace android
+
+#endif  // MY_HANDLER_H_
diff --git a/media/libstagefright/rtsp/MyTransmitter.h b/media/libstagefright/rtsp/MyTransmitter.h
new file mode 100644
index 0000000..009a3b1
--- /dev/null
+++ b/media/libstagefright/rtsp/MyTransmitter.h
@@ -0,0 +1,981 @@
+/*
+ * Copyright (C) 2010 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 MY_TRANSMITTER_H_
+
+#define MY_TRANSMITTER_H_
+
+#include "ARTPConnection.h"
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <openssl/md5.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+#ifdef ANDROID
+#include "VideoSource.h"
+
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#endif
+
+namespace android {
+
+#define TRACK_SUFFIX    "trackid=1"
+#define PT              96
+#define PT_STR          "96"
+
+#define USERNAME        "bcast"
+#define PASSWORD        "test"
+
+static int uniformRand(int limit) {
+    return ((double)rand() * limit) / RAND_MAX;
+}
+
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+    value->clear();
+
+    size_t keyLen = strlen(key);
+
+    for (;;) {
+        const char *colonPos = strchr(s, ';');
+
+        size_t len =
+            (colonPos == NULL) ? strlen(s) : colonPos - s;
+
+        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
+            value->setTo(&s[keyLen + 1], len - keyLen - 1);
+            return true;
+        }
+
+        if (colonPos == NULL) {
+            return false;
+        }
+
+        s = colonPos + 1;
+    }
+}
+
+struct MyTransmitter : public AHandler {
+    MyTransmitter(const char *url, const sp<ALooper> &looper)
+        : mServerURL(url),
+          mLooper(looper),
+          mConn(new ARTSPConnection),
+          mConnected(false),
+          mAuthType(NONE),
+          mRTPSocket(-1),
+          mRTCPSocket(-1),
+          mSourceID(rand()),
+          mSeqNo(uniformRand(65536)),
+          mRTPTimeBase(rand()),
+          mNumSamplesSent(0),
+          mNumRTPSent(0),
+          mNumRTPOctetsSent(0),
+          mLastRTPTime(0),
+          mLastNTPTime(0) {
+        mStreamURL = mServerURL;
+        mStreamURL.append("/bazong.sdp");
+
+        mTrackURL = mStreamURL;
+        mTrackURL.append("/");
+        mTrackURL.append(TRACK_SUFFIX);
+
+        mLooper->registerHandler(this);
+        mLooper->registerHandler(mConn);
+
+        sp<AMessage> reply = new AMessage('conn', id());
+        mConn->connect(mServerURL.c_str(), reply);
+
+#ifdef ANDROID
+        int width = 640;
+        int height = 480;
+
+        sp<MediaSource> source = new VideoSource(width, height);
+
+        sp<MetaData> encMeta = new MetaData;
+        encMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+        encMeta->setInt32(kKeyWidth, width);
+        encMeta->setInt32(kKeyHeight, height);
+
+        OMXClient client;
+        client.connect();
+
+        mEncoder = OMXCodec::Create(
+                client.interface(), encMeta,
+                true /* createEncoder */, source);
+
+        mEncoder->start();
+
+        MediaBuffer *buffer;
+        CHECK_EQ(mEncoder->read(&buffer), (status_t)OK);
+        CHECK(buffer != NULL);
+
+        makeH264SPropParamSets(buffer);
+
+        buffer->release();
+        buffer = NULL;
+#endif
+    }
+
+    uint64_t ntpTime() {
+        struct timeval tv;
+        gettimeofday(&tv, NULL);
+
+        uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec;
+
+        nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
+
+        uint64_t hi = nowUs / 1000000ll;
+        uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
+
+        return (hi << 32) | lo;
+    }
+
+    void issueAnnounce() {
+        AString sdp;
+        sdp = "v=0\r\n";
+
+        sdp.append("o=- ");
+
+        uint64_t ntp = ntpTime();
+        sdp.append(ntp);
+        sdp.append(" ");
+        sdp.append(ntp);
+        sdp.append(" IN IP4 127.0.0.0\r\n");
+
+        sdp.append(
+              "s=Sample\r\n"
+              "i=Playing around with ANNOUNCE\r\n"
+              "c=IN IP4 ");
+
+        struct in_addr addr;
+        addr.s_addr = htonl(mServerIP);
+
+        sdp.append(inet_ntoa(addr));
+
+        sdp.append(
+              "\r\n"
+              "t=0 0\r\n"
+              "a=range:npt=now-\r\n");
+
+#ifdef ANDROID
+        sp<MetaData> meta = mEncoder->getFormat();
+        int32_t width, height;
+        CHECK(meta->findInt32(kKeyWidth, &width));
+        CHECK(meta->findInt32(kKeyHeight, &height));
+
+        sdp.append(
+              "m=video 0 RTP/AVP " PT_STR "\r\n"
+              "b=AS 320000\r\n"
+              "a=rtpmap:" PT_STR " H264/90000\r\n");
+
+        sdp.append("a=cliprect 0,0,");
+        sdp.append(height);
+        sdp.append(",");
+        sdp.append(width);
+        sdp.append("\r\n");
+
+        sdp.append(
+              "a=framesize:" PT_STR " ");
+        sdp.append(width);
+        sdp.append("-");
+        sdp.append(height);
+        sdp.append("\r\n");
+
+        sdp.append(
+              "a=fmtp:" PT_STR " profile-level-id=42C015;sprop-parameter-sets=");
+
+        sdp.append(mSeqParamSet);
+        sdp.append(",");
+        sdp.append(mPicParamSet);
+        sdp.append(";packetization-mode=1\r\n");
+#else
+        sdp.append(
+                "m=audio 0 RTP/AVP " PT_STR "\r\n"
+                "a=rtpmap:" PT_STR " L8/8000/1\r\n");
+#endif
+
+        sdp.append("a=control:" TRACK_SUFFIX "\r\n");
+
+        AString request;
+        request.append("ANNOUNCE ");
+        request.append(mStreamURL);
+        request.append(" RTSP/1.0\r\n");
+
+        addAuthentication(&request, "ANNOUNCE", mStreamURL.c_str());
+
+        request.append("Content-Type: application/sdp\r\n");
+        request.append("Content-Length: ");
+        request.append(sdp.size());
+        request.append("\r\n");
+
+        request.append("\r\n");
+        request.append(sdp);
+
+        sp<AMessage> reply = new AMessage('anno', id());
+        mConn->sendRequest(request.c_str(), reply);
+    }
+
+    void H(const AString &s, AString *out) {
+        out->clear();
+
+        MD5_CTX m;
+        MD5_Init(&m);
+        MD5_Update(&m, s.c_str(), s.size());
+
+        uint8_t key[16];
+        MD5_Final(key, &m);
+
+        for (size_t i = 0; i < 16; ++i) {
+            char nibble = key[i] >> 4;
+            if (nibble <= 9) {
+                nibble += '0';
+            } else {
+                nibble += 'a' - 10;
+            }
+            out->append(&nibble, 1);
+
+            nibble = key[i] & 0x0f;
+            if (nibble <= 9) {
+                nibble += '0';
+            } else {
+                nibble += 'a' - 10;
+            }
+            out->append(&nibble, 1);
+        }
+    }
+
+    void authenticate(const sp<ARTSPResponse> &response) {
+        ssize_t i = response->mHeaders.indexOfKey("www-authenticate");
+        CHECK_GE(i, 0);
+
+        AString value = response->mHeaders.valueAt(i);
+
+        if (!strncmp(value.c_str(), "Basic", 5)) {
+            mAuthType = BASIC;
+        } else {
+            CHECK(!strncmp(value.c_str(), "Digest", 6));
+            mAuthType = DIGEST;
+
+            i = value.find("nonce=");
+            CHECK_GE(i, 0);
+            CHECK_EQ(value.c_str()[i + 6], '\"');
+            ssize_t j = value.find("\"", i + 7);
+            CHECK_GE(j, 0);
+
+            mNonce.setTo(value, i + 7, j - i - 7);
+        }
+
+        issueAnnounce();
+    }
+
+    void addAuthentication(
+            AString *request, const char *method, const char *url) {
+        if (mAuthType == NONE) {
+            return;
+        }
+
+        if (mAuthType == BASIC) {
+            request->append("Authorization: Basic YmNhc3Q6dGVzdAo=\r\n");
+            return;
+        }
+
+        CHECK_EQ((int)mAuthType, (int)DIGEST);
+
+        AString A1;
+        A1.append(USERNAME);
+        A1.append(":");
+        A1.append("Streaming Server");
+        A1.append(":");
+        A1.append(PASSWORD);
+
+        AString A2;
+        A2.append(method);
+        A2.append(":");
+        A2.append(url);
+
+        AString HA1, HA2;
+        H(A1, &HA1);
+        H(A2, &HA2);
+
+        AString tmp;
+        tmp.append(HA1);
+        tmp.append(":");
+        tmp.append(mNonce);
+        tmp.append(":");
+        tmp.append(HA2);
+
+        AString digest;
+        H(tmp, &digest);
+
+        request->append("Authorization: Digest ");
+        request->append("nonce=\"");
+        request->append(mNonce);
+        request->append("\", ");
+        request->append("username=\"" USERNAME "\", ");
+        request->append("uri=\"");
+        request->append(url);
+        request->append("\", ");
+        request->append("response=\"");
+        request->append(digest);
+        request->append("\"");
+        request->append("\r\n");
+    }
+
+    virtual void onMessageReceived(const sp<AMessage> &msg) {
+        switch (msg->what()) {
+            case 'conn':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "connection request completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                if (result != OK) {
+                    (new AMessage('quit', id()))->post();
+                    break;
+                }
+
+                mConnected = true;
+
+                CHECK(msg->findInt32("server-ip", (int32_t *)&mServerIP));
+
+                issueAnnounce();
+                break;
+            }
+
+            case 'anno':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "ANNOUNCE completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                sp<RefBase> obj;
+                CHECK(msg->findObject("response", &obj));
+                sp<ARTSPResponse> response;
+
+                if (result == OK) {
+                    response = static_cast<ARTSPResponse *>(obj.get());
+                    CHECK(response != NULL);
+
+                    if (response->mStatusCode == 401) {
+                        if (mAuthType != NONE) {
+                            LOG(INFO) << "FAILED to authenticate";
+                            (new AMessage('quit', id()))->post();
+                            break;
+                        }
+
+                        authenticate(response);
+                        break;
+                    }
+                }
+
+                if (result != OK || response->mStatusCode != 200) {
+                    (new AMessage('quit', id()))->post();
+                    break;
+                }
+
+                unsigned rtpPort;
+                ARTPConnection::MakePortPair(&mRTPSocket, &mRTCPSocket, &rtpPort);
+
+                // (new AMessage('poll', id()))->post();
+
+                AString request;
+                request.append("SETUP ");
+                request.append(mTrackURL);
+                request.append(" RTSP/1.0\r\n");
+
+                addAuthentication(&request, "SETUP", mTrackURL.c_str());
+
+                request.append("Transport: RTP/AVP;unicast;client_port=");
+                request.append(rtpPort);
+                request.append("-");
+                request.append(rtpPort + 1);
+                request.append(";mode=record\r\n");
+                request.append("\r\n");
+
+                sp<AMessage> reply = new AMessage('setu', id());
+                mConn->sendRequest(request.c_str(), reply);
+                break;
+            }
+
+#if 0
+            case 'poll':
+            {
+                fd_set rs;
+                FD_ZERO(&rs);
+                FD_SET(mRTCPSocket, &rs);
+
+                struct timeval tv;
+                tv.tv_sec = 0;
+                tv.tv_usec = 0;
+
+                int res = select(mRTCPSocket + 1, &rs, NULL, NULL, &tv);
+
+                if (res == 1) {
+                    sp<ABuffer> buffer = new ABuffer(65536);
+                    ssize_t n = recv(mRTCPSocket, buffer->data(), buffer->size(), 0);
+
+                    if (n <= 0) {
+                        LOG(ERROR) << "recv returned " << n;
+                    } else {
+                        LOG(INFO) << "recv returned " << n << " bytes of data.";
+
+                        hexdump(buffer->data(), n);
+                    }
+                }
+
+                msg->post(50000);
+                break;
+            }
+#endif
+
+            case 'setu':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "SETUP completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                sp<RefBase> obj;
+                CHECK(msg->findObject("response", &obj));
+                sp<ARTSPResponse> response;
+
+                if (result == OK) {
+                    response = static_cast<ARTSPResponse *>(obj.get());
+                    CHECK(response != NULL);
+                }
+
+                if (result != OK || response->mStatusCode != 200) {
+                    (new AMessage('quit', id()))->post();
+                    break;
+                }
+
+                ssize_t i = response->mHeaders.indexOfKey("session");
+                CHECK_GE(i, 0);
+                mSessionID = response->mHeaders.valueAt(i);
+                i = mSessionID.find(";");
+                if (i >= 0) {
+                    // Remove options, i.e. ";timeout=90"
+                    mSessionID.erase(i, mSessionID.size() - i);
+                }
+
+                i = response->mHeaders.indexOfKey("transport");
+                CHECK_GE(i, 0);
+                AString transport = response->mHeaders.valueAt(i);
+
+                LOG(INFO) << "transport = '" << transport << "'";
+
+                AString value;
+                CHECK(GetAttribute(transport.c_str(), "server_port", &value));
+
+                unsigned rtpPort, rtcpPort;
+                CHECK_EQ(sscanf(value.c_str(), "%u-%u", &rtpPort, &rtcpPort), 2);
+
+                CHECK(GetAttribute(transport.c_str(), "source", &value));
+
+                memset(mRemoteAddr.sin_zero, 0, sizeof(mRemoteAddr.sin_zero));
+                mRemoteAddr.sin_family = AF_INET;
+                mRemoteAddr.sin_addr.s_addr = inet_addr(value.c_str());
+                mRemoteAddr.sin_port = htons(rtpPort);
+
+                mRemoteRTCPAddr = mRemoteAddr;
+                mRemoteRTCPAddr.sin_port = htons(rtpPort + 1);
+
+                CHECK_EQ(0, connect(mRTPSocket,
+                                    (const struct sockaddr *)&mRemoteAddr,
+                                    sizeof(mRemoteAddr)));
+
+                CHECK_EQ(0, connect(mRTCPSocket,
+                                    (const struct sockaddr *)&mRemoteRTCPAddr,
+                                    sizeof(mRemoteRTCPAddr)));
+
+                uint32_t x = ntohl(mRemoteAddr.sin_addr.s_addr);
+                LOG(INFO) << "sending data to "
+                     << (x >> 24)
+                     << "."
+                     << ((x >> 16) & 0xff)
+                     << "."
+                     << ((x >> 8) & 0xff)
+                     << "."
+                     << (x & 0xff)
+                     << ":"
+                     << rtpPort;
+
+                AString request;
+                request.append("RECORD ");
+                request.append(mStreamURL);
+                request.append(" RTSP/1.0\r\n");
+
+                addAuthentication(&request, "RECORD", mStreamURL.c_str());
+
+                request.append("Session: ");
+                request.append(mSessionID);
+                request.append("\r\n");
+                request.append("\r\n");
+
+                sp<AMessage> reply = new AMessage('reco', id());
+                mConn->sendRequest(request.c_str(), reply);
+                break;
+            }
+
+            case 'reco':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "RECORD completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                sp<RefBase> obj;
+                CHECK(msg->findObject("response", &obj));
+                sp<ARTSPResponse> response;
+
+                if (result == OK) {
+                    response = static_cast<ARTSPResponse *>(obj.get());
+                    CHECK(response != NULL);
+                }
+
+                if (result != OK) {
+                    (new AMessage('quit', id()))->post();
+                    break;
+                }
+
+                (new AMessage('more', id()))->post();
+                (new AMessage('sr  ', id()))->post();
+                (new AMessage('aliv', id()))->post(30000000ll);
+                break;
+            }
+
+            case 'aliv':
+            {
+                if (!mConnected) {
+                    break;
+                }
+
+                AString request;
+                request.append("OPTIONS ");
+                request.append(mStreamURL);
+                request.append(" RTSP/1.0\r\n");
+
+                addAuthentication(&request, "RECORD", mStreamURL.c_str());
+
+                request.append("Session: ");
+                request.append(mSessionID);
+                request.append("\r\n");
+                request.append("\r\n");
+
+                sp<AMessage> reply = new AMessage('opts', id());
+                mConn->sendRequest(request.c_str(), reply);
+                break;
+            }
+
+            case 'opts':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "OPTIONS completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                if (!mConnected) {
+                    break;
+                }
+
+                (new AMessage('aliv', id()))->post(30000000ll);
+                break;
+            }
+
+            case 'more':
+            {
+                if (!mConnected) {
+                    break;
+                }
+
+                sp<ABuffer> buffer = new ABuffer(65536);
+                uint8_t *data = buffer->data();
+                data[0] = 0x80;
+                data[1] = (1 << 7) | PT;  // M-bit
+                data[2] = (mSeqNo >> 8) & 0xff;
+                data[3] = mSeqNo & 0xff;
+                data[8] = mSourceID >> 24;
+                data[9] = (mSourceID >> 16) & 0xff;
+                data[10] = (mSourceID >> 8) & 0xff;
+                data[11] = mSourceID & 0xff;
+
+#ifdef ANDROID
+                MediaBuffer *mediaBuf = NULL;
+                for (;;) {
+                    CHECK_EQ(mEncoder->read(&mediaBuf), (status_t)OK);
+                    if (mediaBuf->range_length() > 0) {
+                        break;
+                    }
+                    mediaBuf->release();
+                    mediaBuf = NULL;
+                }
+
+                int64_t timeUs;
+                CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
+
+                uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+
+                const uint8_t *mediaData =
+                    (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+
+                CHECK(!memcmp("\x00\x00\x00\x01", mediaData, 4));
+
+                CHECK_LE(mediaBuf->range_length() - 4 + 12, buffer->size());
+
+                memcpy(&data[12],
+                       mediaData + 4, mediaBuf->range_length() - 4);
+
+                buffer->setRange(0, mediaBuf->range_length() - 4 + 12);
+
+                mediaBuf->release();
+                mediaBuf = NULL;
+#else
+                uint32_t rtpTime = mRTPTimeBase + mNumRTPSent * 128;
+                memset(&data[12], 0, 128);
+                buffer->setRange(0, 12 + 128);
+#endif
+
+                data[4] = rtpTime >> 24;
+                data[5] = (rtpTime >> 16) & 0xff;
+                data[6] = (rtpTime >> 8) & 0xff;
+                data[7] = rtpTime & 0xff;
+
+                ssize_t n = send(
+                        mRTPSocket, data, buffer->size(), 0);
+                if (n < 0) {
+                    LOG(ERROR) << "send failed (" << strerror(errno) << ")";
+                }
+                CHECK_EQ(n, (ssize_t)buffer->size());
+
+                ++mSeqNo;
+
+                ++mNumRTPSent;
+                mNumRTPOctetsSent += buffer->size() - 12;
+
+                mLastRTPTime = rtpTime;
+                mLastNTPTime = ntpTime();
+
+#ifdef ANDROID
+                if (mNumRTPSent < 60 * 25) {  // 60 secs worth
+                    msg->post(40000);
+#else
+                if (mNumRTPOctetsSent < 8000 * 60) {
+                    msg->post(1000000ll * 128 / 8000);
+#endif
+                } else {
+                    LOG(INFO) << "That's enough, pausing.";
+
+                    AString request;
+                    request.append("PAUSE ");
+                    request.append(mStreamURL);
+                    request.append(" RTSP/1.0\r\n");
+
+                    addAuthentication(&request, "PAUSE", mStreamURL.c_str());
+
+                    request.append("Session: ");
+                    request.append(mSessionID);
+                    request.append("\r\n");
+                    request.append("\r\n");
+
+                    sp<AMessage> reply = new AMessage('paus', id());
+                    mConn->sendRequest(request.c_str(), reply);
+                }
+                break;
+            }
+
+            case 'sr  ':
+            {
+                if (!mConnected) {
+                    break;
+                }
+
+                sp<ABuffer> buffer = new ABuffer(65536);
+                buffer->setRange(0, 0);
+
+                addSR(buffer);
+                addSDES(buffer);
+
+                uint8_t *data = buffer->data();
+                ssize_t n = send(
+                        mRTCPSocket, data, buffer->size(), 0);
+                CHECK_EQ(n, (ssize_t)buffer->size());
+
+                msg->post(3000000);
+                break;
+            }
+
+            case 'paus':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "PAUSE completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                sp<RefBase> obj;
+                CHECK(msg->findObject("response", &obj));
+                sp<ARTSPResponse> response;
+
+                AString request;
+                request.append("TEARDOWN ");
+                request.append(mStreamURL);
+                request.append(" RTSP/1.0\r\n");
+
+                addAuthentication(&request, "TEARDOWN", mStreamURL.c_str());
+
+                request.append("Session: ");
+                request.append(mSessionID);
+                request.append("\r\n");
+                request.append("\r\n");
+
+                sp<AMessage> reply = new AMessage('tear', id());
+                mConn->sendRequest(request.c_str(), reply);
+                break;
+            }
+
+            case 'tear':
+            {
+                int32_t result;
+                CHECK(msg->findInt32("result", &result));
+
+                LOG(INFO) << "TEARDOWN completed with result "
+                     << result << " (" << strerror(-result) << ")";
+
+                sp<RefBase> obj;
+                CHECK(msg->findObject("response", &obj));
+                sp<ARTSPResponse> response;
+
+                if (result == OK) {
+                    response = static_cast<ARTSPResponse *>(obj.get());
+                    CHECK(response != NULL);
+                }
+
+                (new AMessage('quit', id()))->post();
+                break;
+            }
+
+            case 'disc':
+            {
+                LOG(INFO) << "disconnect completed";
+
+                mConnected = false;
+                (new AMessage('quit', id()))->post();
+                break;
+            }
+
+            case 'quit':
+            {
+                if (mConnected) {
+                    mConn->disconnect(new AMessage('disc', id()));
+                    break;
+                }
+
+                if (mRTPSocket >= 0) {
+                    close(mRTPSocket);
+                    mRTPSocket = -1;
+                }
+
+                if (mRTCPSocket >= 0) {
+                    close(mRTCPSocket);
+                    mRTCPSocket = -1;
+                }
+
+#ifdef ANDROID
+                mEncoder->stop();
+                mEncoder.clear();
+#endif
+
+                mLooper->stop();
+                break;
+            }
+
+            default:
+                TRESPASS();
+        }
+    }
+
+protected:
+    virtual ~MyTransmitter() {
+    }
+
+private:
+    enum AuthType {
+        NONE,
+        BASIC,
+        DIGEST
+    };
+
+    AString mServerURL;
+    AString mTrackURL;
+    AString mStreamURL;
+
+    sp<ALooper> mLooper;
+    sp<ARTSPConnection> mConn;
+    bool mConnected;
+    uint32_t mServerIP;
+    AuthType mAuthType;
+    AString mNonce;
+    AString mSessionID;
+    int mRTPSocket, mRTCPSocket;
+    uint32_t mSourceID;
+    uint32_t mSeqNo;
+    uint32_t mRTPTimeBase;
+    struct sockaddr_in mRemoteAddr;
+    struct sockaddr_in mRemoteRTCPAddr;
+    size_t mNumSamplesSent;
+    uint32_t mNumRTPSent;
+    uint32_t mNumRTPOctetsSent;
+    uint32_t mLastRTPTime;
+    uint64_t mLastNTPTime;
+
+#ifdef ANDROID
+    sp<MediaSource> mEncoder;
+    AString mSeqParamSet;
+    AString mPicParamSet;
+
+    void makeH264SPropParamSets(MediaBuffer *buffer) {
+        static const char kStartCode[] = "\x00\x00\x00\x01";
+
+        const uint8_t *data =
+            (const uint8_t *)buffer->data() + buffer->range_offset();
+        size_t size = buffer->range_length();
+
+        CHECK_GE(size, 0u);
+        CHECK(!memcmp(kStartCode, data, 4));
+
+        data += 4;
+        size -= 4;
+
+        size_t startCodePos = 0;
+        while (startCodePos + 3 < size
+                && memcmp(kStartCode, &data[startCodePos], 4)) {
+            ++startCodePos;
+        }
+
+        CHECK_LT(startCodePos + 3, size);
+
+        encodeBase64(data, startCodePos, &mSeqParamSet);
+
+        encodeBase64(&data[startCodePos + 4], size - startCodePos - 4,
+                     &mPicParamSet);
+    }
+#endif
+
+    void addSR(const sp<ABuffer> &buffer) {
+        uint8_t *data = buffer->data() + buffer->size();
+
+        data[0] = 0x80 | 0;
+        data[1] = 200;  // SR
+        data[2] = 0;
+        data[3] = 6;
+        data[4] = mSourceID >> 24;
+        data[5] = (mSourceID >> 16) & 0xff;
+        data[6] = (mSourceID >> 8) & 0xff;
+        data[7] = mSourceID & 0xff;
+
+        data[8] = mLastNTPTime >> (64 - 8);
+        data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
+        data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
+        data[11] = (mLastNTPTime >> 32) & 0xff;
+        data[12] = (mLastNTPTime >> 24) & 0xff;
+        data[13] = (mLastNTPTime >> 16) & 0xff;
+        data[14] = (mLastNTPTime >> 8) & 0xff;
+        data[15] = mLastNTPTime & 0xff;
+
+        data[16] = (mLastRTPTime >> 24) & 0xff;
+        data[17] = (mLastRTPTime >> 16) & 0xff;
+        data[18] = (mLastRTPTime >> 8) & 0xff;
+        data[19] = mLastRTPTime & 0xff;
+
+        data[20] = mNumRTPSent >> 24;
+        data[21] = (mNumRTPSent >> 16) & 0xff;
+        data[22] = (mNumRTPSent >> 8) & 0xff;
+        data[23] = mNumRTPSent & 0xff;
+
+        data[24] = mNumRTPOctetsSent >> 24;
+        data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
+        data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
+        data[27] = mNumRTPOctetsSent & 0xff;
+
+        buffer->setRange(buffer->offset(), buffer->size() + 28);
+    }
+
+    void addSDES(const sp<ABuffer> &buffer) {
+        uint8_t *data = buffer->data() + buffer->size();
+        data[0] = 0x80 | 1;
+        data[1] = 202;  // SDES
+        data[4] = mSourceID >> 24;
+        data[5] = (mSourceID >> 16) & 0xff;
+        data[6] = (mSourceID >> 8) & 0xff;
+        data[7] = mSourceID & 0xff;
+
+        size_t offset = 8;
+
+        data[offset++] = 1;  // CNAME
+
+        static const char *kCNAME = "andih@laptop";
+        data[offset++] = strlen(kCNAME);
+
+        memcpy(&data[offset], kCNAME, strlen(kCNAME));
+        offset += strlen(kCNAME);
+
+        data[offset++] = 7;  // NOTE
+
+        static const char *kNOTE = "Hell's frozen over.";
+        data[offset++] = strlen(kNOTE);
+
+        memcpy(&data[offset], kNOTE, strlen(kNOTE));
+        offset += strlen(kNOTE);
+
+        data[offset++] = 0;
+
+        if ((offset % 4) > 0) {
+            size_t count = 4 - (offset % 4);
+            switch (count) {
+                case 3:
+                    data[offset++] = 0;
+                case 2:
+                    data[offset++] = 0;
+                case 1:
+                    data[offset++] = 0;
+            }
+        }
+
+        size_t numWords = (offset / 4) - 1;
+        data[2] = numWords >> 8;
+        data[3] = numWords & 0xff;
+
+        buffer->setRange(buffer->offset(), buffer->size() + offset);
+    }
+
+    DISALLOW_EVIL_CONSTRUCTORS(MyTransmitter);
+};
+
+}  // namespace android
+
+#endif  // MY_TRANSMITTER_H_
diff --git a/media/libstagefright/rtsp/VideoSource.h b/media/libstagefright/rtsp/VideoSource.h
new file mode 100644
index 0000000..ae0c85b
--- /dev/null
+++ b/media/libstagefright/rtsp/VideoSource.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 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 VIDEO_SOURCE_H_
+
+#define VIDEO_SOURCE_H_
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+class VideoSource : public MediaSource {
+    static const int32_t kFramerate = 24;  // fps
+
+public:
+    VideoSource(int width, int height)
+        : mWidth(width),
+          mHeight(height),
+          mSize((width * height * 3) / 2) {
+        mGroup.add_buffer(new MediaBuffer(mSize));
+    }
+
+    virtual sp<MetaData> getFormat() {
+        sp<MetaData> meta = new MetaData;
+        meta->setInt32(kKeyWidth, mWidth);
+        meta->setInt32(kKeyHeight, mHeight);
+        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+
+        return meta;
+    }
+
+    virtual status_t start(MetaData *params) {
+        mNumFramesOutput = 0;
+        return OK;
+    }
+
+    virtual status_t stop() {
+        return OK;
+    }
+
+    virtual status_t read(
+            MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
+        if (mNumFramesOutput == kFramerate * 100) {
+            // Stop returning data after 10 secs.
+            return ERROR_END_OF_STREAM;
+        }
+
+        // printf("VideoSource::read\n");
+        status_t err = mGroup.acquire_buffer(buffer);
+        if (err != OK) {
+            return err;
+        }
+
+        char x = (char)((double)rand() / RAND_MAX * 255);
+        memset((*buffer)->data(), x, mSize);
+        (*buffer)->set_range(0, mSize);
+        (*buffer)->meta_data()->clear();
+        (*buffer)->meta_data()->setInt64(
+                kKeyTime, (mNumFramesOutput * 1000000) / kFramerate);
+        ++mNumFramesOutput;
+
+        // printf("VideoSource::read - returning buffer\n");
+        // LOG(INFO)("VideoSource::read - returning buffer");
+        return OK;
+    }
+
+protected:
+    virtual ~VideoSource() {}
+
+private:
+    MediaBufferGroup mGroup;
+    int mWidth, mHeight;
+    size_t mSize;
+    int64_t mNumFramesOutput;;
+
+    VideoSource(const VideoSource &);
+    VideoSource &operator=(const VideoSource &);
+};
+
+}  // namespace android
+
+#endif  // VIDEO_SOURCE_H_
diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk
index a92cea8..0559812 100644
--- a/media/mediaserver/Android.mk
+++ b/media/mediaserver/Android.mk
@@ -14,8 +14,8 @@
 base := $(LOCAL_PATH)/../..
 
 LOCAL_C_INCLUDES := \
-    $(base)/libs/audioflinger \
-    $(base)/camera/libcameraservice \
+    $(base)/services/audioflinger \
+    $(base)/services/camera/libcameraservice \
     $(base)/media/libmediaplayerservice
 
 LOCAL_MODULE:= mediaserver
diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
new file mode 100644
index 0000000..995e31c
--- /dev/null
+++ b/services/audioflinger/A2dpAudioInterface.cpp
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <math.h>
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "A2dpAudioInterface"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include "A2dpAudioInterface.h"
+#include "audio/liba2dp.h"
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
+//{
+//    AudioHardwareInterface* hw = 0;
+//
+//    hw = AudioHardwareInterface::create();
+//    LOGD("new A2dpAudioInterface(hw: %p)", hw);
+//    hw = new A2dpAudioInterface(hw);
+//    return hw;
+//}
+
+A2dpAudioInterface::A2dpAudioInterface(AudioHardwareInterface* hw) :
+    mOutput(0), mHardwareInterface(hw), mBluetoothEnabled(true), mSuspended(false)
+{
+}
+
+A2dpAudioInterface::~A2dpAudioInterface()
+{
+    closeOutputStream((AudioStreamOut *)mOutput);
+    delete mHardwareInterface;
+}
+
+status_t A2dpAudioInterface::initCheck()
+{
+    if (mHardwareInterface == 0) return NO_INIT;
+    return mHardwareInterface->initCheck();
+}
+
+AudioStreamOut* A2dpAudioInterface::openOutputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
+{
+    if (!AudioSystem::isA2dpDevice((AudioSystem::audio_devices)devices)) {
+        LOGV("A2dpAudioInterface::openOutputStream() open HW device: %x", devices);
+        return mHardwareInterface->openOutputStream(devices, format, channels, sampleRate, status);
+    }
+
+    status_t err = 0;
+
+    // only one output stream allowed
+    if (mOutput) {
+        if (status)
+            *status = -1;
+        return NULL;
+    }
+
+    // create new output stream
+    A2dpAudioStreamOut* out = new A2dpAudioStreamOut();
+    if ((err = out->set(devices, format, channels, sampleRate)) == NO_ERROR) {
+        mOutput = out;
+        mOutput->setBluetoothEnabled(mBluetoothEnabled);
+        mOutput->setSuspended(mSuspended);
+    } else {
+        delete out;
+    }
+
+    if (status)
+        *status = err;
+    return mOutput;
+}
+
+void A2dpAudioInterface::closeOutputStream(AudioStreamOut* out) {
+    if (mOutput == 0 || mOutput != out) {
+        mHardwareInterface->closeOutputStream(out);
+    }
+    else {
+        delete mOutput;
+        mOutput = 0;
+    }
+}
+
+
+AudioStreamIn* A2dpAudioInterface::openInputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
+        AudioSystem::audio_in_acoustics acoustics)
+{
+    return mHardwareInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
+}
+
+void A2dpAudioInterface::closeInputStream(AudioStreamIn* in)
+{
+    return mHardwareInterface->closeInputStream(in);
+}
+
+status_t A2dpAudioInterface::setMode(int mode)
+{
+    return mHardwareInterface->setMode(mode);
+}
+
+status_t A2dpAudioInterface::setMicMute(bool state)
+{
+    return mHardwareInterface->setMicMute(state);
+}
+
+status_t A2dpAudioInterface::getMicMute(bool* state)
+{
+    return mHardwareInterface->getMicMute(state);
+}
+
+status_t A2dpAudioInterface::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    String8 key;
+    status_t status = NO_ERROR;
+
+    LOGV("setParameters() %s", keyValuePairs.string());
+
+    key = "bluetooth_enabled";
+    if (param.get(key, value) == NO_ERROR) {
+        mBluetoothEnabled = (value == "true");
+        if (mOutput) {
+            mOutput->setBluetoothEnabled(mBluetoothEnabled);
+        }
+        param.remove(key);
+    }
+    key = String8("A2dpSuspended");
+    if (param.get(key, value) == NO_ERROR) {
+        mSuspended = (value == "true");
+        if (mOutput) {
+            mOutput->setSuspended(mSuspended);
+        }
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status_t hwStatus = mHardwareInterface->setParameters(param.toString());
+        if (status == NO_ERROR) {
+            status = hwStatus;
+        }
+    }
+
+    return status;
+}
+
+String8 A2dpAudioInterface::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    AudioParameter a2dpParam = AudioParameter();
+    String8 value;
+    String8 key;
+
+    key = "bluetooth_enabled";
+    if (param.get(key, value) == NO_ERROR) {
+        value = mBluetoothEnabled ? "true" : "false";
+        a2dpParam.add(key, value);
+        param.remove(key);
+    }
+    key = "A2dpSuspended";
+    if (param.get(key, value) == NO_ERROR) {
+        value = mSuspended ? "true" : "false";
+        a2dpParam.add(key, value);
+        param.remove(key);
+    }
+
+    String8 keyValuePairs  = a2dpParam.toString();
+
+    if (param.size()) {
+        if (keyValuePairs != "") {
+            keyValuePairs += ";";
+        }
+        keyValuePairs += mHardwareInterface->getParameters(param.toString());
+    }
+
+    LOGV("getParameters() %s", keyValuePairs.string());
+    return keyValuePairs;
+}
+
+size_t A2dpAudioInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+    return mHardwareInterface->getInputBufferSize(sampleRate, format, channelCount);
+}
+
+status_t A2dpAudioInterface::setVoiceVolume(float v)
+{
+    return mHardwareInterface->setVoiceVolume(v);
+}
+
+status_t A2dpAudioInterface::setMasterVolume(float v)
+{
+    return mHardwareInterface->setMasterVolume(v);
+}
+
+status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& args)
+{
+    return mHardwareInterface->dumpState(fd, args);
+}
+
+// ----------------------------------------------------------------------------
+
+A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
+    mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
+    // assume BT enabled to start, this is safe because its only the
+    // enabled->disabled transition we are worried about
+    mBluetoothEnabled(true), mDevice(0), mClosing(false), mSuspended(false)
+{
+    // use any address by default
+    strcpy(mA2dpAddress, "00:00:00:00:00:00");
+    init();
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
+        uint32_t device, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
+{
+    int lFormat = pFormat ? *pFormat : 0;
+    uint32_t lChannels = pChannels ? *pChannels : 0;
+    uint32_t lRate = pRate ? *pRate : 0;
+
+    LOGD("A2dpAudioStreamOut::set %x, %d, %d, %d\n", device, lFormat, lChannels, lRate);
+
+    // fix up defaults
+    if (lFormat == 0) lFormat = format();
+    if (lChannels == 0) lChannels = channels();
+    if (lRate == 0) lRate = sampleRate();
+
+    // check values
+    if ((lFormat != format()) ||
+            (lChannels != channels()) ||
+            (lRate != sampleRate())){
+        if (pFormat) *pFormat = format();
+        if (pChannels) *pChannels = channels();
+        if (pRate) *pRate = sampleRate();
+        return BAD_VALUE;
+    }
+
+    if (pFormat) *pFormat = lFormat;
+    if (pChannels) *pChannels = lChannels;
+    if (pRate) *pRate = lRate;
+
+    mDevice = device;
+    return NO_ERROR;
+}
+
+A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
+{
+    LOGV("A2dpAudioStreamOut destructor");
+    standby();
+    close();
+    LOGV("A2dpAudioStreamOut destructor returning from close()");
+}
+
+ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
+{
+    Mutex::Autolock lock(mLock);
+
+    size_t remaining = bytes;
+    status_t status = -1;
+
+    if (!mBluetoothEnabled || mClosing || mSuspended) {
+        LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
+               mBluetoothEnabled %d, mClosing %d, mSuspended %d",
+                mBluetoothEnabled, mClosing, mSuspended);
+        goto Error;
+    }
+
+    status = init();
+    if (status < 0)
+        goto Error;
+
+    while (remaining > 0) {
+        status = a2dp_write(mData, buffer, remaining);
+        if (status <= 0) {
+            LOGE("a2dp_write failed err: %d\n", status);
+            goto Error;
+        }
+        remaining -= status;
+        buffer = ((char *)buffer) + status;
+    }
+
+    mStandby = false;
+
+    return bytes;
+
+Error:
+    // Simulate audio output timing in case of error
+    usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
+
+    return status;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
+{
+    if (!mData) {
+        status_t status = a2dp_init(44100, 2, &mData);
+        if (status < 0) {
+            LOGE("a2dp_init failed err: %d\n", status);
+            mData = NULL;
+            return status;
+        }
+        a2dp_set_sink(mData, mA2dpAddress);
+    }
+
+    return 0;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
+{
+    int result = 0;
+
+    if (mClosing) {
+        LOGV("Ignore standby, closing");
+        return result;
+    }
+
+    Mutex::Autolock lock(mLock);
+
+    if (!mStandby) {
+        result = a2dp_stop(mData);
+        if (result == 0)
+            mStandby = true;
+    }
+
+    return result;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    String8 key = String8("a2dp_sink_address");
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("A2dpAudioStreamOut::setParameters() %s", keyValuePairs.string());
+
+    if (param.get(key, value) == NO_ERROR) {
+        if (value.length() != strlen("00:00:00:00:00:00")) {
+            status = BAD_VALUE;
+        } else {
+            setAddress(value.string());
+        }
+        param.remove(key);
+    }
+    key = String8("closing");
+    if (param.get(key, value) == NO_ERROR) {
+        mClosing = (value == "true");
+        param.remove(key);
+    }
+    key = AudioParameter::keyRouting;
+    if (param.getInt(key, device) == NO_ERROR) {
+        if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) {
+            mDevice = device;
+            status = NO_ERROR;
+        } else {
+            status = BAD_VALUE;
+        }
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 A2dpAudioInterface::A2dpAudioStreamOut::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8("a2dp_sink_address");
+
+    if (param.get(key, value) == NO_ERROR) {
+        value = mA2dpAddress;
+        param.add(key, value);
+    }
+    key = AudioParameter::keyRouting;
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("A2dpAudioStreamOut::getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (strlen(address) != strlen("00:00:00:00:00:00"))
+        return -EINVAL;
+
+    strcpy(mA2dpAddress, address);
+    if (mData)
+        a2dp_set_sink(mData, mA2dpAddress);
+
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setBluetoothEnabled(bool enabled)
+{
+    LOGD("setBluetoothEnabled %d", enabled);
+
+    Mutex::Autolock lock(mLock);
+
+    mBluetoothEnabled = enabled;
+    if (!enabled) {
+        return close_l();
+    }
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::setSuspended(bool onOff)
+{
+    LOGV("setSuspended %d", onOff);
+    mSuspended = onOff;
+    standby();
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
+{
+    Mutex::Autolock lock(mLock);
+    LOGV("A2dpAudioStreamOut::close() calling close_l()");
+    return close_l();
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
+{
+    if (mData) {
+        LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
+        a2dp_cleanup(mData);
+        mData = NULL;
+    }
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::dump(int fd, const Vector<String16>& args)
+{
+    return NO_ERROR;
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::getRenderPosition(uint32_t *driverFrames)
+{
+    //TODO: enable when supported by driver
+    return INVALID_OPERATION;
+}
+
+}; // namespace android
diff --git a/services/audioflinger/A2dpAudioInterface.h b/services/audioflinger/A2dpAudioInterface.h
new file mode 100644
index 0000000..48154f9
--- /dev/null
+++ b/services/audioflinger/A2dpAudioInterface.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2008 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 A2DP_AUDIO_HARDWARE_H
+#define A2DP_AUDIO_HARDWARE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+
+#include <hardware_legacy/AudioHardwareBase.h>
+
+
+namespace android {
+
+class A2dpAudioInterface : public AudioHardwareBase
+{
+    class A2dpAudioStreamOut;
+
+public:
+                        A2dpAudioInterface(AudioHardwareInterface* hw);
+    virtual             ~A2dpAudioInterface();
+    virtual status_t    initCheck();
+
+    virtual status_t    setVoiceVolume(float volume);
+    virtual status_t    setMasterVolume(float volume);
+
+    virtual status_t    setMode(int mode);
+
+    // mic mute
+    virtual status_t    setMicMute(bool state);
+    virtual status_t    getMicMute(bool* state);
+
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+
+    virtual size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
+
+    // create I/O streams
+    virtual AudioStreamOut* openOutputStream(
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
+                                status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
+
+    virtual AudioStreamIn* openInputStream(
+                                uint32_t devices,
+                                int *format,
+                                uint32_t *channels,
+                                uint32_t *sampleRate,
+                                status_t *status,
+                                AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
+//    static AudioHardwareInterface* createA2dpInterface();
+
+protected:
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+
+private:
+    class A2dpAudioStreamOut : public AudioStreamOut {
+    public:
+                            A2dpAudioStreamOut();
+        virtual             ~A2dpAudioStreamOut();
+                status_t    set(uint32_t device,
+                                int *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pRate);
+        virtual uint32_t    sampleRate() const { return 44100; }
+        // SBC codec wants a multiple of 512
+        virtual size_t      bufferSize() const { return 512 * 20; }
+        virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
+        virtual int         format() const { return AudioSystem::PCM_16_BIT; }
+        virtual uint32_t    latency() const { return ((1000*bufferSize())/frameSize())/sampleRate() + 200; }
+        virtual status_t    setVolume(float left, float right) { return INVALID_OPERATION; }
+        virtual ssize_t     write(const void* buffer, size_t bytes);
+                status_t    standby();
+        virtual status_t    dump(int fd, const Vector<String16>& args);
+        virtual status_t    setParameters(const String8& keyValuePairs);
+        virtual String8     getParameters(const String8& keys);
+        virtual status_t    getRenderPosition(uint32_t *dspFrames);
+
+    private:
+        friend class A2dpAudioInterface;
+                status_t    init();
+                status_t    close();
+                status_t    close_l();
+                status_t    setAddress(const char* address);
+                status_t    setBluetoothEnabled(bool enabled);
+                status_t    setSuspended(bool onOff);
+
+    private:
+                int         mFd;
+                bool        mStandby;
+                int         mStartCount;
+                int         mRetryCount;
+                char        mA2dpAddress[20];
+                void*       mData;
+                Mutex       mLock;
+                bool        mBluetoothEnabled;
+                uint32_t    mDevice;
+                bool        mClosing;
+                bool        mSuspended;
+    };
+
+    friend class A2dpAudioStreamOut;
+
+    A2dpAudioStreamOut*     mOutput;
+    AudioHardwareInterface  *mHardwareInterface;
+    char        mA2dpAddress[20];
+    bool        mBluetoothEnabled;
+    bool        mSuspended;
+};
+
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // A2DP_AUDIO_HARDWARE_H
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
new file mode 100644
index 0000000..22ecc54
--- /dev/null
+++ b/services/audioflinger/Android.mk
@@ -0,0 +1,131 @@
+LOCAL_PATH:= $(call my-dir)
+
+#AUDIO_POLICY_TEST := true
+#ENABLE_AUDIO_DUMP := true
+
+include $(CLEAR_VARS)
+
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  ENABLE_AUDIO_DUMP := true
+endif
+
+
+LOCAL_SRC_FILES:= \
+    AudioHardwareGeneric.cpp \
+    AudioHardwareStub.cpp \
+    AudioHardwareInterface.cpp
+
+ifeq ($(ENABLE_AUDIO_DUMP),true)
+  LOCAL_SRC_FILES += AudioDumpInterface.cpp
+  LOCAL_CFLAGS += -DENABLE_AUDIO_DUMP
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libbinder \
+    libmedia \
+    libhardware_legacy
+
+ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
+  LOCAL_CFLAGS += -DGENERIC_AUDIO
+endif
+
+LOCAL_MODULE:= libaudiointerface
+
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+  LOCAL_SRC_FILES += A2dpAudioInterface.cpp
+  LOCAL_SHARED_LIBRARIES += liba2dp
+  LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
+  LOCAL_C_INCLUDES += $(call include-path-for, bluez)
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    AudioPolicyManagerBase.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libmedia
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_MODULE:= libaudiopolicybase
+
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+  LOCAL_CFLAGS += -DWITH_A2DP
+endif
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    AudioFlinger.cpp            \
+    AudioMixer.cpp.arm          \
+    AudioResampler.cpp.arm      \
+    AudioResamplerSinc.cpp.arm  \
+    AudioResamplerCubic.cpp.arm \
+    AudioPolicyService.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libbinder \
+    libmedia \
+    libhardware_legacy \
+    libeffects
+
+ifeq ($(strip $(BOARD_USES_GENERIC_AUDIO)),true)
+  LOCAL_STATIC_LIBRARIES += libaudiointerface libaudiopolicybase
+  LOCAL_CFLAGS += -DGENERIC_AUDIO
+else
+  LOCAL_SHARED_LIBRARIES += libaudio libaudiopolicy
+endif
+
+ifeq ($(TARGET_SIMULATOR),true)
+ LOCAL_LDLIBS += -ldl
+else
+ LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_MODULE:= libaudioflinger
+
+ifeq ($(BOARD_HAVE_BLUETOOTH),true)
+  LOCAL_CFLAGS += -DWITH_BLUETOOTH -DWITH_A2DP
+  LOCAL_SHARED_LIBRARIES += liba2dp
+endif
+
+ifeq ($(AUDIO_POLICY_TEST),true)
+  LOCAL_CFLAGS += -DAUDIO_POLICY_TEST
+endif
+
+ifeq ($(TARGET_SIMULATOR),true)
+    ifeq ($(HOST_OS),linux)
+        LOCAL_LDLIBS += -lrt -lpthread
+    endif
+endif
+
+ifeq ($(BOARD_USE_LVMX),true)
+    LOCAL_CFLAGS += -DLVMX
+    LOCAL_C_INCLUDES += vendor/nxp
+    LOCAL_STATIC_LIBRARIES += liblifevibes
+    LOCAL_SHARED_LIBRARIES += liblvmxservice
+#    LOCAL_SHARED_LIBRARIES += liblvmxipc
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/audioflinger/AudioBufferProvider.h b/services/audioflinger/AudioBufferProvider.h
new file mode 100644
index 0000000..81c5c39
--- /dev/null
+++ b/services/audioflinger/AudioBufferProvider.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 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 ANDROID_AUDIO_BUFFER_PROVIDER_H
+#define ANDROID_AUDIO_BUFFER_PROVIDER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Errors.h>
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioBufferProvider
+{
+public:
+
+    struct Buffer {
+        union {
+            void*       raw;
+            short*      i16;
+            int8_t*     i8;
+        };
+        size_t frameCount;
+    };
+
+    virtual ~AudioBufferProvider() {}
+    
+    virtual status_t getNextBuffer(Buffer* buffer) = 0;
+    virtual void releaseBuffer(Buffer* buffer) = 0;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_AUDIO_BUFFER_PROVIDER_H
diff --git a/services/audioflinger/AudioDumpInterface.cpp b/services/audioflinger/AudioDumpInterface.cpp
new file mode 100644
index 0000000..6c11114
--- /dev/null
+++ b/services/audioflinger/AudioDumpInterface.cpp
@@ -0,0 +1,573 @@
+/* //device/servers/AudioFlinger/AudioDumpInterface.cpp
+**
+** Copyright 2008, 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_TAG "AudioFlingerDump"
+//#define LOG_NDEBUG 0
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Log.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "AudioDumpInterface.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+AudioDumpInterface::AudioDumpInterface(AudioHardwareInterface* hw)
+    : mPolicyCommands(String8("")), mFileName(String8(""))
+{
+    if(hw == 0) {
+        LOGE("Dump construct hw = 0");
+    }
+    mFinalInterface = hw;
+    LOGV("Constructor %p, mFinalInterface %p", this, mFinalInterface);
+}
+
+
+AudioDumpInterface::~AudioDumpInterface()
+{
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        closeOutputStream((AudioStreamOut *)mOutputs[i]);
+    }
+
+    for (size_t i = 0; i < mInputs.size(); i++) {
+        closeInputStream((AudioStreamIn *)mInputs[i]);
+    }
+
+    if(mFinalInterface) delete mFinalInterface;
+}
+
+
+AudioStreamOut* AudioDumpInterface::openOutputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
+{
+    AudioStreamOut* outFinal = NULL;
+    int lFormat = AudioSystem::PCM_16_BIT;
+    uint32_t lChannels = AudioSystem::CHANNEL_OUT_STEREO;
+    uint32_t lRate = 44100;
+
+
+    outFinal = mFinalInterface->openOutputStream(devices, format, channels, sampleRate, status);
+    if (outFinal != 0) {
+        lFormat = outFinal->format();
+        lChannels = outFinal->channels();
+        lRate = outFinal->sampleRate();
+    } else {
+        if (format != 0) {
+            if (*format != 0) {
+                lFormat = *format;
+            } else {
+                *format = lFormat;
+            }
+        }
+        if (channels != 0) {
+            if (*channels != 0) {
+                lChannels = *channels;
+            } else {
+                *channels = lChannels;
+            }
+        }
+        if (sampleRate != 0) {
+            if (*sampleRate != 0) {
+                lRate = *sampleRate;
+            } else {
+                *sampleRate = lRate;
+            }
+        }
+        if (status) *status = NO_ERROR;
+    }
+    LOGV("openOutputStream(), outFinal %p", outFinal);
+
+    AudioStreamOutDump *dumOutput = new AudioStreamOutDump(this, mOutputs.size(), outFinal,
+            devices, lFormat, lChannels, lRate);
+    mOutputs.add(dumOutput);
+
+    return dumOutput;
+}
+
+void AudioDumpInterface::closeOutputStream(AudioStreamOut* out)
+{
+    AudioStreamOutDump *dumpOut = (AudioStreamOutDump *)out;
+
+    if (mOutputs.indexOf(dumpOut) < 0) {
+        LOGW("Attempt to close invalid output stream");
+        return;
+    }
+
+    LOGV("closeOutputStream() output %p", out);
+
+    dumpOut->standby();
+    if (dumpOut->finalStream() != NULL) {
+        mFinalInterface->closeOutputStream(dumpOut->finalStream());
+    }
+
+    mOutputs.remove(dumpOut);
+    delete dumpOut;
+}
+
+AudioStreamIn* AudioDumpInterface::openInputStream(uint32_t devices, int *format, uint32_t *channels,
+        uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics)
+{
+    AudioStreamIn* inFinal = NULL;
+    int lFormat = AudioSystem::PCM_16_BIT;
+    uint32_t lChannels = AudioSystem::CHANNEL_IN_MONO;
+    uint32_t lRate = 8000;
+
+    inFinal = mFinalInterface->openInputStream(devices, format, channels, sampleRate, status, acoustics);
+    if (inFinal != 0) {
+        lFormat = inFinal->format();
+        lChannels = inFinal->channels();
+        lRate = inFinal->sampleRate();
+    } else {
+        if (format != 0) {
+            if (*format != 0) {
+                lFormat = *format;
+            } else {
+                *format = lFormat;
+            }
+        }
+        if (channels != 0) {
+            if (*channels != 0) {
+                lChannels = *channels;
+            } else {
+                *channels = lChannels;
+            }
+        }
+        if (sampleRate != 0) {
+            if (*sampleRate != 0) {
+                lRate = *sampleRate;
+            } else {
+                *sampleRate = lRate;
+            }
+        }
+        if (status) *status = NO_ERROR;
+    }
+    LOGV("openInputStream(), inFinal %p", inFinal);
+
+    AudioStreamInDump *dumInput = new AudioStreamInDump(this, mInputs.size(), inFinal,
+            devices, lFormat, lChannels, lRate);
+    mInputs.add(dumInput);
+
+    return dumInput;
+}
+void AudioDumpInterface::closeInputStream(AudioStreamIn* in)
+{
+    AudioStreamInDump *dumpIn = (AudioStreamInDump *)in;
+
+    if (mInputs.indexOf(dumpIn) < 0) {
+        LOGW("Attempt to close invalid input stream");
+        return;
+    }
+    dumpIn->standby();
+    if (dumpIn->finalStream() != NULL) {
+        mFinalInterface->closeInputStream(dumpIn->finalStream());
+    }
+
+    mInputs.remove(dumpIn);
+    delete dumpIn;
+}
+
+
+status_t AudioDumpInterface::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    int valueInt;
+    LOGV("setParameters %s", keyValuePairs.string());
+
+    if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
+        mFileName = value;
+        param.remove(String8("test_cmd_file_name"));
+    }
+    if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
+        Mutex::Autolock _l(mLock);
+        param.remove(String8("test_cmd_policy"));
+        mPolicyCommands = param.toString();
+        LOGV("test_cmd_policy command %s written", mPolicyCommands.string());
+        return NO_ERROR;
+    }
+
+    if (mFinalInterface != 0 ) return mFinalInterface->setParameters(keyValuePairs);
+    return NO_ERROR;
+}
+
+String8 AudioDumpInterface::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    AudioParameter response;
+    String8 value;
+
+//    LOGV("getParameters %s", keys.string());
+    if (param.get(String8("test_cmd_policy"), value) == NO_ERROR) {
+        Mutex::Autolock _l(mLock);
+        if (mPolicyCommands.length() != 0) {
+            response = AudioParameter(mPolicyCommands);
+            response.addInt(String8("test_cmd_policy"), 1);
+        } else {
+            response.addInt(String8("test_cmd_policy"), 0);
+        }
+        param.remove(String8("test_cmd_policy"));
+//        LOGV("test_cmd_policy command %s read", mPolicyCommands.string());
+    }
+
+    if (param.get(String8("test_cmd_file_name"), value) == NO_ERROR) {
+        response.add(String8("test_cmd_file_name"), mFileName);
+        param.remove(String8("test_cmd_file_name"));
+    }
+
+    String8 keyValuePairs = response.toString();
+
+    if (param.size() && mFinalInterface != 0 ) {
+        keyValuePairs += ";";
+        keyValuePairs += mFinalInterface->getParameters(param.toString());
+    }
+
+    return keyValuePairs;
+}
+
+status_t AudioDumpInterface::setMode(int mode)
+{
+    return mFinalInterface->setMode(mode);
+}
+
+size_t AudioDumpInterface::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+    return mFinalInterface->getInputBufferSize(sampleRate, format, channelCount);
+}
+
+// ----------------------------------------------------------------------------
+
+AudioStreamOutDump::AudioStreamOutDump(AudioDumpInterface *interface,
+                                        int id,
+                                        AudioStreamOut* finalStream,
+                                        uint32_t devices,
+                                        int format,
+                                        uint32_t channels,
+                                        uint32_t sampleRate)
+    : mInterface(interface), mId(id),
+      mSampleRate(sampleRate), mFormat(format), mChannels(channels), mLatency(0), mDevice(devices),
+      mBufferSize(1024), mFinalStream(finalStream), mFile(0), mFileCount(0)
+{
+    LOGV("AudioStreamOutDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
+}
+
+
+AudioStreamOutDump::~AudioStreamOutDump()
+{
+    LOGV("AudioStreamOutDump destructor");
+    Close();
+}
+
+ssize_t AudioStreamOutDump::write(const void* buffer, size_t bytes)
+{
+    ssize_t ret;
+
+    if (mFinalStream) {
+        ret = mFinalStream->write(buffer, bytes);
+    } else {
+        usleep((((bytes * 1000) / frameSize()) / sampleRate()) * 1000);
+        ret = bytes;
+    }
+    if(!mFile) {
+        if (mInterface->fileName() != "") {
+            char name[255];
+            sprintf(name, "%s_out_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
+            mFile = fopen(name, "wb");
+            LOGV("Opening dump file %s, fh %p", name, mFile);
+        }
+    }
+    if (mFile) {
+        fwrite(buffer, bytes, 1, mFile);
+    }
+    return ret;
+}
+
+status_t AudioStreamOutDump::standby()
+{
+    LOGV("AudioStreamOutDump standby(), mFile %p, mFinalStream %p", mFile, mFinalStream);
+
+    Close();
+    if (mFinalStream != 0 ) return mFinalStream->standby();
+    return NO_ERROR;
+}
+
+uint32_t AudioStreamOutDump::sampleRate() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->sampleRate();
+    return mSampleRate;
+}
+
+size_t AudioStreamOutDump::bufferSize() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->bufferSize();
+    return mBufferSize;
+}
+
+uint32_t AudioStreamOutDump::channels() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->channels();
+    return mChannels;
+}
+int AudioStreamOutDump::format() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->format();
+    return mFormat;
+}
+uint32_t AudioStreamOutDump::latency() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->latency();
+    return 0;
+}
+status_t AudioStreamOutDump::setVolume(float left, float right)
+{
+    if (mFinalStream != 0 ) return mFinalStream->setVolume(left, right);
+    return NO_ERROR;
+}
+status_t AudioStreamOutDump::setParameters(const String8& keyValuePairs)
+{
+    LOGV("AudioStreamOutDump::setParameters %s", keyValuePairs.string());
+
+    if (mFinalStream != 0 ) {
+        return mFinalStream->setParameters(keyValuePairs);
+    }
+
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 value;
+    int valueInt;
+    status_t status = NO_ERROR;
+
+    if (param.getInt(String8("set_id"), valueInt) == NO_ERROR) {
+        mId = valueInt;
+    }
+
+    if (param.getInt(String8("format"), valueInt) == NO_ERROR) {
+        if (mFile == 0) {
+            mFormat = valueInt;
+        } else {
+            status = INVALID_OPERATION;
+        }
+    }
+    if (param.getInt(String8("channels"), valueInt) == NO_ERROR) {
+        if (valueInt == AudioSystem::CHANNEL_OUT_STEREO || valueInt == AudioSystem::CHANNEL_OUT_MONO) {
+            mChannels = valueInt;
+        } else {
+            status = BAD_VALUE;
+        }
+    }
+    if (param.getInt(String8("sampling_rate"), valueInt) == NO_ERROR) {
+        if (valueInt > 0 && valueInt <= 48000) {
+            if (mFile == 0) {
+                mSampleRate = valueInt;
+            } else {
+                status = INVALID_OPERATION;
+            }
+        } else {
+            status = BAD_VALUE;
+        }
+    }
+    return status;
+}
+
+String8 AudioStreamOutDump::getParameters(const String8& keys)
+{
+    if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
+
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
+status_t AudioStreamOutDump::dump(int fd, const Vector<String16>& args)
+{
+    if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
+    return NO_ERROR;
+}
+
+void AudioStreamOutDump::Close()
+{
+    if(mFile) {
+        fclose(mFile);
+        mFile = 0;
+    }
+}
+
+status_t AudioStreamOutDump::getRenderPosition(uint32_t *dspFrames)
+{
+    if (mFinalStream != 0 ) return mFinalStream->getRenderPosition(dspFrames);
+    return INVALID_OPERATION;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioStreamInDump::AudioStreamInDump(AudioDumpInterface *interface,
+                                        int id,
+                                        AudioStreamIn* finalStream,
+                                        uint32_t devices,
+                                        int format,
+                                        uint32_t channels,
+                                        uint32_t sampleRate)
+    : mInterface(interface), mId(id),
+      mSampleRate(sampleRate), mFormat(format), mChannels(channels), mDevice(devices),
+      mBufferSize(1024), mFinalStream(finalStream), mFile(0), mFileCount(0)
+{
+    LOGV("AudioStreamInDump Constructor %p, mInterface %p, mFinalStream %p", this, mInterface, mFinalStream);
+}
+
+
+AudioStreamInDump::~AudioStreamInDump()
+{
+    Close();
+}
+
+ssize_t AudioStreamInDump::read(void* buffer, ssize_t bytes)
+{
+    ssize_t ret;
+
+    if (mFinalStream) {
+        ret = mFinalStream->read(buffer, bytes);
+        if(!mFile) {
+            if (mInterface->fileName() != "") {
+                char name[255];
+                sprintf(name, "%s_in_%d_%d.pcm", mInterface->fileName().string(), mId, ++mFileCount);
+                mFile = fopen(name, "wb");
+                LOGV("Opening input dump file %s, fh %p", name, mFile);
+            }
+        }
+        if (mFile) {
+            fwrite(buffer, bytes, 1, mFile);
+        }
+    } else {
+        usleep((((bytes * 1000) / frameSize()) / sampleRate()) * 1000);
+        ret = bytes;
+        if(!mFile) {
+            char name[255];
+            strcpy(name, "/sdcard/music/sine440");
+            if (channels() == AudioSystem::CHANNEL_IN_MONO) {
+                strcat(name, "_mo");
+            } else {
+                strcat(name, "_st");
+            }
+            if (format() == AudioSystem::PCM_16_BIT) {
+                strcat(name, "_16b");
+            } else {
+                strcat(name, "_8b");
+            }
+            if (sampleRate() < 16000) {
+                strcat(name, "_8k");
+            } else if (sampleRate() < 32000) {
+                strcat(name, "_22k");
+            } else if (sampleRate() < 48000) {
+                strcat(name, "_44k");
+            } else {
+                strcat(name, "_48k");
+            }
+            strcat(name, ".wav");
+            mFile = fopen(name, "rb");
+            LOGV("Opening input read file %s, fh %p", name, mFile);
+            if (mFile) {
+                fseek(mFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
+            }
+        }
+        if (mFile) {
+            ssize_t bytesRead = fread(buffer, bytes, 1, mFile);
+            if (bytesRead >=0 && bytesRead < bytes) {
+                fseek(mFile, AUDIO_DUMP_WAVE_HDR_SIZE, SEEK_SET);
+                fread((uint8_t *)buffer+bytesRead, bytes-bytesRead, 1, mFile);
+            }
+        }
+    }
+
+    return ret;
+}
+
+status_t AudioStreamInDump::standby()
+{
+    LOGV("AudioStreamInDump standby(), mFile %p, mFinalStream %p", mFile, mFinalStream);
+
+    Close();
+    if (mFinalStream != 0 ) return mFinalStream->standby();
+    return NO_ERROR;
+}
+
+status_t AudioStreamInDump::setGain(float gain)
+{
+    if (mFinalStream != 0 ) return mFinalStream->setGain(gain);
+    return NO_ERROR;
+}
+
+uint32_t AudioStreamInDump::sampleRate() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->sampleRate();
+    return mSampleRate;
+}
+
+size_t AudioStreamInDump::bufferSize() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->bufferSize();
+    return mBufferSize;
+}
+
+uint32_t AudioStreamInDump::channels() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->channels();
+    return mChannels;
+}
+
+int AudioStreamInDump::format() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->format();
+    return mFormat;
+}
+
+status_t AudioStreamInDump::setParameters(const String8& keyValuePairs)
+{
+    LOGV("AudioStreamInDump::setParameters()");
+    if (mFinalStream != 0 ) return mFinalStream->setParameters(keyValuePairs);
+    return NO_ERROR;
+}
+
+String8 AudioStreamInDump::getParameters(const String8& keys)
+{
+    if (mFinalStream != 0 ) return mFinalStream->getParameters(keys);
+
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
+unsigned int AudioStreamInDump::getInputFramesLost() const
+{
+    if (mFinalStream != 0 ) return mFinalStream->getInputFramesLost();
+    return 0;
+}
+
+status_t AudioStreamInDump::dump(int fd, const Vector<String16>& args)
+{
+    if (mFinalStream != 0 ) return mFinalStream->dump(fd, args);
+    return NO_ERROR;
+}
+
+void AudioStreamInDump::Close()
+{
+    if(mFile) {
+        fclose(mFile);
+        mFile = 0;
+    }
+}
+}; // namespace android
diff --git a/services/audioflinger/AudioDumpInterface.h b/services/audioflinger/AudioDumpInterface.h
new file mode 100644
index 0000000..814ce5f
--- /dev/null
+++ b/services/audioflinger/AudioDumpInterface.h
@@ -0,0 +1,170 @@
+/* //device/servers/AudioFlinger/AudioDumpInterface.h
+**
+** Copyright 2008, 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 ANDROID_AUDIO_DUMP_INTERFACE_H
+#define ANDROID_AUDIO_DUMP_INTERFACE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/String8.h>
+#include <utils/SortedVector.h>
+
+#include <hardware_legacy/AudioHardwareBase.h>
+
+namespace android {
+
+#define AUDIO_DUMP_WAVE_HDR_SIZE 44
+
+class AudioDumpInterface;
+
+class AudioStreamOutDump : public AudioStreamOut {
+public:
+                        AudioStreamOutDump(AudioDumpInterface *interface,
+                                            int id,
+                                            AudioStreamOut* finalStream,
+                                            uint32_t devices,
+                                            int format,
+                                            uint32_t channels,
+                                            uint32_t sampleRate);
+                        ~AudioStreamOutDump();
+
+    virtual ssize_t     write(const void* buffer, size_t bytes);
+    virtual uint32_t    sampleRate() const;
+    virtual size_t      bufferSize() const;
+    virtual uint32_t    channels() const;
+    virtual int         format() const;
+    virtual uint32_t    latency() const;
+    virtual status_t    setVolume(float left, float right);
+    virtual status_t    standby();
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    void                Close(void);
+    AudioStreamOut*     finalStream() { return mFinalStream; }
+    uint32_t            device() { return mDevice; }
+    int                 getId()  { return mId; }
+    virtual status_t    getRenderPosition(uint32_t *dspFrames);
+
+private:
+    AudioDumpInterface *mInterface;
+    int                  mId;
+    uint32_t mSampleRate;               //
+    uint32_t mFormat;                   //
+    uint32_t mChannels;                 // output configuration
+    uint32_t mLatency;                  //
+    uint32_t mDevice;                   // current device this output is routed to
+    size_t  mBufferSize;
+    AudioStreamOut      *mFinalStream;
+    FILE                *mFile;      // output file
+    int                 mFileCount;
+};
+
+class AudioStreamInDump : public AudioStreamIn {
+public:
+                        AudioStreamInDump(AudioDumpInterface *interface,
+                                            int id,
+                                            AudioStreamIn* finalStream,
+                                            uint32_t devices,
+                                            int format,
+                                            uint32_t channels,
+                                            uint32_t sampleRate);
+                        ~AudioStreamInDump();
+
+    virtual uint32_t    sampleRate() const;
+    virtual size_t      bufferSize() const;
+    virtual uint32_t    channels() const;
+    virtual int         format() const;
+
+    virtual status_t    setGain(float gain);
+    virtual ssize_t     read(void* buffer, ssize_t bytes);
+    virtual status_t    standby();
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+    virtual unsigned int  getInputFramesLost() const;
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    void                Close(void);
+    AudioStreamIn*     finalStream() { return mFinalStream; }
+    uint32_t            device() { return mDevice; }
+
+private:
+    AudioDumpInterface *mInterface;
+    int                  mId;
+    uint32_t mSampleRate;               //
+    uint32_t mFormat;                   //
+    uint32_t mChannels;                 // output configuration
+    uint32_t mDevice;                   // current device this output is routed to
+    size_t  mBufferSize;
+    AudioStreamIn      *mFinalStream;
+    FILE                *mFile;      // output file
+    int                 mFileCount;
+};
+
+class AudioDumpInterface : public AudioHardwareBase
+{
+
+public:
+                        AudioDumpInterface(AudioHardwareInterface* hw);
+    virtual AudioStreamOut* openOutputStream(
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
+                                status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
+
+    virtual             ~AudioDumpInterface();
+
+    virtual status_t    initCheck()
+                            {return mFinalInterface->initCheck();}
+    virtual status_t    setVoiceVolume(float volume)
+                            {return mFinalInterface->setVoiceVolume(volume);}
+    virtual status_t    setMasterVolume(float volume)
+                            {return mFinalInterface->setMasterVolume(volume);}
+
+    virtual status_t    setMode(int mode);
+
+    // mic mute
+    virtual status_t    setMicMute(bool state)
+                            {return mFinalInterface->setMicMute(state);}
+    virtual status_t    getMicMute(bool* state)
+                            {return mFinalInterface->getMicMute(state);}
+
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+
+    virtual size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
+
+    virtual AudioStreamIn* openInputStream(uint32_t devices, int *format, uint32_t *channels,
+            uint32_t *sampleRate, status_t *status, AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
+
+    virtual status_t    dump(int fd, const Vector<String16>& args) { return mFinalInterface->dumpState(fd, args); }
+
+            String8     fileName() const { return mFileName; }
+protected:
+
+    AudioHardwareInterface          *mFinalInterface;
+    SortedVector<AudioStreamOutDump *>   mOutputs;
+    SortedVector<AudioStreamInDump *>    mInputs;
+    Mutex                           mLock;
+    String8                         mPolicyCommands;
+    String8                         mFileName;
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_DUMP_INTERFACE_H
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
new file mode 100644
index 0000000..252b42a
--- /dev/null
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -0,0 +1,6370 @@
+/* //device/include/server/AudioFlinger/AudioFlinger.cpp
+**
+** Copyright 2007, 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_TAG "AudioFlinger"
+//#define LOG_NDEBUG 0
+
+#include <math.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <binder/IPCThreadState.h>
+#include <utils/String16.h>
+#include <utils/threads.h>
+
+#include <cutils/properties.h>
+
+#include <media/AudioTrack.h>
+#include <media/AudioRecord.h>
+
+#include <private/media/AudioTrackShared.h>
+#include <private/media/AudioEffectShared.h>
+#include <hardware_legacy/AudioHardwareInterface.h>
+
+#include "AudioMixer.h"
+#include "AudioFlinger.h"
+
+#ifdef WITH_A2DP
+#include "A2dpAudioInterface.h"
+#endif
+
+#ifdef LVMX
+#include "lifevibes.h"
+#endif
+
+#include <media/EffectsFactoryApi.h>
+#include <media/EffectVisualizerApi.h>
+
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+// ----------------------------------------------------------------------------
+
+extern const char * const gEffectLibPath;
+
+namespace android {
+
+static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
+static const char* kHardwareLockedString = "Hardware lock is taken\n";
+
+//static const nsecs_t kStandbyTimeInNsecs = seconds(3);
+static const float MAX_GAIN = 4096.0f;
+static const float MAX_GAIN_INT = 0x1000;
+
+// retry counts for buffer fill timeout
+// 50 * ~20msecs = 1 second
+static const int8_t kMaxTrackRetries = 50;
+static const int8_t kMaxTrackStartupRetries = 50;
+// allow less retry attempts on direct output thread.
+// direct outputs can be a scarce resource in audio hardware and should
+// be released as quickly as possible.
+static const int8_t kMaxTrackRetriesDirect = 2;
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 20000;
+
+static const nsecs_t kWarningThrottle = seconds(5);
+
+
+#define AUDIOFLINGER_SECURITY_ENABLED 1
+
+// ----------------------------------------------------------------------------
+
+static bool recordingAllowed() {
+#ifndef HAVE_ANDROID_OS
+    return true;
+#endif
+#if AUDIOFLINGER_SECURITY_ENABLED
+    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+    bool ok = checkCallingPermission(String16("android.permission.RECORD_AUDIO"));
+    if (!ok) LOGE("Request requires android.permission.RECORD_AUDIO");
+    return ok;
+#else
+    if (!checkCallingPermission(String16("android.permission.RECORD_AUDIO")))
+        LOGW("WARNING: Need to add android.permission.RECORD_AUDIO to manifest");
+    return true;
+#endif
+}
+
+static bool settingsAllowed() {
+#ifndef HAVE_ANDROID_OS
+    return true;
+#endif
+#if AUDIOFLINGER_SECURITY_ENABLED
+    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+    bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
+    if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
+    return ok;
+#else
+    if (!checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS")))
+        LOGW("WARNING: Need to add android.permission.MODIFY_AUDIO_SETTINGS to manifest");
+    return true;
+#endif
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::AudioFlinger()
+    : BnAudioFlinger(),
+        mAudioHardware(0), mMasterVolume(1.0f), mMasterMute(false), mNextUniqueId(1)
+{
+    mHardwareStatus = AUDIO_HW_IDLE;
+
+    mAudioHardware = AudioHardwareInterface::create();
+
+    mHardwareStatus = AUDIO_HW_INIT;
+    if (mAudioHardware->initCheck() == NO_ERROR) {
+        // open 16-bit output stream for s/w mixer
+        mMode = AudioSystem::MODE_NORMAL;
+        setMode(mMode);
+
+        setMasterVolume(1.0f);
+        setMasterMute(false);
+    } else {
+        LOGE("Couldn't even initialize the stubbed audio hardware!");
+    }
+#ifdef LVMX
+    LifeVibes::init();
+    mLifeVibesClientPid = -1;
+#endif
+}
+
+AudioFlinger::~AudioFlinger()
+{
+    while (!mRecordThreads.isEmpty()) {
+        // closeInput() will remove first entry from mRecordThreads
+        closeInput(mRecordThreads.keyAt(0));
+    }
+    while (!mPlaybackThreads.isEmpty()) {
+        // closeOutput() will remove first entry from mPlaybackThreads
+        closeOutput(mPlaybackThreads.keyAt(0));
+    }
+    if (mAudioHardware) {
+        delete mAudioHardware;
+    }
+}
+
+
+
+status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    result.append("Clients:\n");
+    for (size_t i = 0; i < mClients.size(); ++i) {
+        wp<Client> wClient = mClients.valueAt(i);
+        if (wClient != 0) {
+            sp<Client> client = wClient.promote();
+            if (client != 0) {
+                snprintf(buffer, SIZE, "  pid: %d\n", client->pid());
+                result.append(buffer);
+            }
+        }
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+
+status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    int hardwareStatus = mHardwareStatus;
+
+    snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "Permission Denial: "
+            "can't dump AudioFlinger from pid=%d, uid=%d\n",
+            IPCThreadState::self()->getCallingPid(),
+            IPCThreadState::self()->getCallingUid());
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
+status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
+{
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        dumpPermissionDenial(fd, args);
+    } else {
+        // get state of hardware lock
+        bool hardwareLocked = tryLock(mHardwareLock);
+        if (!hardwareLocked) {
+            String8 result(kHardwareLockedString);
+            write(fd, result.string(), result.size());
+        } else {
+            mHardwareLock.unlock();
+        }
+
+        bool locked = tryLock(mLock);
+
+        // failed to lock - AudioFlinger is probably deadlocked
+        if (!locked) {
+            String8 result(kDeadlockedString);
+            write(fd, result.string(), result.size());
+        }
+
+        dumpClients(fd, args);
+        dumpInternals(fd, args);
+
+        // dump playback threads
+        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+            mPlaybackThreads.valueAt(i)->dump(fd, args);
+        }
+
+        // dump record threads
+        for (size_t i = 0; i < mRecordThreads.size(); i++) {
+            mRecordThreads.valueAt(i)->dump(fd, args);
+        }
+
+        if (mAudioHardware) {
+            mAudioHardware->dumpState(fd, args);
+        }
+        if (locked) mLock.unlock();
+    }
+    return NO_ERROR;
+}
+
+
+// IAudioFlinger interface
+
+
+sp<IAudioTrack> AudioFlinger::createTrack(
+        pid_t pid,
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        uint32_t flags,
+        const sp<IMemory>& sharedBuffer,
+        int output,
+        int *sessionId,
+        status_t *status)
+{
+    sp<PlaybackThread::Track> track;
+    sp<TrackHandle> trackHandle;
+    sp<Client> client;
+    wp<Client> wclient;
+    status_t lStatus;
+    int lSessionId;
+
+    if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
+        LOGE("invalid stream type");
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
+
+    {
+        Mutex::Autolock _l(mLock);
+        PlaybackThread *thread = checkPlaybackThread_l(output);
+        PlaybackThread *effectThread = NULL;
+        if (thread == NULL) {
+            LOGE("unknown output thread");
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+
+        wclient = mClients.valueFor(pid);
+
+        if (wclient != NULL) {
+            client = wclient.promote();
+        } else {
+            client = new Client(this, pid);
+            mClients.add(pid, client);
+        }
+
+        LOGV("createTrack() sessionId: %d", (sessionId == NULL) ? -2 : *sessionId);
+        if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
+            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+                sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+                if (mPlaybackThreads.keyAt(i) != output) {
+                    // prevent same audio session on different output threads
+                    uint32_t sessions = t->hasAudioSession(*sessionId);
+                    if (sessions & PlaybackThread::TRACK_SESSION) {
+                        lStatus = BAD_VALUE;
+                        goto Exit;
+                    }
+                    // check if an effect with same session ID is waiting for a track to be created
+                    if (sessions & PlaybackThread::EFFECT_SESSION) {
+                        effectThread = t.get();
+                    }
+                }
+            }
+            lSessionId = *sessionId;
+        } else {
+            // if no audio session id is provided, create one here
+            lSessionId = nextUniqueId();
+            if (sessionId != NULL) {
+                *sessionId = lSessionId;
+            }
+        }
+        LOGV("createTrack() lSessionId: %d", lSessionId);
+
+        track = thread->createTrack_l(client, streamType, sampleRate, format,
+                channelCount, frameCount, sharedBuffer, lSessionId, &lStatus);
+
+        // move effect chain to this output thread if an effect on same session was waiting
+        // for a track to be created
+        if (lStatus == NO_ERROR && effectThread != NULL) {
+            Mutex::Autolock _dl(thread->mLock);
+            Mutex::Autolock _sl(effectThread->mLock);
+            moveEffectChain_l(lSessionId, effectThread, thread, true);
+        }
+    }
+    if (lStatus == NO_ERROR) {
+        trackHandle = new TrackHandle(track);
+    } else {
+        // remove local strong reference to Client before deleting the Track so that the Client
+        // destructor is called by the TrackBase destructor with mLock held
+        client.clear();
+        track.clear();
+    }
+
+Exit:
+    if(status) {
+        *status = lStatus;
+    }
+    return trackHandle;
+}
+
+uint32_t AudioFlinger::sampleRate(int output) const
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("sampleRate() unknown thread %d", output);
+        return 0;
+    }
+    return thread->sampleRate();
+}
+
+int AudioFlinger::channelCount(int output) const
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("channelCount() unknown thread %d", output);
+        return 0;
+    }
+    return thread->channelCount();
+}
+
+int AudioFlinger::format(int output) const
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("format() unknown thread %d", output);
+        return 0;
+    }
+    return thread->format();
+}
+
+size_t AudioFlinger::frameCount(int output) const
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("frameCount() unknown thread %d", output);
+        return 0;
+    }
+    return thread->frameCount();
+}
+
+uint32_t AudioFlinger::latency(int output) const
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread == NULL) {
+        LOGW("latency() unknown thread %d", output);
+        return 0;
+    }
+    return thread->latency();
+}
+
+status_t AudioFlinger::setMasterVolume(float value)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    // when hw supports master volume, don't scale in sw mixer
+    AutoMutex lock(mHardwareLock);
+    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+    if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
+        value = 1.0f;
+    }
+    mHardwareStatus = AUDIO_HW_IDLE;
+
+    mMasterVolume = value;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads.valueAt(i)->setMasterVolume(value);
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::setMode(int mode)
+{
+    status_t ret;
+
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    if ((mode < 0) || (mode >= AudioSystem::NUM_MODES)) {
+        LOGW("Illegal value: setMode(%d)", mode);
+        return BAD_VALUE;
+    }
+
+    { // scope for the lock
+        AutoMutex lock(mHardwareLock);
+        mHardwareStatus = AUDIO_HW_SET_MODE;
+        ret = mAudioHardware->setMode(mode);
+        mHardwareStatus = AUDIO_HW_IDLE;
+    }
+
+    if (NO_ERROR == ret) {
+        Mutex::Autolock _l(mLock);
+        mMode = mode;
+        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+           mPlaybackThreads.valueAt(i)->setMode(mode);
+#ifdef LVMX
+        LifeVibes::setMode(mode);
+#endif
+    }
+
+    return ret;
+}
+
+status_t AudioFlinger::setMicMute(bool state)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    AutoMutex lock(mHardwareLock);
+    mHardwareStatus = AUDIO_HW_SET_MIC_MUTE;
+    status_t ret = mAudioHardware->setMicMute(state);
+    mHardwareStatus = AUDIO_HW_IDLE;
+    return ret;
+}
+
+bool AudioFlinger::getMicMute() const
+{
+    bool state = AudioSystem::MODE_INVALID;
+    mHardwareStatus = AUDIO_HW_GET_MIC_MUTE;
+    mAudioHardware->getMicMute(&state);
+    mHardwareStatus = AUDIO_HW_IDLE;
+    return state;
+}
+
+status_t AudioFlinger::setMasterMute(bool muted)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    mMasterMute = muted;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads.valueAt(i)->setMasterMute(muted);
+
+    return NO_ERROR;
+}
+
+float AudioFlinger::masterVolume() const
+{
+    return mMasterVolume;
+}
+
+bool AudioFlinger::masterMute() const
+{
+    return mMasterMute;
+}
+
+status_t AudioFlinger::setStreamVolume(int stream, float value, int output)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+
+    AutoMutex lock(mLock);
+    PlaybackThread *thread = NULL;
+    if (output) {
+        thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return BAD_VALUE;
+        }
+    }
+
+    mStreamTypes[stream].volume = value;
+
+    if (thread == NULL) {
+        for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
+           mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value);
+        }
+    } else {
+        thread->setStreamVolume(stream, value);
+    }
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::setStreamMute(int stream, bool muted)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES ||
+        uint32_t(stream) == AudioSystem::ENFORCED_AUDIBLE) {
+        return BAD_VALUE;
+    }
+
+    mStreamTypes[stream].mute = muted;
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++)
+       mPlaybackThreads.valueAt(i)->setStreamMute(stream, muted);
+
+    return NO_ERROR;
+}
+
+float AudioFlinger::streamVolume(int stream, int output) const
+{
+    if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
+        return 0.0f;
+    }
+
+    AutoMutex lock(mLock);
+    float volume;
+    if (output) {
+        PlaybackThread *thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return 0.0f;
+        }
+        volume = thread->streamVolume(stream);
+    } else {
+        volume = mStreamTypes[stream].volume;
+    }
+
+    return volume;
+}
+
+bool AudioFlinger::streamMute(int stream) const
+{
+    if (stream < 0 || stream >= (int)AudioSystem::NUM_STREAM_TYPES) {
+        return true;
+    }
+
+    return mStreamTypes[stream].mute;
+}
+
+bool AudioFlinger::isStreamActive(int stream) const
+{
+    Mutex::Autolock _l(mLock);
+    for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) {
+        if (mPlaybackThreads.valueAt(i)->isStreamActive(stream)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+status_t AudioFlinger::setParameters(int ioHandle, const String8& keyValuePairs)
+{
+    status_t result;
+
+    LOGV("setParameters(): io %d, keyvalue %s, tid %d, calling tid %d",
+            ioHandle, keyValuePairs.string(), gettid(), IPCThreadState::self()->getCallingPid());
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+#ifdef LVMX
+    AudioParameter param = AudioParameter(keyValuePairs);
+    LifeVibes::setParameters(ioHandle,keyValuePairs);
+    String8 key = String8(AudioParameter::keyRouting);
+    int device;
+    if (NO_ERROR != param.getInt(key, device)) {
+        device = -1;
+    }
+
+    key = String8(LifevibesTag);
+    String8 value;
+    int musicEnabled = -1;
+    if (NO_ERROR == param.get(key, value)) {
+        if (value == LifevibesEnable) {
+            mLifeVibesClientPid = IPCThreadState::self()->getCallingPid();
+            musicEnabled = 1;
+        } else if (value == LifevibesDisable) {
+            mLifeVibesClientPid = -1;
+            musicEnabled = 0;
+        }
+    }
+#endif
+
+    // ioHandle == 0 means the parameters are global to the audio hardware interface
+    if (ioHandle == 0) {
+        AutoMutex lock(mHardwareLock);
+        mHardwareStatus = AUDIO_SET_PARAMETER;
+        result = mAudioHardware->setParameters(keyValuePairs);
+#ifdef LVMX
+        if (musicEnabled != -1) {
+            LifeVibes::enableMusic((bool) musicEnabled);
+        }
+#endif
+        mHardwareStatus = AUDIO_HW_IDLE;
+        return result;
+    }
+
+    // hold a strong ref on thread in case closeOutput() or closeInput() is called
+    // and the thread is exited once the lock is released
+    sp<ThreadBase> thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkPlaybackThread_l(ioHandle);
+        if (thread == NULL) {
+            thread = checkRecordThread_l(ioHandle);
+        }
+    }
+    if (thread != NULL) {
+        result = thread->setParameters(keyValuePairs);
+#ifdef LVMX
+        if ((NO_ERROR == result) && (device != -1)) {
+            LifeVibes::setDevice(LifeVibes::threadIdToAudioOutputType(thread->id()), device);
+        }
+#endif
+        return result;
+    }
+    return BAD_VALUE;
+}
+
+String8 AudioFlinger::getParameters(int ioHandle, const String8& keys)
+{
+//    LOGV("getParameters() io %d, keys %s, tid %d, calling tid %d",
+//            ioHandle, keys.string(), gettid(), IPCThreadState::self()->getCallingPid());
+
+    if (ioHandle == 0) {
+        return mAudioHardware->getParameters(keys);
+    }
+
+    Mutex::Autolock _l(mLock);
+
+    PlaybackThread *playbackThread = checkPlaybackThread_l(ioHandle);
+    if (playbackThread != NULL) {
+        return playbackThread->getParameters(keys);
+    }
+    RecordThread *recordThread = checkRecordThread_l(ioHandle);
+    if (recordThread != NULL) {
+        return recordThread->getParameters(keys);
+    }
+    return String8("");
+}
+
+size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+    return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
+}
+
+unsigned int AudioFlinger::getInputFramesLost(int ioHandle)
+{
+    if (ioHandle == 0) {
+        return 0;
+    }
+
+    Mutex::Autolock _l(mLock);
+
+    RecordThread *recordThread = checkRecordThread_l(ioHandle);
+    if (recordThread != NULL) {
+        return recordThread->getInputFramesLost();
+    }
+    return 0;
+}
+
+status_t AudioFlinger::setVoiceVolume(float value)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    AutoMutex lock(mHardwareLock);
+    mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
+    status_t ret = mAudioHardware->setVoiceVolume(value);
+    mHardwareStatus = AUDIO_HW_IDLE;
+
+    return ret;
+}
+
+status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output)
+{
+    status_t status;
+
+    Mutex::Autolock _l(mLock);
+
+    PlaybackThread *playbackThread = checkPlaybackThread_l(output);
+    if (playbackThread != NULL) {
+        return playbackThread->getRenderPosition(halFrames, dspFrames);
+    }
+
+    return BAD_VALUE;
+}
+
+void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
+{
+
+    Mutex::Autolock _l(mLock);
+
+    int pid = IPCThreadState::self()->getCallingPid();
+    if (mNotificationClients.indexOfKey(pid) < 0) {
+        sp<NotificationClient> notificationClient = new NotificationClient(this,
+                                                                            client,
+                                                                            pid);
+        LOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);
+
+        mNotificationClients.add(pid, notificationClient);
+
+        sp<IBinder> binder = client->asBinder();
+        binder->linkToDeath(notificationClient);
+
+        // the config change is always sent from playback or record threads to avoid deadlock
+        // with AudioSystem::gLock
+        for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+            mPlaybackThreads.valueAt(i)->sendConfigEvent(AudioSystem::OUTPUT_OPENED);
+        }
+
+        for (size_t i = 0; i < mRecordThreads.size(); i++) {
+            mRecordThreads.valueAt(i)->sendConfigEvent(AudioSystem::INPUT_OPENED);
+        }
+    }
+}
+
+void AudioFlinger::removeNotificationClient(pid_t pid)
+{
+    Mutex::Autolock _l(mLock);
+
+    int index = mNotificationClients.indexOfKey(pid);
+    if (index >= 0) {
+        sp <NotificationClient> client = mNotificationClients.valueFor(pid);
+        LOGV("removeNotificationClient() %p, pid %d", client.get(), pid);
+#ifdef LVMX
+        if (pid == mLifeVibesClientPid) {
+            LOGV("Disabling lifevibes");
+            LifeVibes::enableMusic(false);
+            mLifeVibesClientPid = -1;
+        }
+#endif
+        mNotificationClients.removeItem(pid);
+    }
+}
+
+// audioConfigChanged_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2)
+{
+    size_t size = mNotificationClients.size();
+    for (size_t i = 0; i < size; i++) {
+        mNotificationClients.valueAt(i)->client()->ioConfigChanged(event, ioHandle, param2);
+    }
+}
+
+// removeClient_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::removeClient_l(pid_t pid)
+{
+    LOGV("removeClient_l() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
+    mClients.removeItem(pid);
+}
+
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
+    :   Thread(false),
+        mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
+        mFrameSize(1), mFormat(0), mStandby(false), mId(id), mExiting(false)
+{
+}
+
+AudioFlinger::ThreadBase::~ThreadBase()
+{
+    mParamCond.broadcast();
+    mNewParameters.clear();
+}
+
+void AudioFlinger::ThreadBase::exit()
+{
+    // keep a strong ref on ourself so that we wont get
+    // destroyed in the middle of requestExitAndWait()
+    sp <ThreadBase> strongMe = this;
+
+    LOGV("ThreadBase::exit");
+    {
+        AutoMutex lock(&mLock);
+        mExiting = true;
+        requestExit();
+        mWaitWorkCV.signal();
+    }
+    requestExitAndWait();
+}
+
+uint32_t AudioFlinger::ThreadBase::sampleRate() const
+{
+    return mSampleRate;
+}
+
+int AudioFlinger::ThreadBase::channelCount() const
+{
+    return (int)mChannelCount;
+}
+
+int AudioFlinger::ThreadBase::format() const
+{
+    return mFormat;
+}
+
+size_t AudioFlinger::ThreadBase::frameCount() const
+{
+    return mFrameCount;
+}
+
+status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
+{
+    status_t status;
+
+    LOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
+    Mutex::Autolock _l(mLock);
+
+    mNewParameters.add(keyValuePairs);
+    mWaitWorkCV.signal();
+    // wait condition with timeout in case the thread loop has exited
+    // before the request could be processed
+    if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
+        status = mParamStatus;
+        mWaitWorkCV.signal();
+    } else {
+        status = TIMED_OUT;
+    }
+    return status;
+}
+
+void AudioFlinger::ThreadBase::sendConfigEvent(int event, int param)
+{
+    Mutex::Autolock _l(mLock);
+    sendConfigEvent_l(event, param);
+}
+
+// sendConfigEvent_l() must be called with ThreadBase::mLock held
+void AudioFlinger::ThreadBase::sendConfigEvent_l(int event, int param)
+{
+    ConfigEvent *configEvent = new ConfigEvent();
+    configEvent->mEvent = event;
+    configEvent->mParam = param;
+    mConfigEvents.add(configEvent);
+    LOGV("sendConfigEvent() num events %d event %d, param %d", mConfigEvents.size(), event, param);
+    mWaitWorkCV.signal();
+}
+
+void AudioFlinger::ThreadBase::processConfigEvents()
+{
+    mLock.lock();
+    while(!mConfigEvents.isEmpty()) {
+        LOGV("processConfigEvents() remaining events %d", mConfigEvents.size());
+        ConfigEvent *configEvent = mConfigEvents[0];
+        mConfigEvents.removeAt(0);
+        // release mLock before locking AudioFlinger mLock: lock order is always
+        // AudioFlinger then ThreadBase to avoid cross deadlock
+        mLock.unlock();
+        mAudioFlinger->mLock.lock();
+        audioConfigChanged_l(configEvent->mEvent, configEvent->mParam);
+        mAudioFlinger->mLock.unlock();
+        delete configEvent;
+        mLock.lock();
+    }
+    mLock.unlock();
+}
+
+status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    bool locked = tryLock(mLock);
+    if (!locked) {
+        snprintf(buffer, SIZE, "thread %p maybe dead locked\n", this);
+        write(fd, buffer, strlen(buffer));
+    }
+
+    snprintf(buffer, SIZE, "standby: %d\n", mStandby);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Sample rate: %d\n", mSampleRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Frame count: %d\n", mFrameCount);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Channel Count: %d\n", mChannelCount);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Frame size: %d\n", mFrameSize);
+    result.append(buffer);
+
+    snprintf(buffer, SIZE, "\nPending setParameters commands: \n");
+    result.append(buffer);
+    result.append(" Index Command");
+    for (size_t i = 0; i < mNewParameters.size(); ++i) {
+        snprintf(buffer, SIZE, "\n %02d    ", i);
+        result.append(buffer);
+        result.append(mNewParameters[i]);
+    }
+
+    snprintf(buffer, SIZE, "\n\nPending config events: \n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Index event param\n");
+    result.append(buffer);
+    for (size_t i = 0; i < mConfigEvents.size(); i++) {
+        snprintf(buffer, SIZE, " %02d    %02d    %d\n", i, mConfigEvents[i]->mEvent, mConfigEvents[i]->mParam);
+        result.append(buffer);
+    }
+    result.append("\n");
+
+    write(fd, result.string(), result.size());
+
+    if (locked) {
+        mLock.unlock();
+    }
+    return NO_ERROR;
+}
+
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
+    :   ThreadBase(audioFlinger, id),
+        mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
+        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
+        mDevice(device)
+{
+    readOutputParameters();
+
+    mMasterVolume = mAudioFlinger->masterVolume();
+    mMasterMute = mAudioFlinger->masterMute();
+
+    for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+        mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream);
+        mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream);
+    }
+}
+
+AudioFlinger::PlaybackThread::~PlaybackThread()
+{
+    delete [] mMixBuffer;
+}
+
+status_t AudioFlinger::PlaybackThread::dump(int fd, const Vector<String16>& args)
+{
+    dumpInternals(fd, args);
+    dumpTracks(fd, args);
+    dumpEffectChains(fd, args);
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::dumpTracks(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "Output thread %p tracks\n", this);
+    result.append(buffer);
+    result.append("   Name  Clien Typ Fmt Chn Session Buf  S M F SRate LeftV RighV  Serv       User       Main buf   Aux Buf\n");
+    for (size_t i = 0; i < mTracks.size(); ++i) {
+        sp<Track> track = mTracks[i];
+        if (track != 0) {
+            track->dump(buffer, SIZE);
+            result.append(buffer);
+        }
+    }
+
+    snprintf(buffer, SIZE, "Output thread %p active tracks\n", this);
+    result.append(buffer);
+    result.append("   Name  Clien Typ Fmt Chn Session Buf  S M F SRate LeftV RighV  Serv       User       Main buf   Aux Buf\n");
+    for (size_t i = 0; i < mActiveTracks.size(); ++i) {
+        wp<Track> wTrack = mActiveTracks[i];
+        if (wTrack != 0) {
+            sp<Track> track = wTrack.promote();
+            if (track != 0) {
+                track->dump(buffer, SIZE);
+                result.append(buffer);
+            }
+        }
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::dumpEffectChains(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "\n- %d Effect Chains:\n", mEffectChains.size());
+    write(fd, buffer, strlen(buffer));
+
+    for (size_t i = 0; i < mEffectChains.size(); ++i) {
+        sp<EffectChain> chain = mEffectChains[i];
+        if (chain != 0) {
+            chain->dump(fd, args);
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "\nOutput thread %p internals\n", this);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
+    result.append(buffer);
+    snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "suspend count: %d\n", mSuspended);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    dumpBase(fd, args);
+
+    return NO_ERROR;
+}
+
+// Thread virtuals
+status_t AudioFlinger::PlaybackThread::readyToRun()
+{
+    if (mSampleRate == 0) {
+        LOGE("No working audio driver found.");
+        return NO_INIT;
+    }
+    LOGI("AudioFlinger's thread %p ready to run", this);
+    return NO_ERROR;
+}
+
+void AudioFlinger::PlaybackThread::onFirstRef()
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "Playback Thread %p", this);
+
+    run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
+}
+
+// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::PlaybackThread::Track>  AudioFlinger::PlaybackThread::createTrack_l(
+        const sp<AudioFlinger::Client>& client,
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        const sp<IMemory>& sharedBuffer,
+        int sessionId,
+        status_t *status)
+{
+    sp<Track> track;
+    status_t lStatus;
+
+    if (mType == DIRECT) {
+        if (sampleRate != mSampleRate || format != mFormat || channelCount != (int)mChannelCount) {
+            LOGE("createTrack_l() Bad parameter:  sampleRate %d format %d, channelCount %d for output %p",
+                 sampleRate, format, channelCount, mOutput);
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+    } else {
+        // Resampler implementation limits input sampling rate to 2 x output sampling rate.
+        if (sampleRate > mSampleRate*2) {
+            LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+    }
+
+    if (mOutput == 0) {
+        LOGE("Audio driver not initialized.");
+        lStatus = NO_INIT;
+        goto Exit;
+    }
+
+    { // scope for mLock
+        Mutex::Autolock _l(mLock);
+
+        // all tracks in same audio session must share the same routing strategy otherwise
+        // conflicts will happen when tracks are moved from one output to another by audio policy
+        // manager
+        uint32_t strategy =
+                AudioSystem::getStrategyForStream((AudioSystem::stream_type)streamType);
+        for (size_t i = 0; i < mTracks.size(); ++i) {
+            sp<Track> t = mTracks[i];
+            if (t != 0) {
+                if (sessionId == t->sessionId() &&
+                        strategy != AudioSystem::getStrategyForStream((AudioSystem::stream_type)t->type())) {
+                    lStatus = BAD_VALUE;
+                    goto Exit;
+                }
+            }
+        }
+
+        track = new Track(this, client, streamType, sampleRate, format,
+                channelCount, frameCount, sharedBuffer, sessionId);
+        if (track->getCblk() == NULL || track->name() < 0) {
+            lStatus = NO_MEMORY;
+            goto Exit;
+        }
+        mTracks.add(track);
+
+        sp<EffectChain> chain = getEffectChain_l(sessionId);
+        if (chain != 0) {
+            LOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
+            track->setMainBuffer(chain->inBuffer());
+            chain->setStrategy(AudioSystem::getStrategyForStream((AudioSystem::stream_type)track->type()));
+        }
+    }
+    lStatus = NO_ERROR;
+
+Exit:
+    if(status) {
+        *status = lStatus;
+    }
+    return track;
+}
+
+uint32_t AudioFlinger::PlaybackThread::latency() const
+{
+    if (mOutput) {
+        return mOutput->latency();
+    }
+    else {
+        return 0;
+    }
+}
+
+status_t AudioFlinger::PlaybackThread::setMasterVolume(float value)
+{
+#ifdef LVMX
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+        LifeVibes::setMasterVolume(audioOutputType, value);
+    }
+#endif
+    mMasterVolume = value;
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::setMasterMute(bool muted)
+{
+#ifdef LVMX
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+        LifeVibes::setMasterMute(audioOutputType, muted);
+    }
+#endif
+    mMasterMute = muted;
+    return NO_ERROR;
+}
+
+float AudioFlinger::PlaybackThread::masterVolume() const
+{
+    return mMasterVolume;
+}
+
+bool AudioFlinger::PlaybackThread::masterMute() const
+{
+    return mMasterMute;
+}
+
+status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value)
+{
+#ifdef LVMX
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+        LifeVibes::setStreamVolume(audioOutputType, stream, value);
+    }
+#endif
+    mStreamTypes[stream].volume = value;
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::PlaybackThread::setStreamMute(int stream, bool muted)
+{
+#ifdef LVMX
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+        LifeVibes::setStreamMute(audioOutputType, stream, muted);
+    }
+#endif
+    mStreamTypes[stream].mute = muted;
+    return NO_ERROR;
+}
+
+float AudioFlinger::PlaybackThread::streamVolume(int stream) const
+{
+    return mStreamTypes[stream].volume;
+}
+
+bool AudioFlinger::PlaybackThread::streamMute(int stream) const
+{
+    return mStreamTypes[stream].mute;
+}
+
+bool AudioFlinger::PlaybackThread::isStreamActive(int stream) const
+{
+    Mutex::Autolock _l(mLock);
+    size_t count = mActiveTracks.size();
+    for (size_t i = 0 ; i < count ; ++i) {
+        sp<Track> t = mActiveTracks[i].promote();
+        if (t == 0) continue;
+        Track* const track = t.get();
+        if (t->type() == stream)
+            return true;
+    }
+    return false;
+}
+
+// addTrack_l() must be called with ThreadBase::mLock held
+status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
+{
+    status_t status = ALREADY_EXISTS;
+
+    // set retry count for buffer fill
+    track->mRetryCount = kMaxTrackStartupRetries;
+    if (mActiveTracks.indexOf(track) < 0) {
+        // the track is newly added, make sure it fills up all its
+        // buffers before playing. This is to ensure the client will
+        // effectively get the latency it requested.
+        track->mFillingUpStatus = Track::FS_FILLING;
+        track->mResetDone = false;
+        mActiveTracks.add(track);
+        if (track->mainBuffer() != mMixBuffer) {
+            sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+            if (chain != 0) {
+                LOGV("addTrack_l() starting track on chain %p for session %d", chain.get(), track->sessionId());
+                chain->startTrack();
+            }
+        }
+
+        status = NO_ERROR;
+    }
+
+    LOGV("mWaitWorkCV.broadcast");
+    mWaitWorkCV.broadcast();
+
+    return status;
+}
+
+// destroyTrack_l() must be called with ThreadBase::mLock held
+void AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
+{
+    track->mState = TrackBase::TERMINATED;
+    if (mActiveTracks.indexOf(track) < 0) {
+        mTracks.remove(track);
+        deleteTrackName_l(track->name());
+    }
+}
+
+String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
+{
+    return mOutput->getParameters(keys);
+}
+
+// destroyTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) {
+    AudioSystem::OutputDescriptor desc;
+    void *param2 = 0;
+
+    LOGV("PlaybackThread::audioConfigChanged_l, thread %p, event %d, param %d", this, event, param);
+
+    switch (event) {
+    case AudioSystem::OUTPUT_OPENED:
+    case AudioSystem::OUTPUT_CONFIG_CHANGED:
+        desc.channels = mChannels;
+        desc.samplingRate = mSampleRate;
+        desc.format = mFormat;
+        desc.frameCount = mFrameCount;
+        desc.latency = latency();
+        param2 = &desc;
+        break;
+
+    case AudioSystem::STREAM_CONFIG_CHANGED:
+        param2 = &param;
+    case AudioSystem::OUTPUT_CLOSED:
+    default:
+        break;
+    }
+    mAudioFlinger->audioConfigChanged_l(event, mId, param2);
+}
+
+void AudioFlinger::PlaybackThread::readOutputParameters()
+{
+    mSampleRate = mOutput->sampleRate();
+    mChannels = mOutput->channels();
+    mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
+    mFormat = mOutput->format();
+    mFrameSize = (uint16_t)mOutput->frameSize();
+    mFrameCount = mOutput->bufferSize() / mFrameSize;
+
+    // FIXME - Current mixer implementation only supports stereo output: Always
+    // Allocate a stereo buffer even if HW output is mono.
+    if (mMixBuffer != NULL) delete[] mMixBuffer;
+    mMixBuffer = new int16_t[mFrameCount * 2];
+    memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
+
+    // force reconfiguration of effect chains and engines to take new buffer size and audio
+    // parameters into account
+    // Note that mLock is not held when readOutputParameters() is called from the constructor
+    // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
+    // matter.
+    // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
+    Vector< sp<EffectChain> > effectChains = mEffectChains;
+    for (size_t i = 0; i < effectChains.size(); i ++) {
+        mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
+    }
+}
+
+status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
+{
+    if (halFrames == 0 || dspFrames == 0) {
+        return BAD_VALUE;
+    }
+    if (mOutput == 0) {
+        return INVALID_OPERATION;
+    }
+    *halFrames = mBytesWritten/mOutput->frameSize();
+
+    return mOutput->getRenderPosition(dspFrames);
+}
+
+uint32_t AudioFlinger::PlaybackThread::hasAudioSession(int sessionId)
+{
+    Mutex::Autolock _l(mLock);
+    uint32_t result = 0;
+    if (getEffectChain_l(sessionId) != 0) {
+        result = EFFECT_SESSION;
+    }
+
+    for (size_t i = 0; i < mTracks.size(); ++i) {
+        sp<Track> track = mTracks[i];
+        if (sessionId == track->sessionId() &&
+                !(track->mCblk->flags & CBLK_INVALID_MSK)) {
+            result |= TRACK_SESSION;
+            break;
+        }
+    }
+
+    return result;
+}
+
+uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId)
+{
+    // session AudioSystem::SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
+    // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
+    if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {
+        return AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
+    }
+    for (size_t i = 0; i < mTracks.size(); i++) {
+        sp<Track> track = mTracks[i];
+        if (sessionId == track->sessionId() &&
+                !(track->mCblk->flags & CBLK_INVALID_MSK)) {
+            return AudioSystem::getStrategyForStream((AudioSystem::stream_type) track->type());
+        }
+    }
+    return AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
+}
+
+sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain(int sessionId)
+{
+    Mutex::Autolock _l(mLock);
+    return getEffectChain_l(sessionId);
+}
+
+sp<AudioFlinger::EffectChain> AudioFlinger::PlaybackThread::getEffectChain_l(int sessionId)
+{
+    sp<EffectChain> chain;
+
+    size_t size = mEffectChains.size();
+    for (size_t i = 0; i < size; i++) {
+        if (mEffectChains[i]->sessionId() == sessionId) {
+            chain = mEffectChains[i];
+            break;
+        }
+    }
+    return chain;
+}
+
+void AudioFlinger::PlaybackThread::setMode(uint32_t mode)
+{
+    Mutex::Autolock _l(mLock);
+    size_t size = mEffectChains.size();
+    for (size_t i = 0; i < size; i++) {
+        mEffectChains[i]->setMode_l(mode);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
+    :   PlaybackThread(audioFlinger, output, id, device),
+        mAudioMixer(0)
+{
+    mType = PlaybackThread::MIXER;
+    mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
+
+    // FIXME - Current mixer implementation only supports stereo output
+    if (mChannelCount == 1) {
+        LOGE("Invalid audio hardware channel count");
+    }
+}
+
+AudioFlinger::MixerThread::~MixerThread()
+{
+    delete mAudioMixer;
+}
+
+bool AudioFlinger::MixerThread::threadLoop()
+{
+    Vector< sp<Track> > tracksToRemove;
+    uint32_t mixerStatus = MIXER_IDLE;
+    nsecs_t standbyTime = systemTime();
+    size_t mixBufferSize = mFrameCount * mFrameSize;
+    // FIXME: Relaxed timing because of a certain device that can't meet latency
+    // Should be reduced to 2x after the vendor fixes the driver issue
+    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
+    nsecs_t lastWarning = 0;
+    bool longStandbyExit = false;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
+    Vector< sp<EffectChain> > effectChains;
+
+    while (!exitPending())
+    {
+        processConfigEvents();
+
+        mixerStatus = MIXER_IDLE;
+        { // scope for mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount * mFrameSize;
+                // FIXME: Relaxed timing because of a certain device that can't meet latency
+                // Should be reduced to 2x after the vendor fixes the driver issue
+                maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
+            }
+
+            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
+                        mSuspended) {
+                if (!mStandby) {
+                    LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
+                    mOutput->standby();
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+
+                    if (exitPending()) break;
+
+                    // wait until we have something to do...
+                    LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("MixerThread %p TID %d waking up\n", this, gettid());
+
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = idleSleepTime;
+                    continue;
+                }
+            }
+
+            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
+
+            // prevent any changes in effect chain list and in each effect chain
+            // during mixing and effect process as the audio buffers could be deleted
+            // or modified if an effect is created or deleted
+            lockEffectChains_l(effectChains);
+       }
+
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
+            // mix buffers...
+            mAudioMixer->process();
+            sleepTime = 0;
+            standbyTime = systemTime() + kStandbyTimeInNsecs;
+            //TODO: delay standby when effects have a tail
+        } else {
+            // If no tracks are ready, sleep once for the duration of an output
+            // buffer size, then write 0s to the output
+            if (sleepTime == 0) {
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
+            } else if (mBytesWritten != 0 ||
+                       (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
+                memset (mMixBuffer, 0, mixBufferSize);
+                sleepTime = 0;
+                LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
+            }
+            // TODO add standby time extension fct of effect tail
+        }
+
+        if (mSuspended) {
+            sleepTime = idleSleepTime;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+             for (size_t i = 0; i < effectChains.size(); i ++) {
+                 effectChains[i]->process_l();
+             }
+             // enable changes in effect chain
+             unlockEffectChains(effectChains);
+#ifdef LVMX
+            int audioOutputType = LifeVibes::getMixerType(mId, mType);
+            if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) {
+               LifeVibes::process(audioOutputType, mMixBuffer, mixBufferSize);
+            }
+#endif
+            mLastWriteTime = systemTime();
+            mInWrite = true;
+            mBytesWritten += mixBufferSize;
+
+            int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
+            if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
+            mNumWrites++;
+            mInWrite = false;
+            nsecs_t now = systemTime();
+            nsecs_t delta = now - mLastWriteTime;
+            if (delta > maxPeriod) {
+                mNumDelayedWrites++;
+                if ((now - lastWarning) > kWarningThrottle) {
+                    LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
+                            ns2ms(delta), mNumDelayedWrites, this);
+                    lastWarning = now;
+                }
+                if (mStandby) {
+                    longStandbyExit = true;
+                }
+            }
+            mStandby = false;
+        } else {
+            // enable changes in effect chain
+            unlockEffectChains(effectChains);
+            usleep(sleepTime);
+        }
+
+        // finally let go of all our tracks, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        tracksToRemove.clear();
+
+        // Effect chains will be actually deleted here if they were removed from
+        // mEffectChains list during mixing or effects processing
+        effectChains.clear();
+    }
+
+    if (!mStandby) {
+        mOutput->standby();
+    }
+
+    LOGV("MixerThread %p exiting", this);
+    return false;
+}
+
+// prepareTracks_l() must be called with ThreadBase::mLock held
+uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
+{
+
+    uint32_t mixerStatus = MIXER_IDLE;
+    // find out which tracks need to be processed
+    size_t count = activeTracks.size();
+    size_t mixedTracks = 0;
+    size_t tracksWithEffect = 0;
+
+    float masterVolume = mMasterVolume;
+    bool  masterMute = mMasterMute;
+
+#ifdef LVMX
+    bool tracksConnectedChanged = false;
+    bool stateChanged = false;
+
+    int audioOutputType = LifeVibes::getMixerType(mId, mType);
+    if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
+    {
+        int activeTypes = 0;
+        for (size_t i=0 ; i<count ; i++) {
+            sp<Track> t = activeTracks[i].promote();
+            if (t == 0) continue;
+            Track* const track = t.get();
+            int iTracktype=track->type();
+            activeTypes |= 1<<track->type();
+        }
+        LifeVibes::computeVolumes(audioOutputType, activeTypes, tracksConnectedChanged, stateChanged, masterVolume, masterMute);
+    }
+#endif
+    // Delegate master volume control to effect in output mix effect chain if needed
+    sp<EffectChain> chain = getEffectChain_l(AudioSystem::SESSION_OUTPUT_MIX);
+    if (chain != 0) {
+        uint32_t v = (uint32_t)(masterVolume * (1 << 24));
+        chain->setVolume_l(&v, &v);
+        masterVolume = (float)((v + (1 << 23)) >> 24);
+        chain.clear();
+    }
+
+    for (size_t i=0 ; i<count ; i++) {
+        sp<Track> t = activeTracks[i].promote();
+        if (t == 0) continue;
+
+        Track* const track = t.get();
+        audio_track_cblk_t* cblk = track->cblk();
+
+        // The first time a track is added we wait
+        // for all its buffers to be filled before processing it
+        mAudioMixer->setActiveTrack(track->name());
+        if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
+                !track->isPaused() && !track->isTerminated())
+        {
+            //LOGV("track %d u=%08x, s=%08x [OK] on thread %p", track->name(), cblk->user, cblk->server, this);
+
+            mixedTracks++;
+
+            // track->mainBuffer() != mMixBuffer means there is an effect chain
+            // connected to the track
+            chain.clear();
+            if (track->mainBuffer() != mMixBuffer) {
+                chain = getEffectChain_l(track->sessionId());
+                // Delegate volume control to effect in track effect chain if needed
+                if (chain != 0) {
+                    tracksWithEffect++;
+                } else {
+                    LOGW("prepareTracks_l(): track %08x attached to effect but no chain found on session %d",
+                            track->name(), track->sessionId());
+                }
+            }
+
+
+            int param = AudioMixer::VOLUME;
+            if (track->mFillingUpStatus == Track::FS_FILLED) {
+                // no ramp for the first volume setting
+                track->mFillingUpStatus = Track::FS_ACTIVE;
+                if (track->mState == TrackBase::RESUMING) {
+                    track->mState = TrackBase::ACTIVE;
+                    param = AudioMixer::RAMP_VOLUME;
+                }
+            } else if (cblk->server != 0) {
+                // If the track is stopped before the first frame was mixed,
+                // do not apply ramp
+                param = AudioMixer::RAMP_VOLUME;
+            }
+
+            // compute volume for this track
+            int16_t left, right, aux;
+            if (track->isMuted() || masterMute || track->isPausing() ||
+                mStreamTypes[track->type()].mute) {
+                left = right = aux = 0;
+                if (track->isPausing()) {
+                    track->setPaused();
+                }
+            } else {
+                // read original volumes with volume control
+                float typeVolume = mStreamTypes[track->type()].volume;
+#ifdef LVMX
+                bool streamMute=false;
+                // read the volume from the LivesVibes audio engine.
+                if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType))
+                {
+                    LifeVibes::getStreamVolumes(audioOutputType, track->type(), &typeVolume, &streamMute);
+                    if (streamMute) {
+                        typeVolume = 0;
+                    }
+                }
+#endif
+                float v = masterVolume * typeVolume;
+                uint32_t vl = (uint32_t)(v * cblk->volume[0]) << 12;
+                uint32_t vr = (uint32_t)(v * cblk->volume[1]) << 12;
+
+                // Delegate volume control to effect in track effect chain if needed
+                if (chain != 0 && chain->setVolume_l(&vl, &vr)) {
+                    // Do not ramp volume is volume is controlled by effect
+                    param = AudioMixer::VOLUME;
+                }
+
+                // Convert volumes from 8.24 to 4.12 format
+                uint32_t v_clamped = (vl + (1 << 11)) >> 12;
+                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+                left = int16_t(v_clamped);
+                v_clamped = (vr + (1 << 11)) >> 12;
+                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+                right = int16_t(v_clamped);
+
+                v_clamped = (uint32_t)(v * cblk->sendLevel);
+                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+                aux = int16_t(v_clamped);
+            }
+
+#ifdef LVMX
+            if ( tracksConnectedChanged || stateChanged )
+            {
+                 // only do the ramp when the volume is changed by the user / application
+                 param = AudioMixer::VOLUME;
+            }
+#endif
+
+            // XXX: these things DON'T need to be done each time
+            mAudioMixer->setBufferProvider(track);
+            mAudioMixer->enable(AudioMixer::MIXING);
+
+            mAudioMixer->setParameter(param, AudioMixer::VOLUME0, (void *)left);
+            mAudioMixer->setParameter(param, AudioMixer::VOLUME1, (void *)right);
+            mAudioMixer->setParameter(param, AudioMixer::AUXLEVEL, (void *)aux);
+            mAudioMixer->setParameter(
+                AudioMixer::TRACK,
+                AudioMixer::FORMAT, (void *)track->format());
+            mAudioMixer->setParameter(
+                AudioMixer::TRACK,
+                AudioMixer::CHANNEL_COUNT, (void *)track->channelCount());
+            mAudioMixer->setParameter(
+                AudioMixer::RESAMPLE,
+                AudioMixer::SAMPLE_RATE,
+                (void *)(cblk->sampleRate));
+            mAudioMixer->setParameter(
+                AudioMixer::TRACK,
+                AudioMixer::MAIN_BUFFER, (void *)track->mainBuffer());
+            mAudioMixer->setParameter(
+                AudioMixer::TRACK,
+                AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
+
+            // reset retry count
+            track->mRetryCount = kMaxTrackRetries;
+            mixerStatus = MIXER_TRACKS_READY;
+        } else {
+            //LOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
+            if (track->isStopped()) {
+                track->reset();
+            }
+            if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+                // We have consumed all the buffers of this track.
+                // Remove it from the list of active tracks.
+                tracksToRemove->add(track);
+            } else {
+                // No buffers for this track. Give it a few chances to
+                // fill a buffer, then remove it from active list.
+                if (--(track->mRetryCount) <= 0) {
+                    LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
+                    tracksToRemove->add(track);
+                } else if (mixerStatus != MIXER_TRACKS_READY) {
+                    mixerStatus = MIXER_TRACKS_ENABLED;
+                }
+            }
+            mAudioMixer->disable(AudioMixer::MIXING);
+        }
+    }
+
+    // remove all the tracks that need to be...
+    count = tracksToRemove->size();
+    if (UNLIKELY(count)) {
+        for (size_t i=0 ; i<count ; i++) {
+            const sp<Track>& track = tracksToRemove->itemAt(i);
+            mActiveTracks.remove(track);
+            if (track->mainBuffer() != mMixBuffer) {
+                chain = getEffectChain_l(track->sessionId());
+                if (chain != 0) {
+                    LOGV("stopping track on chain %p for session Id: %d", chain.get(), track->sessionId());
+                    chain->stopTrack();
+                }
+            }
+            if (track->isTerminated()) {
+                mTracks.remove(track);
+                deleteTrackName_l(track->mName);
+            }
+        }
+    }
+
+    // mix buffer must be cleared if all tracks are connected to an
+    // effect chain as in this case the mixer will not write to
+    // mix buffer and track effects will accumulate into it
+    if (mixedTracks != 0 && mixedTracks == tracksWithEffect) {
+        memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
+    }
+
+    return mixerStatus;
+}
+
+void AudioFlinger::MixerThread::invalidateTracks(int streamType)
+{
+    LOGV ("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %d",
+            this,  streamType, mTracks.size());
+    Mutex::Autolock _l(mLock);
+
+    size_t size = mTracks.size();
+    for (size_t i = 0; i < size; i++) {
+        sp<Track> t = mTracks[i];
+        if (t->type() == streamType) {
+            t->mCblk->lock.lock();
+            t->mCblk->flags |= CBLK_INVALID_ON;
+            t->mCblk->cv.signal();
+            t->mCblk->lock.unlock();
+        }
+    }
+}
+
+
+// getTrackName_l() must be called with ThreadBase::mLock held
+int AudioFlinger::MixerThread::getTrackName_l()
+{
+    return mAudioMixer->getTrackName();
+}
+
+// deleteTrackName_l() must be called with ThreadBase::mLock held
+void AudioFlinger::MixerThread::deleteTrackName_l(int name)
+{
+    LOGV("remove track (%d) and delete from mixer", name);
+    mAudioMixer->deleteTrackName(name);
+}
+
+// checkForNewParameters_l() must be called with ThreadBase::mLock held
+bool AudioFlinger::MixerThread::checkForNewParameters_l()
+{
+    bool reconfig = false;
+
+    while (!mNewParameters.isEmpty()) {
+        status_t status = NO_ERROR;
+        String8 keyValuePair = mNewParameters[0];
+        AudioParameter param = AudioParameter(keyValuePair);
+        int value;
+
+        if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
+            if (value != AudioSystem::PCM_16_BIT) {
+                status = BAD_VALUE;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
+            if (value != AudioSystem::CHANNEL_OUT_STEREO) {
+                status = BAD_VALUE;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (!mTracks.isEmpty()) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (param.getInt(String8(AudioParameter::keyRouting), value) == NO_ERROR) {
+            // forward device change to effects that have requested to be
+            // aware of attached audio device.
+            mDevice = (uint32_t)value;
+            for (size_t i = 0; i < mEffectChains.size(); i++) {
+                mEffectChains[i]->setDevice_l(mDevice);
+            }
+        }
+
+        if (status == NO_ERROR) {
+            status = mOutput->setParameters(keyValuePair);
+            if (!mStandby && status == INVALID_OPERATION) {
+               mOutput->standby();
+               mStandby = true;
+               mBytesWritten = 0;
+               status = mOutput->setParameters(keyValuePair);
+            }
+            if (status == NO_ERROR && reconfig) {
+                delete mAudioMixer;
+                readOutputParameters();
+                mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
+                for (size_t i = 0; i < mTracks.size() ; i++) {
+                    int name = getTrackName_l();
+                    if (name < 0) break;
+                    mTracks[i]->mName = name;
+                    // limit track sample rate to 2 x new output sample rate
+                    if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) {
+                        mTracks[i]->mCblk->sampleRate = 2 * sampleRate();
+                    }
+                }
+                sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+            }
+        }
+
+        mNewParameters.removeAt(0);
+
+        mParamStatus = status;
+        mParamCond.signal();
+        mWaitWorkCV.wait(mLock);
+    }
+    return reconfig;
+}
+
+status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    PlaybackThread::dumpInternals(fd, args);
+
+    snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
+{
+    return (uint32_t)(mOutput->latency() * 1000) / 2;
+}
+
+uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
+{
+    return (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
+}
+
+// ----------------------------------------------------------------------------
+AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
+    :   PlaybackThread(audioFlinger, output, id, device)
+{
+    mType = PlaybackThread::DIRECT;
+}
+
+AudioFlinger::DirectOutputThread::~DirectOutputThread()
+{
+}
+
+
+static inline int16_t clamp16(int32_t sample)
+{
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
+static inline
+int32_t mul(int16_t in, int16_t v)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    asm( "smulbb %[out], %[in], %[v] \n"
+         : [out]"=r"(out)
+         : [in]"%r"(in), [v]"r"(v)
+         : );
+    return out;
+#else
+    return in * int32_t(v);
+#endif
+}
+
+void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
+{
+    // Do not apply volume on compressed audio
+    if (!AudioSystem::isLinearPCM(mFormat)) {
+        return;
+    }
+
+    // convert to signed 16 bit before volume calculation
+    if (mFormat == AudioSystem::PCM_8_BIT) {
+        size_t count = mFrameCount * mChannelCount;
+        uint8_t *src = (uint8_t *)mMixBuffer + count-1;
+        int16_t *dst = mMixBuffer + count-1;
+        while(count--) {
+            *dst-- = (int16_t)(*src--^0x80) << 8;
+        }
+    }
+
+    size_t frameCount = mFrameCount;
+    int16_t *out = mMixBuffer;
+    if (ramp) {
+        if (mChannelCount == 1) {
+            int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
+            int32_t vlInc = d / (int32_t)frameCount;
+            int32_t vl = ((int32_t)mLeftVolShort << 16);
+            do {
+                out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
+                out++;
+                vl += vlInc;
+            } while (--frameCount);
+
+        } else {
+            int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
+            int32_t vlInc = d / (int32_t)frameCount;
+            d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
+            int32_t vrInc = d / (int32_t)frameCount;
+            int32_t vl = ((int32_t)mLeftVolShort << 16);
+            int32_t vr = ((int32_t)mRightVolShort << 16);
+            do {
+                out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
+                out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
+                out += 2;
+                vl += vlInc;
+                vr += vrInc;
+            } while (--frameCount);
+        }
+    } else {
+        if (mChannelCount == 1) {
+            do {
+                out[0] = clamp16(mul(out[0], leftVol) >> 12);
+                out++;
+            } while (--frameCount);
+        } else {
+            do {
+                out[0] = clamp16(mul(out[0], leftVol) >> 12);
+                out[1] = clamp16(mul(out[1], rightVol) >> 12);
+                out += 2;
+            } while (--frameCount);
+        }
+    }
+
+    // convert back to unsigned 8 bit after volume calculation
+    if (mFormat == AudioSystem::PCM_8_BIT) {
+        size_t count = mFrameCount * mChannelCount;
+        int16_t *src = mMixBuffer;
+        uint8_t *dst = (uint8_t *)mMixBuffer;
+        while(count--) {
+            *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
+        }
+    }
+
+    mLeftVolShort = leftVol;
+    mRightVolShort = rightVol;
+}
+
+bool AudioFlinger::DirectOutputThread::threadLoop()
+{
+    uint32_t mixerStatus = MIXER_IDLE;
+    sp<Track> trackToRemove;
+    sp<Track> activeTrack;
+    nsecs_t standbyTime = systemTime();
+    int8_t *curBuf;
+    size_t mixBufferSize = mFrameCount*mFrameSize;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
+    // use shorter standby delay as on normal output to release
+    // hardware resources as soon as possible
+    nsecs_t standbyDelay = microseconds(activeSleepTime*2);
+
+    while (!exitPending())
+    {
+        bool rampVolume;
+        uint16_t leftVol;
+        uint16_t rightVol;
+        Vector< sp<EffectChain> > effectChains;
+
+        processConfigEvents();
+
+        mixerStatus = MIXER_IDLE;
+
+        { // scope for the mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount*mFrameSize;
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
+                standbyDelay = microseconds(activeSleepTime*2);
+            }
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
+                        mSuspended) {
+                // wait until we have something to do...
+                if (!mStandby) {
+                    LOGV("Audio hardware entering standby, mixer %p\n", this);
+                    mOutput->standby();
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+
+                    if (exitPending()) break;
+
+                    LOGV("DirectOutputThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("DirectOutputThread %p TID %d waking up in active mode\n", this, gettid());
+
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + standbyDelay;
+                    sleepTime = idleSleepTime;
+                    continue;
+                }
+            }
+
+            effectChains = mEffectChains;
+
+            // find out which tracks need to be processed
+            if (mActiveTracks.size() != 0) {
+                sp<Track> t = mActiveTracks[0].promote();
+                if (t == 0) continue;
+
+                Track* const track = t.get();
+                audio_track_cblk_t* cblk = track->cblk();
+
+                // The first time a track is added we wait
+                // for all its buffers to be filled before processing it
+                if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
+                        !track->isPaused() && !track->isTerminated())
+                {
+                    //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
+
+                    if (track->mFillingUpStatus == Track::FS_FILLED) {
+                        track->mFillingUpStatus = Track::FS_ACTIVE;
+                        mLeftVolFloat = mRightVolFloat = 0;
+                        mLeftVolShort = mRightVolShort = 0;
+                        if (track->mState == TrackBase::RESUMING) {
+                            track->mState = TrackBase::ACTIVE;
+                            rampVolume = true;
+                        }
+                    } else if (cblk->server != 0) {
+                        // If the track is stopped before the first frame was mixed,
+                        // do not apply ramp
+                        rampVolume = true;
+                    }
+                    // compute volume for this track
+                    float left, right;
+                    if (track->isMuted() || mMasterMute || track->isPausing() ||
+                        mStreamTypes[track->type()].mute) {
+                        left = right = 0;
+                        if (track->isPausing()) {
+                            track->setPaused();
+                        }
+                    } else {
+                        float typeVolume = mStreamTypes[track->type()].volume;
+                        float v = mMasterVolume * typeVolume;
+                        float v_clamped = v * cblk->volume[0];
+                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                        left = v_clamped/MAX_GAIN;
+                        v_clamped = v * cblk->volume[1];
+                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                        right = v_clamped/MAX_GAIN;
+                    }
+
+                    if (left != mLeftVolFloat || right != mRightVolFloat) {
+                        mLeftVolFloat = left;
+                        mRightVolFloat = right;
+
+                        // If audio HAL implements volume control,
+                        // force software volume to nominal value
+                        if (mOutput->setVolume(left, right) == NO_ERROR) {
+                            left = 1.0f;
+                            right = 1.0f;
+                        }
+
+                        // Convert volumes from float to 8.24
+                        uint32_t vl = (uint32_t)(left * (1 << 24));
+                        uint32_t vr = (uint32_t)(right * (1 << 24));
+
+                        // Delegate volume control to effect in track effect chain if needed
+                        // only one effect chain can be present on DirectOutputThread, so if
+                        // there is one, the track is connected to it
+                        if (!effectChains.isEmpty()) {
+                            // Do not ramp volume is volume is controlled by effect
+                            if(effectChains[0]->setVolume_l(&vl, &vr)) {
+                                rampVolume = false;
+                            }
+                        }
+
+                        // Convert volumes from 8.24 to 4.12 format
+                        uint32_t v_clamped = (vl + (1 << 11)) >> 12;
+                        if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+                        leftVol = (uint16_t)v_clamped;
+                        v_clamped = (vr + (1 << 11)) >> 12;
+                        if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+                        rightVol = (uint16_t)v_clamped;
+                    } else {
+                        leftVol = mLeftVolShort;
+                        rightVol = mRightVolShort;
+                        rampVolume = false;
+                    }
+
+                    // reset retry count
+                    track->mRetryCount = kMaxTrackRetriesDirect;
+                    activeTrack = t;
+                    mixerStatus = MIXER_TRACKS_READY;
+                } else {
+                    //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+                    if (track->isStopped()) {
+                        track->reset();
+                    }
+                    if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+                        // We have consumed all the buffers of this track.
+                        // Remove it from the list of active tracks.
+                        trackToRemove = track;
+                    } else {
+                        // No buffers for this track. Give it a few chances to
+                        // fill a buffer, then remove it from active list.
+                        if (--(track->mRetryCount) <= 0) {
+                            LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
+                            trackToRemove = track;
+                        } else {
+                            mixerStatus = MIXER_TRACKS_ENABLED;
+                        }
+                    }
+                }
+            }
+
+            // remove all the tracks that need to be...
+            if (UNLIKELY(trackToRemove != 0)) {
+                mActiveTracks.remove(trackToRemove);
+                if (!effectChains.isEmpty()) {
+                    LOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
+                            trackToRemove->sessionId());
+                    effectChains[0]->stopTrack();
+                }
+                if (trackToRemove->isTerminated()) {
+                    mTracks.remove(trackToRemove);
+                    deleteTrackName_l(trackToRemove->mName);
+                }
+            }
+
+            lockEffectChains_l(effectChains);
+       }
+
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
+            AudioBufferProvider::Buffer buffer;
+            size_t frameCount = mFrameCount;
+            curBuf = (int8_t *)mMixBuffer;
+            // output audio to hardware
+            while (frameCount) {
+                buffer.frameCount = frameCount;
+                activeTrack->getNextBuffer(&buffer);
+                if (UNLIKELY(buffer.raw == 0)) {
+                    memset(curBuf, 0, frameCount * mFrameSize);
+                    break;
+                }
+                memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
+                frameCount -= buffer.frameCount;
+                curBuf += buffer.frameCount * mFrameSize;
+                activeTrack->releaseBuffer(&buffer);
+            }
+            sleepTime = 0;
+            standbyTime = systemTime() + standbyDelay;
+        } else {
+            if (sleepTime == 0) {
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
+            } else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
+                memset (mMixBuffer, 0, mFrameCount * mFrameSize);
+                sleepTime = 0;
+            }
+        }
+
+        if (mSuspended) {
+            sleepTime = idleSleepTime;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+            if (mixerStatus == MIXER_TRACKS_READY) {
+                applyVolume(leftVol, rightVol, rampVolume);
+            }
+            for (size_t i = 0; i < effectChains.size(); i ++) {
+                effectChains[i]->process_l();
+            }
+            unlockEffectChains(effectChains);
+
+            mLastWriteTime = systemTime();
+            mInWrite = true;
+            mBytesWritten += mixBufferSize;
+            int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
+            if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
+            mNumWrites++;
+            mInWrite = false;
+            mStandby = false;
+        } else {
+            unlockEffectChains(effectChains);
+            usleep(sleepTime);
+        }
+
+        // finally let go of removed track, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        trackToRemove.clear();
+        activeTrack.clear();
+
+        // Effect chains will be actually deleted here if they were removed from
+        // mEffectChains list during mixing or effects processing
+        effectChains.clear();
+    }
+
+    if (!mStandby) {
+        mOutput->standby();
+    }
+
+    LOGV("DirectOutputThread %p exiting", this);
+    return false;
+}
+
+// getTrackName_l() must be called with ThreadBase::mLock held
+int AudioFlinger::DirectOutputThread::getTrackName_l()
+{
+    return 0;
+}
+
+// deleteTrackName_l() must be called with ThreadBase::mLock held
+void AudioFlinger::DirectOutputThread::deleteTrackName_l(int name)
+{
+}
+
+// checkForNewParameters_l() must be called with ThreadBase::mLock held
+bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
+{
+    bool reconfig = false;
+
+    while (!mNewParameters.isEmpty()) {
+        status_t status = NO_ERROR;
+        String8 keyValuePair = mNewParameters[0];
+        AudioParameter param = AudioParameter(keyValuePair);
+        int value;
+
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (!mTracks.isEmpty()) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (status == NO_ERROR) {
+            status = mOutput->setParameters(keyValuePair);
+            if (!mStandby && status == INVALID_OPERATION) {
+               mOutput->standby();
+               mStandby = true;
+               mBytesWritten = 0;
+               status = mOutput->setParameters(keyValuePair);
+            }
+            if (status == NO_ERROR && reconfig) {
+                readOutputParameters();
+                sendConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED);
+            }
+        }
+
+        mNewParameters.removeAt(0);
+
+        mParamStatus = status;
+        mParamCond.signal();
+        mWaitWorkCV.wait(mLock);
+    }
+    return reconfig;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
+{
+    uint32_t time;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        time = (uint32_t)(mOutput->latency() * 1000) / 2;
+    } else {
+        time = 10000;
+    }
+    return time;
+}
+
+uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
+{
+    uint32_t time;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
+    } else {
+        time = 10000;
+    }
+    return time;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
+    :   MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX)
+{
+    mType = PlaybackThread::DUPLICATING;
+    addOutputTrack(mainThread);
+}
+
+AudioFlinger::DuplicatingThread::~DuplicatingThread()
+{
+    for (size_t i = 0; i < mOutputTracks.size(); i++) {
+        mOutputTracks[i]->destroy();
+    }
+    mOutputTracks.clear();
+}
+
+bool AudioFlinger::DuplicatingThread::threadLoop()
+{
+    Vector< sp<Track> > tracksToRemove;
+    uint32_t mixerStatus = MIXER_IDLE;
+    nsecs_t standbyTime = systemTime();
+    size_t mixBufferSize = mFrameCount*mFrameSize;
+    SortedVector< sp<OutputTrack> > outputTracks;
+    uint32_t writeFrames = 0;
+    uint32_t activeSleepTime = activeSleepTimeUs();
+    uint32_t idleSleepTime = idleSleepTimeUs();
+    uint32_t sleepTime = idleSleepTime;
+    Vector< sp<EffectChain> > effectChains;
+
+    while (!exitPending())
+    {
+        processConfigEvents();
+
+        mixerStatus = MIXER_IDLE;
+        { // scope for the mLock
+
+            Mutex::Autolock _l(mLock);
+
+            if (checkForNewParameters_l()) {
+                mixBufferSize = mFrameCount*mFrameSize;
+                updateWaitTime();
+                activeSleepTime = activeSleepTimeUs();
+                idleSleepTime = idleSleepTimeUs();
+            }
+
+            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
+
+            for (size_t i = 0; i < mOutputTracks.size(); i++) {
+                outputTracks.add(mOutputTracks[i]);
+            }
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
+                         mSuspended) {
+                if (!mStandby) {
+                    for (size_t i = 0; i < outputTracks.size(); i++) {
+                        outputTracks[i]->stop();
+                    }
+                    mStandby = true;
+                    mBytesWritten = 0;
+                }
+
+                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
+                    // we're about to wait, flush the binder command buffer
+                    IPCThreadState::self()->flushCommands();
+                    outputTracks.clear();
+
+                    if (exitPending()) break;
+
+                    LOGV("DuplicatingThread %p TID %d going to sleep\n", this, gettid());
+                    mWaitWorkCV.wait(mLock);
+                    LOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
+                    if (mMasterMute == false) {
+                        char value[PROPERTY_VALUE_MAX];
+                        property_get("ro.audio.silent", value, "0");
+                        if (atoi(value)) {
+                            LOGD("Silence is golden");
+                            setMasterMute(true);
+                        }
+                    }
+
+                    standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    sleepTime = idleSleepTime;
+                    continue;
+                }
+            }
+
+            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
+
+            // prevent any changes in effect chain list and in each effect chain
+            // during mixing and effect process as the audio buffers could be deleted
+            // or modified if an effect is created or deleted
+            lockEffectChains_l(effectChains);
+        }
+
+        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
+            // mix buffers...
+            if (outputsReady(outputTracks)) {
+                mAudioMixer->process();
+            } else {
+                memset(mMixBuffer, 0, mixBufferSize);
+            }
+            sleepTime = 0;
+            writeFrames = mFrameCount;
+        } else {
+            if (sleepTime == 0) {
+                if (mixerStatus == MIXER_TRACKS_ENABLED) {
+                    sleepTime = activeSleepTime;
+                } else {
+                    sleepTime = idleSleepTime;
+                }
+            } else if (mBytesWritten != 0) {
+                // flush remaining overflow buffers in output tracks
+                for (size_t i = 0; i < outputTracks.size(); i++) {
+                    if (outputTracks[i]->isActive()) {
+                        sleepTime = 0;
+                        writeFrames = 0;
+                        memset(mMixBuffer, 0, mixBufferSize);
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (mSuspended) {
+            sleepTime = idleSleepTime;
+        }
+        // sleepTime == 0 means we must write to audio hardware
+        if (sleepTime == 0) {
+            for (size_t i = 0; i < effectChains.size(); i ++) {
+                effectChains[i]->process_l();
+            }
+            // enable changes in effect chain
+            unlockEffectChains(effectChains);
+
+            standbyTime = systemTime() + kStandbyTimeInNsecs;
+            for (size_t i = 0; i < outputTracks.size(); i++) {
+                outputTracks[i]->write(mMixBuffer, writeFrames);
+            }
+            mStandby = false;
+            mBytesWritten += mixBufferSize;
+        } else {
+            // enable changes in effect chain
+            unlockEffectChains(effectChains);
+            usleep(sleepTime);
+        }
+
+        // finally let go of all our tracks, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        tracksToRemove.clear();
+        outputTracks.clear();
+
+        // Effect chains will be actually deleted here if they were removed from
+        // mEffectChains list during mixing or effects processing
+        effectChains.clear();
+    }
+
+    return false;
+}
+
+void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
+{
+    int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate();
+    OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread,
+                                            this,
+                                            mSampleRate,
+                                            mFormat,
+                                            mChannelCount,
+                                            frameCount);
+    if (outputTrack->cblk() != NULL) {
+        thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f);
+        mOutputTracks.add(outputTrack);
+        LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
+        updateWaitTime();
+    }
+}
+
+void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
+{
+    Mutex::Autolock _l(mLock);
+    for (size_t i = 0; i < mOutputTracks.size(); i++) {
+        if (mOutputTracks[i]->thread() == (ThreadBase *)thread) {
+            mOutputTracks[i]->destroy();
+            mOutputTracks.removeAt(i);
+            updateWaitTime();
+            return;
+        }
+    }
+    LOGV("removeOutputTrack(): unkonwn thread: %p", thread);
+}
+
+void AudioFlinger::DuplicatingThread::updateWaitTime()
+{
+    mWaitTimeMs = UINT_MAX;
+    for (size_t i = 0; i < mOutputTracks.size(); i++) {
+        sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
+        if (strong != NULL) {
+            uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
+            if (waitTimeMs < mWaitTimeMs) {
+                mWaitTimeMs = waitTimeMs;
+            }
+        }
+    }
+}
+
+
+bool AudioFlinger::DuplicatingThread::outputsReady(SortedVector< sp<OutputTrack> > &outputTracks)
+{
+    for (size_t i = 0; i < outputTracks.size(); i++) {
+        sp <ThreadBase> thread = outputTracks[i]->thread().promote();
+        if (thread == 0) {
+            LOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p", outputTracks[i].get());
+            return false;
+        }
+        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        if (playbackThread->standby() && !playbackThread->isSuspended()) {
+            LOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(), thread.get());
+            return false;
+        }
+    }
+    return true;
+}
+
+uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs()
+{
+    return (mWaitTimeMs * 1000) / 2;
+}
+
+// ----------------------------------------------------------------------------
+
+// TrackBase constructor must be called with AudioFlinger::mLock held
+AudioFlinger::ThreadBase::TrackBase::TrackBase(
+            const wp<ThreadBase>& thread,
+            const sp<Client>& client,
+            uint32_t sampleRate,
+            int format,
+            int channelCount,
+            int frameCount,
+            uint32_t flags,
+            const sp<IMemory>& sharedBuffer,
+            int sessionId)
+    :   RefBase(),
+        mThread(thread),
+        mClient(client),
+        mCblk(0),
+        mFrameCount(0),
+        mState(IDLE),
+        mClientTid(-1),
+        mFormat(format),
+        mFlags(flags & ~SYSTEM_FLAGS_MASK),
+        mSessionId(sessionId)
+{
+    LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
+
+    // LOGD("Creating track with %d buffers @ %d bytes", bufferCount, bufferSize);
+   size_t size = sizeof(audio_track_cblk_t);
+   size_t bufferSize = frameCount*channelCount*sizeof(int16_t);
+   if (sharedBuffer == 0) {
+       size += bufferSize;
+   }
+
+   if (client != NULL) {
+        mCblkMemory = client->heap()->allocate(size);
+        if (mCblkMemory != 0) {
+            mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
+            if (mCblk) { // construct the shared structure in-place.
+                new(mCblk) audio_track_cblk_t();
+                // clear all buffers
+                mCblk->frameCount = frameCount;
+                mCblk->sampleRate = sampleRate;
+                mCblk->channelCount = (uint8_t)channelCount;
+                if (sharedBuffer == 0) {
+                    mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
+                    memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
+                    // Force underrun condition to avoid false underrun callback until first data is
+                    // written to buffer
+                    mCblk->flags = CBLK_UNDERRUN_ON;
+                } else {
+                    mBuffer = sharedBuffer->pointer();
+                }
+                mBufferEnd = (uint8_t *)mBuffer + bufferSize;
+            }
+        } else {
+            LOGE("not enough memory for AudioTrack size=%u", size);
+            client->heap()->dump("AudioTrack");
+            return;
+        }
+   } else {
+       mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
+       if (mCblk) { // construct the shared structure in-place.
+           new(mCblk) audio_track_cblk_t();
+           // clear all buffers
+           mCblk->frameCount = frameCount;
+           mCblk->sampleRate = sampleRate;
+           mCblk->channelCount = (uint8_t)channelCount;
+           mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
+           memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
+           // Force underrun condition to avoid false underrun callback until first data is
+           // written to buffer
+           mCblk->flags = CBLK_UNDERRUN_ON;
+           mBufferEnd = (uint8_t *)mBuffer + bufferSize;
+       }
+   }
+}
+
+AudioFlinger::ThreadBase::TrackBase::~TrackBase()
+{
+    if (mCblk) {
+        mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
+        if (mClient == NULL) {
+            delete mCblk;
+        }
+    }
+    mCblkMemory.clear();            // and free the shared memory
+    if (mClient != NULL) {
+        Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+        mClient.clear();
+    }
+}
+
+void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    buffer->raw = 0;
+    mFrameCount = buffer->frameCount;
+    step();
+    buffer->frameCount = 0;
+}
+
+bool AudioFlinger::ThreadBase::TrackBase::step() {
+    bool result;
+    audio_track_cblk_t* cblk = this->cblk();
+
+    result = cblk->stepServer(mFrameCount);
+    if (!result) {
+        LOGV("stepServer failed acquiring cblk mutex");
+        mFlags |= STEPSERVER_FAILED;
+    }
+    return result;
+}
+
+void AudioFlinger::ThreadBase::TrackBase::reset() {
+    audio_track_cblk_t* cblk = this->cblk();
+
+    cblk->user = 0;
+    cblk->server = 0;
+    cblk->userBase = 0;
+    cblk->serverBase = 0;
+    mFlags &= (uint32_t)(~SYSTEM_FLAGS_MASK);
+    LOGV("TrackBase::reset");
+}
+
+sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
+{
+    return mCblkMemory;
+}
+
+int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
+    return (int)mCblk->sampleRate;
+}
+
+int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
+    return (int)mCblk->channelCount;
+}
+
+void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
+    audio_track_cblk_t* cblk = this->cblk();
+    int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
+    int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
+
+    // Check validity of returned pointer in case the track control block would have been corrupted.
+    if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd ||
+        ((unsigned long)bufferStart & (unsigned long)(cblk->frameSize - 1))) {
+        LOGE("TrackBase::getBuffer buffer out of range:\n    start: %p, end %p , mBuffer %p mBufferEnd %p\n    \
+                server %d, serverBase %d, user %d, userBase %d, channelCount %d",
+                bufferStart, bufferEnd, mBuffer, mBufferEnd,
+                cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channelCount);
+        return 0;
+    }
+
+    return bufferStart;
+}
+
+// ----------------------------------------------------------------------------
+
+// Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
+AudioFlinger::PlaybackThread::Track::Track(
+            const wp<ThreadBase>& thread,
+            const sp<Client>& client,
+            int streamType,
+            uint32_t sampleRate,
+            int format,
+            int channelCount,
+            int frameCount,
+            const sp<IMemory>& sharedBuffer,
+            int sessionId)
+    :   TrackBase(thread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer, sessionId),
+    mMute(false), mSharedBuffer(sharedBuffer), mName(-1), mMainBuffer(NULL), mAuxBuffer(NULL), mAuxEffectId(0)
+{
+    if (mCblk != NULL) {
+        sp<ThreadBase> baseThread = thread.promote();
+        if (baseThread != 0) {
+            PlaybackThread *playbackThread = (PlaybackThread *)baseThread.get();
+            mName = playbackThread->getTrackName_l();
+            mMainBuffer = playbackThread->mixBuffer();
+        }
+        LOGV("Track constructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+        if (mName < 0) {
+            LOGE("no more track names available");
+        }
+        mVolume[0] = 1.0f;
+        mVolume[1] = 1.0f;
+        mStreamType = streamType;
+        // NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
+        // 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
+        mCblk->frameSize = AudioSystem::isLinearPCM(format) ? channelCount * sizeof(int16_t) : sizeof(int8_t);
+    }
+}
+
+AudioFlinger::PlaybackThread::Track::~Track()
+{
+    LOGV("PlaybackThread::Track destructor");
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        mState = TERMINATED;
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::destroy()
+{
+    // NOTE: destroyTrack_l() can remove a strong reference to this Track
+    // by removing it from mTracks vector, so there is a risk that this Tracks's
+    // desctructor is called. As the destructor needs to lock mLock,
+    // we must acquire a strong reference on this Track before locking mLock
+    // here so that the destructor is called only when exiting this function.
+    // On the other hand, as long as Track::destroy() is only called by
+    // TrackHandle destructor, the TrackHandle still holds a strong ref on
+    // this Track with its member mTrack.
+    sp<Track> keep(this);
+    { // scope for mLock
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            if (!isOutputTrack()) {
+                if (mState == ACTIVE || mState == RESUMING) {
+                    AudioSystem::stopOutput(thread->id(),
+                                            (AudioSystem::stream_type)mStreamType,
+                                            mSessionId);
+                }
+                AudioSystem::releaseOutput(thread->id());
+            }
+            Mutex::Autolock _l(thread->mLock);
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            playbackThread->destroyTrack_l(this);
+        }
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "   %05d %05d %03u %03u %03u %05u   %04u %1d %1d %1d %05u %05u %05u  0x%08x 0x%08x 0x%08x 0x%08x\n",
+            mName - AudioMixer::TRACK0,
+            (mClient == NULL) ? getpid() : mClient->pid(),
+            mStreamType,
+            mFormat,
+            mCblk->channelCount,
+            mSessionId,
+            mFrameCount,
+            mState,
+            mMute,
+            mFillingUpStatus,
+            mCblk->sampleRate,
+            mCblk->volume[0],
+            mCblk->volume[1],
+            mCblk->server,
+            mCblk->user,
+            (int)mMainBuffer,
+            (int)mAuxBuffer);
+}
+
+status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+{
+     audio_track_cblk_t* cblk = this->cblk();
+     uint32_t framesReady;
+     uint32_t framesReq = buffer->frameCount;
+
+     // Check if last stepServer failed, try to step now
+     if (mFlags & TrackBase::STEPSERVER_FAILED) {
+         if (!step())  goto getNextBuffer_exit;
+         LOGV("stepServer recovered");
+         mFlags &= ~TrackBase::STEPSERVER_FAILED;
+     }
+
+     framesReady = cblk->framesReady();
+
+     if (LIKELY(framesReady)) {
+        uint32_t s = cblk->server;
+        uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
+
+        bufferEnd = (cblk->loopEnd < bufferEnd) ? cblk->loopEnd : bufferEnd;
+        if (framesReq > framesReady) {
+            framesReq = framesReady;
+        }
+        if (s + framesReq > bufferEnd) {
+            framesReq = bufferEnd - s;
+        }
+
+         buffer->raw = getBuffer(s, framesReq);
+         if (buffer->raw == 0) goto getNextBuffer_exit;
+
+         buffer->frameCount = framesReq;
+        return NO_ERROR;
+     }
+
+getNextBuffer_exit:
+     buffer->raw = 0;
+     buffer->frameCount = 0;
+     LOGV("getNextBuffer() no more data for track %d on thread %p", mName, mThread.unsafe_get());
+     return NOT_ENOUGH_DATA;
+}
+
+bool AudioFlinger::PlaybackThread::Track::isReady() const {
+    if (mFillingUpStatus != FS_FILLING) return true;
+
+    if (mCblk->framesReady() >= mCblk->frameCount ||
+            (mCblk->flags & CBLK_FORCEREADY_MSK)) {
+        mFillingUpStatus = FS_FILLED;
+        mCblk->flags &= ~CBLK_FORCEREADY_MSK;
+        return true;
+    }
+    return false;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::start()
+{
+    status_t status = NO_ERROR;
+    LOGV("start(%d), calling thread %d session %d",
+            mName, IPCThreadState::self()->getCallingPid(), mSessionId);
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        int state = mState;
+        // here the track could be either new, or restarted
+        // in both cases "unstop" the track
+        if (mState == PAUSED) {
+            mState = TrackBase::RESUMING;
+            LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
+        } else {
+            mState = TrackBase::ACTIVE;
+            LOGV("? => ACTIVE (%d) on thread %p", mName, this);
+        }
+
+        if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
+            thread->mLock.unlock();
+            status = AudioSystem::startOutput(thread->id(),
+                                              (AudioSystem::stream_type)mStreamType,
+                                              mSessionId);
+            thread->mLock.lock();
+        }
+        if (status == NO_ERROR) {
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            playbackThread->addTrack_l(this);
+        } else {
+            mState = state;
+        }
+    } else {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+void AudioFlinger::PlaybackThread::Track::stop()
+{
+    LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        int state = mState;
+        if (mState > STOPPED) {
+            mState = STOPPED;
+            // If the track is not active (PAUSED and buffers full), flush buffers
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+                reset();
+            }
+            LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
+        }
+        if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
+            thread->mLock.unlock();
+            AudioSystem::stopOutput(thread->id(),
+                                    (AudioSystem::stream_type)mStreamType,
+                                    mSessionId);
+            thread->mLock.lock();
+        }
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::pause()
+{
+    LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        if (mState == ACTIVE || mState == RESUMING) {
+            mState = PAUSING;
+            LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
+            if (!isOutputTrack()) {
+                thread->mLock.unlock();
+                AudioSystem::stopOutput(thread->id(),
+                                        (AudioSystem::stream_type)mStreamType,
+                                        mSessionId);
+                thread->mLock.lock();
+            }
+        }
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::flush()
+{
+    LOGV("flush(%d)", mName);
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        Mutex::Autolock _l(thread->mLock);
+        if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
+            return;
+        }
+        // No point remaining in PAUSED state after a flush => go to
+        // STOPPED state
+        mState = STOPPED;
+
+        mCblk->lock.lock();
+        // NOTE: reset() will reset cblk->user and cblk->server with
+        // the risk that at the same time, the AudioMixer is trying to read
+        // data. In this case, getNextBuffer() would return a NULL pointer
+        // as audio buffer => the AudioMixer code MUST always test that pointer
+        // returned by getNextBuffer() is not NULL!
+        reset();
+        mCblk->lock.unlock();
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::reset()
+{
+    // Do not reset twice to avoid discarding data written just after a flush and before
+    // the audioflinger thread detects the track is stopped.
+    if (!mResetDone) {
+        TrackBase::reset();
+        // Force underrun condition to avoid false underrun callback until first data is
+        // written to buffer
+        mCblk->flags |= CBLK_UNDERRUN_ON;
+        mCblk->flags &= ~CBLK_FORCEREADY_MSK;
+        mFillingUpStatus = FS_FILLING;
+        mResetDone = true;
+    }
+}
+
+void AudioFlinger::PlaybackThread::Track::mute(bool muted)
+{
+    mMute = muted;
+}
+
+void AudioFlinger::PlaybackThread::Track::setVolume(float left, float right)
+{
+    mVolume[0] = left;
+    mVolume[1] = right;
+}
+
+status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
+{
+    status_t status = DEAD_OBJECT;
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+       PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+       status = playbackThread->attachAuxEffect(this, EffectId);
+    }
+    return status;
+}
+
+void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
+{
+    mAuxEffectId = EffectId;
+    mAuxBuffer = buffer;
+}
+
+// ----------------------------------------------------------------------------
+
+// RecordTrack constructor must be called with AudioFlinger::mLock held
+AudioFlinger::RecordThread::RecordTrack::RecordTrack(
+            const wp<ThreadBase>& thread,
+            const sp<Client>& client,
+            uint32_t sampleRate,
+            int format,
+            int channelCount,
+            int frameCount,
+            uint32_t flags,
+            int sessionId)
+    :   TrackBase(thread, client, sampleRate, format,
+                  channelCount, frameCount, flags, 0, sessionId),
+        mOverflow(false)
+{
+    if (mCblk != NULL) {
+       LOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer);
+       if (format == AudioSystem::PCM_16_BIT) {
+           mCblk->frameSize = channelCount * sizeof(int16_t);
+       } else if (format == AudioSystem::PCM_8_BIT) {
+           mCblk->frameSize = channelCount * sizeof(int8_t);
+       } else {
+           mCblk->frameSize = sizeof(int8_t);
+       }
+    }
+}
+
+AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
+{
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        AudioSystem::releaseInput(thread->id());
+    }
+}
+
+status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    audio_track_cblk_t* cblk = this->cblk();
+    uint32_t framesAvail;
+    uint32_t framesReq = buffer->frameCount;
+
+     // Check if last stepServer failed, try to step now
+    if (mFlags & TrackBase::STEPSERVER_FAILED) {
+        if (!step()) goto getNextBuffer_exit;
+        LOGV("stepServer recovered");
+        mFlags &= ~TrackBase::STEPSERVER_FAILED;
+    }
+
+    framesAvail = cblk->framesAvailable_l();
+
+    if (LIKELY(framesAvail)) {
+        uint32_t s = cblk->server;
+        uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
+
+        if (framesReq > framesAvail) {
+            framesReq = framesAvail;
+        }
+        if (s + framesReq > bufferEnd) {
+            framesReq = bufferEnd - s;
+        }
+
+        buffer->raw = getBuffer(s, framesReq);
+        if (buffer->raw == 0) goto getNextBuffer_exit;
+
+        buffer->frameCount = framesReq;
+        return NO_ERROR;
+    }
+
+getNextBuffer_exit:
+    buffer->raw = 0;
+    buffer->frameCount = 0;
+    return NOT_ENOUGH_DATA;
+}
+
+status_t AudioFlinger::RecordThread::RecordTrack::start()
+{
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        RecordThread *recordThread = (RecordThread *)thread.get();
+        return recordThread->start(this);
+    } else {
+        return BAD_VALUE;
+    }
+}
+
+void AudioFlinger::RecordThread::RecordTrack::stop()
+{
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        RecordThread *recordThread = (RecordThread *)thread.get();
+        recordThread->stop(this);
+        TrackBase::reset();
+        // Force overerrun condition to avoid false overrun callback until first data is
+        // read from buffer
+        mCblk->flags |= CBLK_UNDERRUN_ON;
+    }
+}
+
+void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "   %05d %03u %03u %05d   %04u %01d %05u  %08x %08x\n",
+            (mClient == NULL) ? getpid() : mClient->pid(),
+            mFormat,
+            mCblk->channelCount,
+            mSessionId,
+            mFrameCount,
+            mState,
+            mCblk->sampleRate,
+            mCblk->server,
+            mCblk->user);
+}
+
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
+            const wp<ThreadBase>& thread,
+            DuplicatingThread *sourceThread,
+            uint32_t sampleRate,
+            int format,
+            int channelCount,
+            int frameCount)
+    :   Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL, 0),
+    mActive(false), mSourceThread(sourceThread)
+{
+
+    PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get();
+    if (mCblk != NULL) {
+        mCblk->flags |= CBLK_DIRECTION_OUT;
+        mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+        mCblk->volume[0] = mCblk->volume[1] = 0x1000;
+        mOutBuffer.frameCount = 0;
+        playbackThread->mTracks.add(this);
+        LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p",
+                mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd);
+    } else {
+        LOGW("Error creating output track on thread %p", playbackThread);
+    }
+}
+
+AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
+{
+    clearBufferQueue();
+}
+
+status_t AudioFlinger::PlaybackThread::OutputTrack::start()
+{
+    status_t status = Track::start();
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    mActive = true;
+    mRetryCount = 127;
+    return status;
+}
+
+void AudioFlinger::PlaybackThread::OutputTrack::stop()
+{
+    Track::stop();
+    clearBufferQueue();
+    mOutBuffer.frameCount = 0;
+    mActive = false;
+}
+
+bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t frames)
+{
+    Buffer *pInBuffer;
+    Buffer inBuffer;
+    uint32_t channelCount = mCblk->channelCount;
+    bool outputBufferFull = false;
+    inBuffer.frameCount = frames;
+    inBuffer.i16 = data;
+
+    uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
+
+    if (!mActive && frames != 0) {
+        start();
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            MixerThread *mixerThread = (MixerThread *)thread.get();
+            if (mCblk->frameCount > frames){
+                if (mBufferQueue.size() < kMaxOverFlowBuffers) {
+                    uint32_t startFrames = (mCblk->frameCount - frames);
+                    pInBuffer = new Buffer;
+                    pInBuffer->mBuffer = new int16_t[startFrames * channelCount];
+                    pInBuffer->frameCount = startFrames;
+                    pInBuffer->i16 = pInBuffer->mBuffer;
+                    memset(pInBuffer->raw, 0, startFrames * channelCount * sizeof(int16_t));
+                    mBufferQueue.add(pInBuffer);
+                } else {
+                    LOGW ("OutputTrack::write() %p no more buffers in queue", this);
+                }
+            }
+        }
+    }
+
+    while (waitTimeLeftMs) {
+        // First write pending buffers, then new data
+        if (mBufferQueue.size()) {
+            pInBuffer = mBufferQueue.itemAt(0);
+        } else {
+            pInBuffer = &inBuffer;
+        }
+
+        if (pInBuffer->frameCount == 0) {
+            break;
+        }
+
+        if (mOutBuffer.frameCount == 0) {
+            mOutBuffer.frameCount = pInBuffer->frameCount;
+            nsecs_t startTime = systemTime();
+            if (obtainBuffer(&mOutBuffer, waitTimeLeftMs) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
+                LOGV ("OutputTrack::write() %p thread %p no more output buffers", this, mThread.unsafe_get());
+                outputBufferFull = true;
+                break;
+            }
+            uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime);
+            if (waitTimeLeftMs >= waitTimeMs) {
+                waitTimeLeftMs -= waitTimeMs;
+            } else {
+                waitTimeLeftMs = 0;
+            }
+        }
+
+        uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
+        memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t));
+        mCblk->stepUser(outFrames);
+        pInBuffer->frameCount -= outFrames;
+        pInBuffer->i16 += outFrames * channelCount;
+        mOutBuffer.frameCount -= outFrames;
+        mOutBuffer.i16 += outFrames * channelCount;
+
+        if (pInBuffer->frameCount == 0) {
+            if (mBufferQueue.size()) {
+                mBufferQueue.removeAt(0);
+                delete [] pInBuffer->mBuffer;
+                delete pInBuffer;
+                LOGV("OutputTrack::write() %p thread %p released overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
+            } else {
+                break;
+            }
+        }
+    }
+
+    // If we could not write all frames, allocate a buffer and queue it for next time.
+    if (inBuffer.frameCount) {
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0 && !thread->standby()) {
+            if (mBufferQueue.size() < kMaxOverFlowBuffers) {
+                pInBuffer = new Buffer;
+                pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channelCount];
+                pInBuffer->frameCount = inBuffer.frameCount;
+                pInBuffer->i16 = pInBuffer->mBuffer;
+                memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channelCount * sizeof(int16_t));
+                mBufferQueue.add(pInBuffer);
+                LOGV("OutputTrack::write() %p thread %p adding overflow buffer %d", this, mThread.unsafe_get(), mBufferQueue.size());
+            } else {
+                LOGW("OutputTrack::write() %p thread %p no more overflow buffers", mThread.unsafe_get(), this);
+            }
+        }
+    }
+
+    // Calling write() with a 0 length buffer, means that no more data will be written:
+    // If no more buffers are pending, fill output track buffer to make sure it is started
+    // by output mixer.
+    if (frames == 0 && mBufferQueue.size() == 0) {
+        if (mCblk->user < mCblk->frameCount) {
+            frames = mCblk->frameCount - mCblk->user;
+            pInBuffer = new Buffer;
+            pInBuffer->mBuffer = new int16_t[frames * channelCount];
+            pInBuffer->frameCount = frames;
+            pInBuffer->i16 = pInBuffer->mBuffer;
+            memset(pInBuffer->raw, 0, frames * channelCount * sizeof(int16_t));
+            mBufferQueue.add(pInBuffer);
+        } else if (mActive) {
+            stop();
+        }
+    }
+
+    return outputBufferFull;
+}
+
+status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
+{
+    int active;
+    status_t result;
+    audio_track_cblk_t* cblk = mCblk;
+    uint32_t framesReq = buffer->frameCount;
+
+//    LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
+    buffer->frameCount  = 0;
+
+    uint32_t framesAvail = cblk->framesAvailable();
+
+
+    if (framesAvail == 0) {
+        Mutex::Autolock _l(cblk->lock);
+        goto start_loop_here;
+        while (framesAvail == 0) {
+            active = mActive;
+            if (UNLIKELY(!active)) {
+                LOGV("Not active and NO_MORE_BUFFERS");
+                return AudioTrack::NO_MORE_BUFFERS;
+            }
+            result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+            if (result != NO_ERROR) {
+                return AudioTrack::NO_MORE_BUFFERS;
+            }
+            // read the server count again
+        start_loop_here:
+            framesAvail = cblk->framesAvailable_l();
+        }
+    }
+
+//    if (framesAvail < framesReq) {
+//        return AudioTrack::NO_MORE_BUFFERS;
+//    }
+
+    if (framesReq > framesAvail) {
+        framesReq = framesAvail;
+    }
+
+    uint32_t u = cblk->user;
+    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
+
+    if (u + framesReq > bufferEnd) {
+        framesReq = bufferEnd - u;
+    }
+
+    buffer->frameCount  = framesReq;
+    buffer->raw         = (void *)cblk->buffer(u);
+    return NO_ERROR;
+}
+
+
+void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
+{
+    size_t size = mBufferQueue.size();
+    Buffer *pBuffer;
+
+    for (size_t i = 0; i < size; i++) {
+        pBuffer = mBufferQueue.itemAt(i);
+        delete [] pBuffer->mBuffer;
+        delete pBuffer;
+    }
+    mBufferQueue.clear();
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
+    :   RefBase(),
+        mAudioFlinger(audioFlinger),
+        mMemoryDealer(new MemoryDealer(1024*1024, "AudioFlinger::Client")),
+        mPid(pid)
+{
+    // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
+}
+
+// Client destructor must be called with AudioFlinger::mLock held
+AudioFlinger::Client::~Client()
+{
+    mAudioFlinger->removeClient_l(mPid);
+}
+
+const sp<MemoryDealer>& AudioFlinger::Client::heap() const
+{
+    return mMemoryDealer;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
+                                                     const sp<IAudioFlingerClient>& client,
+                                                     pid_t pid)
+    : mAudioFlinger(audioFlinger), mPid(pid), mClient(client)
+{
+}
+
+AudioFlinger::NotificationClient::~NotificationClient()
+{
+    mClient.clear();
+}
+
+void AudioFlinger::NotificationClient::binderDied(const wp<IBinder>& who)
+{
+    sp<NotificationClient> keep(this);
+    {
+        mAudioFlinger->removeNotificationClient(mPid);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
+    : BnAudioTrack(),
+      mTrack(track)
+{
+}
+
+AudioFlinger::TrackHandle::~TrackHandle() {
+    // just stop the track on deletion, associated resources
+    // will be freed from the main thread once all pending buffers have
+    // been played. Unless it's not in the active track list, in which
+    // case we free everything now...
+    mTrack->destroy();
+}
+
+status_t AudioFlinger::TrackHandle::start() {
+    return mTrack->start();
+}
+
+void AudioFlinger::TrackHandle::stop() {
+    mTrack->stop();
+}
+
+void AudioFlinger::TrackHandle::flush() {
+    mTrack->flush();
+}
+
+void AudioFlinger::TrackHandle::mute(bool e) {
+    mTrack->mute(e);
+}
+
+void AudioFlinger::TrackHandle::pause() {
+    mTrack->pause();
+}
+
+void AudioFlinger::TrackHandle::setVolume(float left, float right) {
+    mTrack->setVolume(left, right);
+}
+
+sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
+    return mTrack->getCblk();
+}
+
+status_t AudioFlinger::TrackHandle::attachAuxEffect(int EffectId)
+{
+    return mTrack->attachAuxEffect(EffectId);
+}
+
+status_t AudioFlinger::TrackHandle::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    return BnAudioTrack::onTransact(code, data, reply, flags);
+}
+
+// ----------------------------------------------------------------------------
+
+sp<IAudioRecord> AudioFlinger::openRecord(
+        pid_t pid,
+        int input,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        uint32_t flags,
+        int *sessionId,
+        status_t *status)
+{
+    sp<RecordThread::RecordTrack> recordTrack;
+    sp<RecordHandle> recordHandle;
+    sp<Client> client;
+    wp<Client> wclient;
+    status_t lStatus;
+    RecordThread *thread;
+    size_t inFrameCount;
+    int lSessionId;
+
+    // check calling permissions
+    if (!recordingAllowed()) {
+        lStatus = PERMISSION_DENIED;
+        goto Exit;
+    }
+
+    // add client to list
+    { // scope for mLock
+        Mutex::Autolock _l(mLock);
+        thread = checkRecordThread_l(input);
+        if (thread == NULL) {
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+
+        wclient = mClients.valueFor(pid);
+        if (wclient != NULL) {
+            client = wclient.promote();
+        } else {
+            client = new Client(this, pid);
+            mClients.add(pid, client);
+        }
+
+        // If no audio session id is provided, create one here
+        if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
+            lSessionId = *sessionId;
+        } else {
+            lSessionId = nextUniqueId();
+            if (sessionId != NULL) {
+                *sessionId = lSessionId;
+            }
+        }
+        // create new record track. The record track uses one track in mHardwareMixerThread by convention.
+        recordTrack = new RecordThread::RecordTrack(thread, client, sampleRate,
+                                                   format, channelCount, frameCount, flags, lSessionId);
+    }
+    if (recordTrack->getCblk() == NULL) {
+        // remove local strong reference to Client before deleting the RecordTrack so that the Client
+        // destructor is called by the TrackBase destructor with mLock held
+        client.clear();
+        recordTrack.clear();
+        lStatus = NO_MEMORY;
+        goto Exit;
+    }
+
+    // return to handle to client
+    recordHandle = new RecordHandle(recordTrack);
+    lStatus = NO_ERROR;
+
+Exit:
+    if (status) {
+        *status = lStatus;
+    }
+    return recordHandle;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
+    : BnAudioRecord(),
+    mRecordTrack(recordTrack)
+{
+}
+
+AudioFlinger::RecordHandle::~RecordHandle() {
+    stop();
+}
+
+status_t AudioFlinger::RecordHandle::start() {
+    LOGV("RecordHandle::start()");
+    return mRecordTrack->start();
+}
+
+void AudioFlinger::RecordHandle::stop() {
+    LOGV("RecordHandle::stop()");
+    mRecordTrack->stop();
+}
+
+sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
+    return mRecordTrack->getCblk();
+}
+
+status_t AudioFlinger::RecordHandle::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    return BnAudioRecord::onTransact(code, data, reply, flags);
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
+    ThreadBase(audioFlinger, id),
+    mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
+{
+    mReqChannelCount = AudioSystem::popCount(channels);
+    mReqSampleRate = sampleRate;
+    readInputParameters();
+}
+
+
+AudioFlinger::RecordThread::~RecordThread()
+{
+    delete[] mRsmpInBuffer;
+    if (mResampler != 0) {
+        delete mResampler;
+        delete[] mRsmpOutBuffer;
+    }
+}
+
+void AudioFlinger::RecordThread::onFirstRef()
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "Record Thread %p", this);
+
+    run(buffer, PRIORITY_URGENT_AUDIO);
+}
+
+bool AudioFlinger::RecordThread::threadLoop()
+{
+    AudioBufferProvider::Buffer buffer;
+    sp<RecordTrack> activeTrack;
+
+    // start recording
+    while (!exitPending()) {
+
+        processConfigEvents();
+
+        { // scope for mLock
+            Mutex::Autolock _l(mLock);
+            checkForNewParameters_l();
+            if (mActiveTrack == 0 && mConfigEvents.isEmpty()) {
+                if (!mStandby) {
+                    mInput->standby();
+                    mStandby = true;
+                }
+
+                if (exitPending()) break;
+
+                LOGV("RecordThread: loop stopping");
+                // go to sleep
+                mWaitWorkCV.wait(mLock);
+                LOGV("RecordThread: loop starting");
+                continue;
+            }
+            if (mActiveTrack != 0) {
+                if (mActiveTrack->mState == TrackBase::PAUSING) {
+                    if (!mStandby) {
+                        mInput->standby();
+                        mStandby = true;
+                    }
+                    mActiveTrack.clear();
+                    mStartStopCond.broadcast();
+                } else if (mActiveTrack->mState == TrackBase::RESUMING) {
+                    if (mReqChannelCount != mActiveTrack->channelCount()) {
+                        mActiveTrack.clear();
+                        mStartStopCond.broadcast();
+                    } else if (mBytesRead != 0) {
+                        // record start succeeds only if first read from audio input
+                        // succeeds
+                        if (mBytesRead > 0) {
+                            mActiveTrack->mState = TrackBase::ACTIVE;
+                        } else {
+                            mActiveTrack.clear();
+                        }
+                        mStartStopCond.broadcast();
+                    }
+                    mStandby = false;
+                }
+            }
+        }
+
+        if (mActiveTrack != 0) {
+            if (mActiveTrack->mState != TrackBase::ACTIVE &&
+                mActiveTrack->mState != TrackBase::RESUMING) {
+                usleep(5000);
+                continue;
+            }
+            buffer.frameCount = mFrameCount;
+            if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
+                size_t framesOut = buffer.frameCount;
+                if (mResampler == 0) {
+                    // no resampling
+                    while (framesOut) {
+                        size_t framesIn = mFrameCount - mRsmpInIndex;
+                        if (framesIn) {
+                            int8_t *src = (int8_t *)mRsmpInBuffer + mRsmpInIndex * mFrameSize;
+                            int8_t *dst = buffer.i8 + (buffer.frameCount - framesOut) * mActiveTrack->mCblk->frameSize;
+                            if (framesIn > framesOut)
+                                framesIn = framesOut;
+                            mRsmpInIndex += framesIn;
+                            framesOut -= framesIn;
+                            if ((int)mChannelCount == mReqChannelCount ||
+                                mFormat != AudioSystem::PCM_16_BIT) {
+                                memcpy(dst, src, framesIn * mFrameSize);
+                            } else {
+                                int16_t *src16 = (int16_t *)src;
+                                int16_t *dst16 = (int16_t *)dst;
+                                if (mChannelCount == 1) {
+                                    while (framesIn--) {
+                                        *dst16++ = *src16;
+                                        *dst16++ = *src16++;
+                                    }
+                                } else {
+                                    while (framesIn--) {
+                                        *dst16++ = (int16_t)(((int32_t)*src16 + (int32_t)*(src16 + 1)) >> 1);
+                                        src16 += 2;
+                                    }
+                                }
+                            }
+                        }
+                        if (framesOut && mFrameCount == mRsmpInIndex) {
+                            if (framesOut == mFrameCount &&
+                                ((int)mChannelCount == mReqChannelCount || mFormat != AudioSystem::PCM_16_BIT)) {
+                                mBytesRead = mInput->read(buffer.raw, mInputBytes);
+                                framesOut = 0;
+                            } else {
+                                mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+                                mRsmpInIndex = 0;
+                            }
+                            if (mBytesRead < 0) {
+                                LOGE("Error reading audio input");
+                                if (mActiveTrack->mState == TrackBase::ACTIVE) {
+                                    // Force input into standby so that it tries to
+                                    // recover at next read attempt
+                                    mInput->standby();
+                                    usleep(5000);
+                                }
+                                mRsmpInIndex = mFrameCount;
+                                framesOut = 0;
+                                buffer.frameCount = 0;
+                            }
+                        }
+                    }
+                } else {
+                    // resampling
+
+                    memset(mRsmpOutBuffer, 0, framesOut * 2 * sizeof(int32_t));
+                    // alter output frame count as if we were expecting stereo samples
+                    if (mChannelCount == 1 && mReqChannelCount == 1) {
+                        framesOut >>= 1;
+                    }
+                    mResampler->resample(mRsmpOutBuffer, framesOut, this);
+                    // ditherAndClamp() works as long as all buffers returned by mActiveTrack->getNextBuffer()
+                    // are 32 bit aligned which should be always true.
+                    if (mChannelCount == 2 && mReqChannelCount == 1) {
+                        AudioMixer::ditherAndClamp(mRsmpOutBuffer, mRsmpOutBuffer, framesOut);
+                        // the resampler always outputs stereo samples: do post stereo to mono conversion
+                        int16_t *src = (int16_t *)mRsmpOutBuffer;
+                        int16_t *dst = buffer.i16;
+                        while (framesOut--) {
+                            *dst++ = (int16_t)(((int32_t)*src + (int32_t)*(src + 1)) >> 1);
+                            src += 2;
+                        }
+                    } else {
+                        AudioMixer::ditherAndClamp((int32_t *)buffer.raw, mRsmpOutBuffer, framesOut);
+                    }
+
+                }
+                mActiveTrack->releaseBuffer(&buffer);
+                mActiveTrack->overflow();
+            }
+            // client isn't retrieving buffers fast enough
+            else {
+                if (!mActiveTrack->setOverflow())
+                    LOGW("RecordThread: buffer overflow");
+                // Release the processor for a while before asking for a new buffer.
+                // This will give the application more chance to read from the buffer and
+                // clear the overflow.
+                usleep(5000);
+            }
+        }
+    }
+
+    if (!mStandby) {
+        mInput->standby();
+    }
+    mActiveTrack.clear();
+
+    mStartStopCond.broadcast();
+
+    LOGV("RecordThread %p exiting", this);
+    return false;
+}
+
+status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
+{
+    LOGV("RecordThread::start");
+    sp <ThreadBase> strongMe = this;
+    status_t status = NO_ERROR;
+    {
+        AutoMutex lock(&mLock);
+        if (mActiveTrack != 0) {
+            if (recordTrack != mActiveTrack.get()) {
+                status = -EBUSY;
+            } else if (mActiveTrack->mState == TrackBase::PAUSING) {
+                mActiveTrack->mState = TrackBase::ACTIVE;
+            }
+            return status;
+        }
+
+        recordTrack->mState = TrackBase::IDLE;
+        mActiveTrack = recordTrack;
+        mLock.unlock();
+        status_t status = AudioSystem::startInput(mId);
+        mLock.lock();
+        if (status != NO_ERROR) {
+            mActiveTrack.clear();
+            return status;
+        }
+        mActiveTrack->mState = TrackBase::RESUMING;
+        mRsmpInIndex = mFrameCount;
+        mBytesRead = 0;
+        // signal thread to start
+        LOGV("Signal record thread");
+        mWaitWorkCV.signal();
+        // do not wait for mStartStopCond if exiting
+        if (mExiting) {
+            mActiveTrack.clear();
+            status = INVALID_OPERATION;
+            goto startError;
+        }
+        mStartStopCond.wait(mLock);
+        if (mActiveTrack == 0) {
+            LOGV("Record failed to start");
+            status = BAD_VALUE;
+            goto startError;
+        }
+        LOGV("Record started OK");
+        return status;
+    }
+startError:
+    AudioSystem::stopInput(mId);
+    return status;
+}
+
+void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
+    LOGV("RecordThread::stop");
+    sp <ThreadBase> strongMe = this;
+    {
+        AutoMutex lock(&mLock);
+        if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
+            mActiveTrack->mState = TrackBase::PAUSING;
+            // do not wait for mStartStopCond if exiting
+            if (mExiting) {
+                return;
+            }
+            mStartStopCond.wait(mLock);
+            // if we have been restarted, recordTrack == mActiveTrack.get() here
+            if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
+                mLock.unlock();
+                AudioSystem::stopInput(mId);
+                mLock.lock();
+                LOGV("Record stopped OK");
+            }
+        }
+    }
+}
+
+status_t AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    pid_t pid = 0;
+
+    snprintf(buffer, SIZE, "\nInput thread %p internals\n", this);
+    result.append(buffer);
+
+    if (mActiveTrack != 0) {
+        result.append("Active Track:\n");
+        result.append("   Clien Fmt Chn Session Buf  S SRate  Serv     User\n");
+        mActiveTrack->dump(buffer, SIZE);
+        result.append(buffer);
+
+        snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "In size: %d\n", mInputBytes);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Resampling: %d\n", (mResampler != 0));
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Out channel count: %d\n", mReqChannelCount);
+        result.append(buffer);
+        snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate);
+        result.append(buffer);
+
+
+    } else {
+        result.append("No record client\n");
+    }
+    write(fd, result.string(), result.size());
+
+    dumpBase(fd, args);
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::RecordThread::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    size_t framesReq = buffer->frameCount;
+    size_t framesReady = mFrameCount - mRsmpInIndex;
+    int channelCount;
+
+    if (framesReady == 0) {
+        mBytesRead = mInput->read(mRsmpInBuffer, mInputBytes);
+        if (mBytesRead < 0) {
+            LOGE("RecordThread::getNextBuffer() Error reading audio input");
+            if (mActiveTrack->mState == TrackBase::ACTIVE) {
+                // Force input into standby so that it tries to
+                // recover at next read attempt
+                mInput->standby();
+                usleep(5000);
+            }
+            buffer->raw = 0;
+            buffer->frameCount = 0;
+            return NOT_ENOUGH_DATA;
+        }
+        mRsmpInIndex = 0;
+        framesReady = mFrameCount;
+    }
+
+    if (framesReq > framesReady) {
+        framesReq = framesReady;
+    }
+
+    if (mChannelCount == 1 && mReqChannelCount == 2) {
+        channelCount = 1;
+    } else {
+        channelCount = 2;
+    }
+    buffer->raw = mRsmpInBuffer + mRsmpInIndex * channelCount;
+    buffer->frameCount = framesReq;
+    return NO_ERROR;
+}
+
+void AudioFlinger::RecordThread::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    mRsmpInIndex += buffer->frameCount;
+    buffer->frameCount = 0;
+}
+
+bool AudioFlinger::RecordThread::checkForNewParameters_l()
+{
+    bool reconfig = false;
+
+    while (!mNewParameters.isEmpty()) {
+        status_t status = NO_ERROR;
+        String8 keyValuePair = mNewParameters[0];
+        AudioParameter param = AudioParameter(keyValuePair);
+        int value;
+        int reqFormat = mFormat;
+        int reqSamplingRate = mReqSampleRate;
+        int reqChannelCount = mReqChannelCount;
+
+        if (param.getInt(String8(AudioParameter::keySamplingRate), value) == NO_ERROR) {
+            reqSamplingRate = value;
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
+            reqFormat = value;
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
+            reqChannelCount = AudioSystem::popCount(value);
+            reconfig = true;
+        }
+        if (param.getInt(String8(AudioParameter::keyFrameCount), value) == NO_ERROR) {
+            // do not accept frame count changes if tracks are open as the track buffer
+            // size depends on frame count and correct behavior would not be garantied
+            // if frame count is changed after track creation
+            if (mActiveTrack != 0) {
+                status = INVALID_OPERATION;
+            } else {
+                reconfig = true;
+            }
+        }
+        if (status == NO_ERROR) {
+            status = mInput->setParameters(keyValuePair);
+            if (status == INVALID_OPERATION) {
+               mInput->standby();
+               status = mInput->setParameters(keyValuePair);
+            }
+            if (reconfig) {
+                if (status == BAD_VALUE &&
+                    reqFormat == mInput->format() && reqFormat == AudioSystem::PCM_16_BIT &&
+                    ((int)mInput->sampleRate() <= 2 * reqSamplingRate) &&
+                    (AudioSystem::popCount(mInput->channels()) < 3) && (reqChannelCount < 3)) {
+                    status = NO_ERROR;
+                }
+                if (status == NO_ERROR) {
+                    readInputParameters();
+                    sendConfigEvent_l(AudioSystem::INPUT_CONFIG_CHANGED);
+                }
+            }
+        }
+
+        mNewParameters.removeAt(0);
+
+        mParamStatus = status;
+        mParamCond.signal();
+        mWaitWorkCV.wait(mLock);
+    }
+    return reconfig;
+}
+
+String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
+{
+    return mInput->getParameters(keys);
+}
+
+void AudioFlinger::RecordThread::audioConfigChanged_l(int event, int param) {
+    AudioSystem::OutputDescriptor desc;
+    void *param2 = 0;
+
+    switch (event) {
+    case AudioSystem::INPUT_OPENED:
+    case AudioSystem::INPUT_CONFIG_CHANGED:
+        desc.channels = mChannels;
+        desc.samplingRate = mSampleRate;
+        desc.format = mFormat;
+        desc.frameCount = mFrameCount;
+        desc.latency = 0;
+        param2 = &desc;
+        break;
+
+    case AudioSystem::INPUT_CLOSED:
+    default:
+        break;
+    }
+    mAudioFlinger->audioConfigChanged_l(event, mId, param2);
+}
+
+void AudioFlinger::RecordThread::readInputParameters()
+{
+    if (mRsmpInBuffer) delete mRsmpInBuffer;
+    if (mRsmpOutBuffer) delete mRsmpOutBuffer;
+    if (mResampler) delete mResampler;
+    mResampler = 0;
+
+    mSampleRate = mInput->sampleRate();
+    mChannels = mInput->channels();
+    mChannelCount = (uint16_t)AudioSystem::popCount(mChannels);
+    mFormat = mInput->format();
+    mFrameSize = (uint16_t)mInput->frameSize();
+    mInputBytes = mInput->bufferSize();
+    mFrameCount = mInputBytes / mFrameSize;
+    mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
+
+    if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
+    {
+        int channelCount;
+         // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
+         // stereo to mono post process as the resampler always outputs stereo.
+        if (mChannelCount == 1 && mReqChannelCount == 2) {
+            channelCount = 1;
+        } else {
+            channelCount = 2;
+        }
+        mResampler = AudioResampler::create(16, channelCount, mReqSampleRate);
+        mResampler->setSampleRate(mSampleRate);
+        mResampler->setVolume(AudioMixer::UNITY_GAIN, AudioMixer::UNITY_GAIN);
+        mRsmpOutBuffer = new int32_t[mFrameCount * 2];
+
+        // optmization: if mono to mono, alter input frame count as if we were inputing stereo samples
+        if (mChannelCount == 1 && mReqChannelCount == 1) {
+            mFrameCount >>= 1;
+        }
+
+    }
+    mRsmpInIndex = mFrameCount;
+}
+
+unsigned int AudioFlinger::RecordThread::getInputFramesLost()
+{
+    return mInput->getInputFramesLost();
+}
+
+// ----------------------------------------------------------------------------
+
+int AudioFlinger::openOutput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pLatencyMs,
+                                uint32_t flags)
+{
+    status_t status;
+    PlaybackThread *thread = NULL;
+    mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
+    uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+    uint32_t format = pFormat ? *pFormat : 0;
+    uint32_t channels = pChannels ? *pChannels : 0;
+    uint32_t latency = pLatencyMs ? *pLatencyMs : 0;
+
+    LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x",
+            pDevices ? *pDevices : 0,
+            samplingRate,
+            format,
+            channels,
+            flags);
+
+    if (pDevices == NULL || *pDevices == 0) {
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+
+    AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices,
+                                                             (int *)&format,
+                                                             &channels,
+                                                             &samplingRate,
+                                                             &status);
+    LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d",
+            output,
+            samplingRate,
+            format,
+            channels,
+            status);
+
+    mHardwareStatus = AUDIO_HW_IDLE;
+    if (output != 0) {
+        int id = nextUniqueId();
+        if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
+            (format != AudioSystem::PCM_16_BIT) ||
+            (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
+            thread = new DirectOutputThread(this, output, id, *pDevices);
+            LOGV("openOutput() created direct output: ID %d thread %p", id, thread);
+        } else {
+            thread = new MixerThread(this, output, id, *pDevices);
+            LOGV("openOutput() created mixer output: ID %d thread %p", id, thread);
+
+#ifdef LVMX
+            unsigned bitsPerSample =
+                (format == AudioSystem::PCM_16_BIT) ? 16 :
+                    ((format == AudioSystem::PCM_8_BIT) ? 8 : 0);
+            unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1;
+            int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id());
+
+            LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount);
+            LifeVibes::setDevice(audioOutputType, *pDevices);
+#endif
+
+        }
+        mPlaybackThreads.add(id, thread);
+
+        if (pSamplingRate) *pSamplingRate = samplingRate;
+        if (pFormat) *pFormat = format;
+        if (pChannels) *pChannels = channels;
+        if (pLatencyMs) *pLatencyMs = thread->latency();
+
+        // notify client processes of the new output creation
+        thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
+        return id;
+    }
+
+    return 0;
+}
+
+int AudioFlinger::openDuplicateOutput(int output1, int output2)
+{
+    Mutex::Autolock _l(mLock);
+    MixerThread *thread1 = checkMixerThread_l(output1);
+    MixerThread *thread2 = checkMixerThread_l(output2);
+
+    if (thread1 == NULL || thread2 == NULL) {
+        LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2);
+        return 0;
+    }
+
+    int id = nextUniqueId();
+    DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
+    thread->addOutputTrack(thread2);
+    mPlaybackThreads.add(id, thread);
+    // notify client processes of the new output creation
+    thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED);
+    return id;
+}
+
+status_t AudioFlinger::closeOutput(int output)
+{
+    // keep strong reference on the playback thread so that
+    // it is not destroyed while exit() is executed
+    sp <PlaybackThread> thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            return BAD_VALUE;
+        }
+
+        LOGV("closeOutput() %d", output);
+
+        if (thread->type() == PlaybackThread::MIXER) {
+            for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+                if (mPlaybackThreads.valueAt(i)->type() == PlaybackThread::DUPLICATING) {
+                    DuplicatingThread *dupThread = (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
+                    dupThread->removeOutputTrack((MixerThread *)thread.get());
+                }
+            }
+        }
+        void *param2 = 0;
+        audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
+        mPlaybackThreads.removeItem(output);
+    }
+    thread->exit();
+
+    if (thread->type() != PlaybackThread::DUPLICATING) {
+        mAudioHardware->closeOutputStream(thread->getOutput());
+    }
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::suspendOutput(int output)
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+
+    if (thread == NULL) {
+        return BAD_VALUE;
+    }
+
+    LOGV("suspendOutput() %d", output);
+    thread->suspend();
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::restoreOutput(int output)
+{
+    Mutex::Autolock _l(mLock);
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+
+    if (thread == NULL) {
+        return BAD_VALUE;
+    }
+
+    LOGV("restoreOutput() %d", output);
+
+    thread->restore();
+
+    return NO_ERROR;
+}
+
+int AudioFlinger::openInput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t acoustics)
+{
+    status_t status;
+    RecordThread *thread = NULL;
+    uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0;
+    uint32_t format = pFormat ? *pFormat : 0;
+    uint32_t channels = pChannels ? *pChannels : 0;
+    uint32_t reqSamplingRate = samplingRate;
+    uint32_t reqFormat = format;
+    uint32_t reqChannels = channels;
+
+    if (pDevices == NULL || *pDevices == 0) {
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+
+    AudioStreamIn *input = mAudioHardware->openInputStream(*pDevices,
+                                                             (int *)&format,
+                                                             &channels,
+                                                             &samplingRate,
+                                                             &status,
+                                                             (AudioSystem::audio_in_acoustics)acoustics);
+    LOGV("openInput() openInputStream returned input %p, SamplingRate %d, Format %d, Channels %x, acoustics %x, status %d",
+            input,
+            samplingRate,
+            format,
+            channels,
+            acoustics,
+            status);
+
+    // If the input could not be opened with the requested parameters and we can handle the conversion internally,
+    // try to open again with the proposed parameters. The AudioFlinger can resample the input and do mono to stereo
+    // or stereo to mono conversions on 16 bit PCM inputs.
+    if (input == 0 && status == BAD_VALUE &&
+        reqFormat == format && format == AudioSystem::PCM_16_BIT &&
+        (samplingRate <= 2 * reqSamplingRate) &&
+        (AudioSystem::popCount(channels) < 3) && (AudioSystem::popCount(reqChannels) < 3)) {
+        LOGV("openInput() reopening with proposed sampling rate and channels");
+        input = mAudioHardware->openInputStream(*pDevices,
+                                                 (int *)&format,
+                                                 &channels,
+                                                 &samplingRate,
+                                                 &status,
+                                                 (AudioSystem::audio_in_acoustics)acoustics);
+    }
+
+    if (input != 0) {
+        int id = nextUniqueId();
+         // Start record thread
+        thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
+        mRecordThreads.add(id, thread);
+        LOGV("openInput() created record thread: ID %d thread %p", id, thread);
+        if (pSamplingRate) *pSamplingRate = reqSamplingRate;
+        if (pFormat) *pFormat = format;
+        if (pChannels) *pChannels = reqChannels;
+
+        input->standby();
+
+        // notify client processes of the new input creation
+        thread->audioConfigChanged_l(AudioSystem::INPUT_OPENED);
+        return id;
+    }
+
+    return 0;
+}
+
+status_t AudioFlinger::closeInput(int input)
+{
+    // keep strong reference on the record thread so that
+    // it is not destroyed while exit() is executed
+    sp <RecordThread> thread;
+    {
+        Mutex::Autolock _l(mLock);
+        thread = checkRecordThread_l(input);
+        if (thread == NULL) {
+            return BAD_VALUE;
+        }
+
+        LOGV("closeInput() %d", input);
+        void *param2 = 0;
+        audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
+        mRecordThreads.removeItem(input);
+    }
+    thread->exit();
+
+    mAudioHardware->closeInputStream(thread->getInput());
+
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::setStreamOutput(uint32_t stream, int output)
+{
+    Mutex::Autolock _l(mLock);
+    MixerThread *dstThread = checkMixerThread_l(output);
+    if (dstThread == NULL) {
+        LOGW("setStreamOutput() bad output id %d", output);
+        return BAD_VALUE;
+    }
+
+    LOGV("setStreamOutput() stream %d to output %d", stream, output);
+    audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream);
+
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+        if (thread != dstThread &&
+            thread->type() != PlaybackThread::DIRECT) {
+            MixerThread *srcThread = (MixerThread *)thread;
+            srcThread->invalidateTracks(stream);
+        }
+    }
+
+    return NO_ERROR;
+}
+
+
+int AudioFlinger::newAudioSessionId()
+{
+    return nextUniqueId();
+}
+
+// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const
+{
+    PlaybackThread *thread = NULL;
+    if (mPlaybackThreads.indexOfKey(output) >= 0) {
+        thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get();
+    }
+    return thread;
+}
+
+// checkMixerThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const
+{
+    PlaybackThread *thread = checkPlaybackThread_l(output);
+    if (thread != NULL) {
+        if (thread->type() == PlaybackThread::DIRECT) {
+            thread = NULL;
+        }
+    }
+    return (MixerThread *)thread;
+}
+
+// checkRecordThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(int input) const
+{
+    RecordThread *thread = NULL;
+    if (mRecordThreads.indexOfKey(input) >= 0) {
+        thread = (RecordThread *)mRecordThreads.valueFor(input).get();
+    }
+    return thread;
+}
+
+int AudioFlinger::nextUniqueId()
+{
+    return android_atomic_inc(&mNextUniqueId);
+}
+
+// ----------------------------------------------------------------------------
+//  Effect management
+// ----------------------------------------------------------------------------
+
+
+status_t AudioFlinger::loadEffectLibrary(const char *libPath, int *handle)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    // only allow libraries loaded from /system/lib/soundfx for now
+    if (strncmp(gEffectLibPath, libPath, strlen(gEffectLibPath)) != 0) {
+        return PERMISSION_DENIED;
+    }
+
+    Mutex::Autolock _l(mLock);
+    return EffectLoadLibrary(libPath, handle);
+}
+
+status_t AudioFlinger::unloadEffectLibrary(int handle)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+
+    Mutex::Autolock _l(mLock);
+    return EffectUnloadLibrary(handle);
+}
+
+status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects)
+{
+    Mutex::Autolock _l(mLock);
+    return EffectQueryNumberEffects(numEffects);
+}
+
+status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
+{
+    Mutex::Autolock _l(mLock);
+    return EffectQueryEffect(index, descriptor);
+}
+
+status_t AudioFlinger::getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor)
+{
+    Mutex::Autolock _l(mLock);
+    return EffectGetDescriptor(pUuid, descriptor);
+}
+
+
+// this UUID must match the one defined in media/libeffects/EffectVisualizer.cpp
+static const effect_uuid_t VISUALIZATION_UUID_ =
+    {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+
+sp<IEffect> AudioFlinger::createEffect(pid_t pid,
+        effect_descriptor_t *pDesc,
+        const sp<IEffectClient>& effectClient,
+        int32_t priority,
+        int output,
+        int sessionId,
+        status_t *status,
+        int *id,
+        int *enabled)
+{
+    status_t lStatus = NO_ERROR;
+    sp<EffectHandle> handle;
+    effect_interface_t itfe;
+    effect_descriptor_t desc;
+    sp<Client> client;
+    wp<Client> wclient;
+
+    LOGV("createEffect pid %d, client %p, priority %d, sessionId %d, output %d",
+            pid, effectClient.get(), priority, sessionId, output);
+
+    if (pDesc == NULL) {
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
+
+    {
+        Mutex::Autolock _l(mLock);
+
+        // check recording permission for visualizer
+        if (memcmp(&pDesc->type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0 ||
+            memcmp(&pDesc->uuid, &VISUALIZATION_UUID_, sizeof(effect_uuid_t)) == 0) {
+            if (!recordingAllowed()) {
+                lStatus = PERMISSION_DENIED;
+                goto Exit;
+            }
+        }
+
+        if (!EffectIsNullUuid(&pDesc->uuid)) {
+            // if uuid is specified, request effect descriptor
+            lStatus = EffectGetDescriptor(&pDesc->uuid, &desc);
+            if (lStatus < 0) {
+                LOGW("createEffect() error %d from EffectGetDescriptor", lStatus);
+                goto Exit;
+            }
+        } else {
+            // if uuid is not specified, look for an available implementation
+            // of the required type in effect factory
+            if (EffectIsNullUuid(&pDesc->type)) {
+                LOGW("createEffect() no effect type");
+                lStatus = BAD_VALUE;
+                goto Exit;
+            }
+            uint32_t numEffects = 0;
+            effect_descriptor_t d;
+            bool found = false;
+
+            lStatus = EffectQueryNumberEffects(&numEffects);
+            if (lStatus < 0) {
+                LOGW("createEffect() error %d from EffectQueryNumberEffects", lStatus);
+                goto Exit;
+            }
+            for (uint32_t i = 0; i < numEffects; i++) {
+                lStatus = EffectQueryEffect(i, &desc);
+                if (lStatus < 0) {
+                    LOGW("createEffect() error %d from EffectQueryEffect", lStatus);
+                    continue;
+                }
+                if (memcmp(&desc.type, &pDesc->type, sizeof(effect_uuid_t)) == 0) {
+                    // If matching type found save effect descriptor. If the session is
+                    // 0 and the effect is not auxiliary, continue enumeration in case
+                    // an auxiliary version of this effect type is available
+                    found = true;
+                    memcpy(&d, &desc, sizeof(effect_descriptor_t));
+                    if (sessionId != AudioSystem::SESSION_OUTPUT_MIX ||
+                            (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+                        break;
+                    }
+                }
+            }
+            if (!found) {
+                lStatus = BAD_VALUE;
+                LOGW("createEffect() effect not found");
+                goto Exit;
+            }
+            // For same effect type, chose auxiliary version over insert version if
+            // connect to output mix (Compliance to OpenSL ES)
+            if (sessionId == AudioSystem::SESSION_OUTPUT_MIX &&
+                    (d.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_AUXILIARY) {
+                memcpy(&desc, &d, sizeof(effect_descriptor_t));
+            }
+        }
+
+        // Do not allow auxiliary effects on a session different from 0 (output mix)
+        if (sessionId != AudioSystem::SESSION_OUTPUT_MIX &&
+             (desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+            lStatus = INVALID_OPERATION;
+            goto Exit;
+        }
+
+        // Session AudioSystem::SESSION_OUTPUT_STAGE is reserved for output stage effects
+        // that can only be created by audio policy manager (running in same process)
+        if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE &&
+                getpid() != IPCThreadState::self()->getCallingPid()) {
+            lStatus = INVALID_OPERATION;
+            goto Exit;
+        }
+
+        // return effect descriptor
+        memcpy(pDesc, &desc, sizeof(effect_descriptor_t));
+
+        // If output is not specified try to find a matching audio session ID in one of the
+        // output threads.
+        // TODO: allow attachment of effect to inputs
+        if (output == 0) {
+            if (sessionId == AudioSystem::SESSION_OUTPUT_STAGE) {
+                // output must be specified by AudioPolicyManager when using session
+                // AudioSystem::SESSION_OUTPUT_STAGE
+                lStatus = BAD_VALUE;
+                goto Exit;
+            } else if (sessionId == AudioSystem::SESSION_OUTPUT_MIX) {
+                output = AudioSystem::getOutputForEffect(&desc);
+                LOGV("createEffect() got output %d for effect %s", output, desc.name);
+            } else {
+                 // look for the thread where the specified audio session is present
+                for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+                    if (mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId) != 0) {
+                        output = mPlaybackThreads.keyAt(i);
+                        break;
+                    }
+                }
+                // If no output thread contains the requested session ID, default to
+                // first output. The effect chain will be moved to the correct output
+                // thread when a track with the same session ID is created
+                if (output == 0 && mPlaybackThreads.size()) {
+                    output = mPlaybackThreads.keyAt(0);
+                }
+            }
+        }
+        PlaybackThread *thread = checkPlaybackThread_l(output);
+        if (thread == NULL) {
+            LOGE("createEffect() unknown output thread");
+            lStatus = BAD_VALUE;
+            goto Exit;
+        }
+
+        wclient = mClients.valueFor(pid);
+
+        if (wclient != NULL) {
+            client = wclient.promote();
+        } else {
+            client = new Client(this, pid);
+            mClients.add(pid, client);
+        }
+
+        // create effect on selected output trhead
+        handle = thread->createEffect_l(client, effectClient, priority, sessionId,
+                &desc, enabled, &lStatus);
+        if (handle != 0 && id != NULL) {
+            *id = handle->id();
+        }
+    }
+
+Exit:
+    if(status) {
+        *status = lStatus;
+    }
+    return handle;
+}
+
+status_t AudioFlinger::moveEffects(int session, int srcOutput, int dstOutput)
+{
+    LOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
+            session, srcOutput, dstOutput);
+    Mutex::Autolock _l(mLock);
+    if (srcOutput == dstOutput) {
+        LOGW("moveEffects() same dst and src outputs %d", dstOutput);
+        return NO_ERROR;
+    }
+    PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
+    if (srcThread == NULL) {
+        LOGW("moveEffects() bad srcOutput %d", srcOutput);
+        return BAD_VALUE;
+    }
+    PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
+    if (dstThread == NULL) {
+        LOGW("moveEffects() bad dstOutput %d", dstOutput);
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _dl(dstThread->mLock);
+    Mutex::Autolock _sl(srcThread->mLock);
+    moveEffectChain_l(session, srcThread, dstThread, false);
+
+    return NO_ERROR;
+}
+
+// moveEffectChain_l mustbe called with both srcThread and dstThread mLocks held
+status_t AudioFlinger::moveEffectChain_l(int session,
+                                   AudioFlinger::PlaybackThread *srcThread,
+                                   AudioFlinger::PlaybackThread *dstThread,
+                                   bool reRegister)
+{
+    LOGV("moveEffectChain_l() session %d from thread %p to thread %p",
+            session, srcThread, dstThread);
+
+    sp<EffectChain> chain = srcThread->getEffectChain_l(session);
+    if (chain == 0) {
+        LOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
+                session, srcThread);
+        return INVALID_OPERATION;
+    }
+
+    // remove chain first. This is useful only if reconfiguring effect chain on same output thread,
+    // so that a new chain is created with correct parameters when first effect is added. This is
+    // otherwise unecessary as removeEffect_l() will remove the chain when last effect is
+    // removed.
+    srcThread->removeEffectChain_l(chain);
+
+    // transfer all effects one by one so that new effect chain is created on new thread with
+    // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
+    int dstOutput = dstThread->id();
+    sp<EffectChain> dstChain;
+    uint32_t strategy;
+    sp<EffectModule> effect = chain->getEffectFromId_l(0);
+    while (effect != 0) {
+        srcThread->removeEffect_l(effect);
+        dstThread->addEffect_l(effect);
+        // if the move request is not received from audio policy manager, the effect must be
+        // re-registered with the new strategy and output
+        if (dstChain == 0) {
+            dstChain = effect->chain().promote();
+            if (dstChain == 0) {
+                LOGW("moveEffectChain_l() cannot get chain from effect %p", effect.get());
+                srcThread->addEffect_l(effect);
+                return NO_INIT;
+            }
+            strategy = dstChain->strategy();
+        }
+        if (reRegister) {
+            AudioSystem::unregisterEffect(effect->id());
+            AudioSystem::registerEffect(&effect->desc(),
+                                        dstOutput,
+                                        strategy,
+                                        session,
+                                        effect->id());
+        }
+        effect = chain->getEffectFromId_l(0);
+    }
+
+    return NO_ERROR;
+}
+
+// PlaybackThread::createEffect_l() must be called with AudioFlinger::mLock held
+sp<AudioFlinger::EffectHandle> AudioFlinger::PlaybackThread::createEffect_l(
+        const sp<AudioFlinger::Client>& client,
+        const sp<IEffectClient>& effectClient,
+        int32_t priority,
+        int sessionId,
+        effect_descriptor_t *desc,
+        int *enabled,
+        status_t *status
+        )
+{
+    sp<EffectModule> effect;
+    sp<EffectHandle> handle;
+    status_t lStatus;
+    sp<Track> track;
+    sp<EffectChain> chain;
+    bool chainCreated = false;
+    bool effectCreated = false;
+    bool effectRegistered = false;
+
+    if (mOutput == 0) {
+        LOGW("createEffect_l() Audio driver not initialized.");
+        lStatus = NO_INIT;
+        goto Exit;
+    }
+
+    // Do not allow auxiliary effect on session other than 0
+    if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY &&
+        sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
+        LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
+                desc->name, sessionId);
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
+
+    // Do not allow effects with session ID 0 on direct output or duplicating threads
+    // TODO: add rule for hw accelerated effects on direct outputs with non PCM format
+    if (sessionId == AudioSystem::SESSION_OUTPUT_MIX && mType != MIXER) {
+        LOGW("createEffect_l() Cannot add auxiliary effect %s to session %d",
+                desc->name, sessionId);
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
+
+    LOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
+
+    { // scope for mLock
+        Mutex::Autolock _l(mLock);
+
+        // check for existing effect chain with the requested audio session
+        chain = getEffectChain_l(sessionId);
+        if (chain == 0) {
+            // create a new chain for this session
+            LOGV("createEffect_l() new effect chain for session %d", sessionId);
+            chain = new EffectChain(this, sessionId);
+            addEffectChain_l(chain);
+            chain->setStrategy(getStrategyForSession_l(sessionId));
+            chainCreated = true;
+        } else {
+            effect = chain->getEffectFromDesc_l(desc);
+        }
+
+        LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
+
+        if (effect == 0) {
+            int id = mAudioFlinger->nextUniqueId();
+            // Check CPU and memory usage
+            lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
+            if (lStatus != NO_ERROR) {
+                goto Exit;
+            }
+            effectRegistered = true;
+            // create a new effect module if none present in the chain
+            effect = new EffectModule(this, chain, desc, id, sessionId);
+            lStatus = effect->status();
+            if (lStatus != NO_ERROR) {
+                goto Exit;
+            }
+            lStatus = chain->addEffect_l(effect);
+            if (lStatus != NO_ERROR) {
+                goto Exit;
+            }
+            effectCreated = true;
+
+            effect->setDevice(mDevice);
+            effect->setMode(mAudioFlinger->getMode());
+        }
+        // create effect handle and connect it to effect module
+        handle = new EffectHandle(effect, client, effectClient, priority);
+        lStatus = effect->addHandle(handle);
+        if (enabled) {
+            *enabled = (int)effect->isEnabled();
+        }
+    }
+
+Exit:
+    if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
+        Mutex::Autolock _l(mLock);
+        if (effectCreated) {
+            chain->removeEffect_l(effect);
+        }
+        if (effectRegistered) {
+            AudioSystem::unregisterEffect(effect->id());
+        }
+        if (chainCreated) {
+            removeEffectChain_l(chain);
+        }
+        handle.clear();
+    }
+
+    if(status) {
+        *status = lStatus;
+    }
+    return handle;
+}
+
+// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
+// PlaybackThread::mLock held
+status_t AudioFlinger::PlaybackThread::addEffect_l(const sp<EffectModule>& effect)
+{
+    // check for existing effect chain with the requested audio session
+    int sessionId = effect->sessionId();
+    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    bool chainCreated = false;
+
+    if (chain == 0) {
+        // create a new chain for this session
+        LOGV("addEffect_l() new effect chain for session %d", sessionId);
+        chain = new EffectChain(this, sessionId);
+        addEffectChain_l(chain);
+        chain->setStrategy(getStrategyForSession_l(sessionId));
+        chainCreated = true;
+    }
+    LOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
+
+    if (chain->getEffectFromId_l(effect->id()) != 0) {
+        LOGW("addEffect_l() %p effect %s already present in chain %p",
+                this, effect->desc().name, chain.get());
+        return BAD_VALUE;
+    }
+
+    status_t status = chain->addEffect_l(effect);
+    if (status != NO_ERROR) {
+        if (chainCreated) {
+            removeEffectChain_l(chain);
+        }
+        return status;
+    }
+
+    effect->setDevice(mDevice);
+    effect->setMode(mAudioFlinger->getMode());
+    return NO_ERROR;
+}
+
+void AudioFlinger::PlaybackThread::removeEffect_l(const sp<EffectModule>& effect) {
+
+    LOGV("removeEffect_l() %p effect %p", this, effect.get());
+    effect_descriptor_t desc = effect->desc();
+    if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+        detachAuxEffect_l(effect->id());
+    }
+
+    sp<EffectChain> chain = effect->chain().promote();
+    if (chain != 0) {
+        // remove effect chain if removing last effect
+        if (chain->removeEffect_l(effect) == 0) {
+            removeEffectChain_l(chain);
+        }
+    } else {
+        LOGW("removeEffect_l() %p cannot promote chain for effect %p", this, effect.get());
+    }
+}
+
+void AudioFlinger::PlaybackThread::disconnectEffect(const sp<EffectModule>& effect,
+                                                    const wp<EffectHandle>& handle) {
+    Mutex::Autolock _l(mLock);
+    LOGV("disconnectEffect() %p effect %p", this, effect.get());
+    // delete the effect module if removing last handle on it
+    if (effect->removeHandle(handle) == 0) {
+        removeEffect_l(effect);
+        AudioSystem::unregisterEffect(effect->id());
+    }
+}
+
+status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
+{
+    int session = chain->sessionId();
+    int16_t *buffer = mMixBuffer;
+    bool ownsBuffer = false;
+
+    LOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
+    if (session > 0) {
+        // Only one effect chain can be present in direct output thread and it uses
+        // the mix buffer as input
+        if (mType != DIRECT) {
+            size_t numSamples = mFrameCount * mChannelCount;
+            buffer = new int16_t[numSamples];
+            memset(buffer, 0, numSamples * sizeof(int16_t));
+            LOGV("addEffectChain_l() creating new input buffer %p session %d", buffer, session);
+            ownsBuffer = true;
+        }
+
+        // Attach all tracks with same session ID to this chain.
+        for (size_t i = 0; i < mTracks.size(); ++i) {
+            sp<Track> track = mTracks[i];
+            if (session == track->sessionId()) {
+                LOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p", track.get(), buffer);
+                track->setMainBuffer(buffer);
+            }
+        }
+
+        // indicate all active tracks in the chain
+        for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
+            sp<Track> track = mActiveTracks[i].promote();
+            if (track == 0) continue;
+            if (session == track->sessionId()) {
+                LOGV("addEffectChain_l() activating track %p on session %d", track.get(), session);
+                chain->startTrack();
+            }
+        }
+    }
+
+    chain->setInBuffer(buffer, ownsBuffer);
+    chain->setOutBuffer(mMixBuffer);
+    // Effect chain for session AudioSystem::SESSION_OUTPUT_STAGE is inserted at end of effect
+    // chains list in order to be processed last as it contains output stage effects
+    // Effect chain for session AudioSystem::SESSION_OUTPUT_MIX is inserted before
+    // session AudioSystem::SESSION_OUTPUT_STAGE to be processed
+    // after track specific effects and before output stage
+    // It is therefore mandatory that AudioSystem::SESSION_OUTPUT_MIX == 0 and
+    // that AudioSystem::SESSION_OUTPUT_STAGE < AudioSystem::SESSION_OUTPUT_MIX
+    // Effect chain for other sessions are inserted at beginning of effect
+    // chains list to be processed before output mix effects. Relative order between other
+    // sessions is not important
+    size_t size = mEffectChains.size();
+    size_t i = 0;
+    for (i = 0; i < size; i++) {
+        if (mEffectChains[i]->sessionId() < session) break;
+    }
+    mEffectChains.insertAt(chain, i);
+
+    return NO_ERROR;
+}
+
+size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
+{
+    int session = chain->sessionId();
+
+    LOGV("removeEffectChain_l() %p from thread %p for session %d", chain.get(), this, session);
+
+    for (size_t i = 0; i < mEffectChains.size(); i++) {
+        if (chain == mEffectChains[i]) {
+            mEffectChains.removeAt(i);
+            // detach all tracks with same session ID from this chain
+            for (size_t i = 0; i < mTracks.size(); ++i) {
+                sp<Track> track = mTracks[i];
+                if (session == track->sessionId()) {
+                    track->setMainBuffer(mMixBuffer);
+                }
+            }
+            break;
+        }
+    }
+    return mEffectChains.size();
+}
+
+void AudioFlinger::PlaybackThread::lockEffectChains_l(
+        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
+{
+    effectChains = mEffectChains;
+    for (size_t i = 0; i < mEffectChains.size(); i++) {
+        mEffectChains[i]->lock();
+    }
+}
+
+void AudioFlinger::PlaybackThread::unlockEffectChains(
+        Vector<sp <AudioFlinger::EffectChain> >& effectChains)
+{
+    for (size_t i = 0; i < effectChains.size(); i++) {
+        effectChains[i]->unlock();
+    }
+}
+
+
+sp<AudioFlinger::EffectModule> AudioFlinger::PlaybackThread::getEffect_l(int sessionId, int effectId)
+{
+    sp<EffectModule> effect;
+
+    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    if (chain != 0) {
+        effect = chain->getEffectFromId_l(effectId);
+    }
+    return effect;
+}
+
+status_t AudioFlinger::PlaybackThread::attachAuxEffect(
+        const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
+{
+    Mutex::Autolock _l(mLock);
+    return attachAuxEffect_l(track, EffectId);
+}
+
+status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
+        const sp<AudioFlinger::PlaybackThread::Track> track, int EffectId)
+{
+    status_t status = NO_ERROR;
+
+    if (EffectId == 0) {
+        track->setAuxBuffer(0, NULL);
+    } else {
+        // Auxiliary effects are always in audio session AudioSystem::SESSION_OUTPUT_MIX
+        sp<EffectModule> effect = getEffect_l(AudioSystem::SESSION_OUTPUT_MIX, EffectId);
+        if (effect != 0) {
+            if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+                track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
+            } else {
+                status = INVALID_OPERATION;
+            }
+        } else {
+            status = BAD_VALUE;
+        }
+    }
+    return status;
+}
+
+void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
+{
+     for (size_t i = 0; i < mTracks.size(); ++i) {
+        sp<Track> track = mTracks[i];
+        if (track->auxEffectId() == effectId) {
+            attachAuxEffect_l(track, 0);
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+//  EffectModule implementation
+// ----------------------------------------------------------------------------
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::EffectModule"
+
+AudioFlinger::EffectModule::EffectModule(const wp<ThreadBase>& wThread,
+                                        const wp<AudioFlinger::EffectChain>& chain,
+                                        effect_descriptor_t *desc,
+                                        int id,
+                                        int sessionId)
+    : mThread(wThread), mChain(chain), mId(id), mSessionId(sessionId), mEffectInterface(NULL),
+      mStatus(NO_INIT), mState(IDLE)
+{
+    LOGV("Constructor %p", this);
+    int lStatus;
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread == 0) {
+        return;
+    }
+    PlaybackThread *p = (PlaybackThread *)thread.get();
+
+    memcpy(&mDescriptor, desc, sizeof(effect_descriptor_t));
+
+    // create effect engine from effect factory
+    mStatus = EffectCreate(&desc->uuid, sessionId, p->id(), &mEffectInterface);
+
+    if (mStatus != NO_ERROR) {
+        return;
+    }
+    lStatus = init();
+    if (lStatus < 0) {
+        mStatus = lStatus;
+        goto Error;
+    }
+
+    LOGV("Constructor success name %s, Interface %p", mDescriptor.name, mEffectInterface);
+    return;
+Error:
+    EffectRelease(mEffectInterface);
+    mEffectInterface = NULL;
+    LOGV("Constructor Error %d", mStatus);
+}
+
+AudioFlinger::EffectModule::~EffectModule()
+{
+    LOGV("Destructor %p", this);
+    if (mEffectInterface != NULL) {
+        // release effect engine
+        EffectRelease(mEffectInterface);
+    }
+}
+
+status_t AudioFlinger::EffectModule::addHandle(sp<EffectHandle>& handle)
+{
+    status_t status;
+
+    Mutex::Autolock _l(mLock);
+    // First handle in mHandles has highest priority and controls the effect module
+    int priority = handle->priority();
+    size_t size = mHandles.size();
+    sp<EffectHandle> h;
+    size_t i;
+    for (i = 0; i < size; i++) {
+        h = mHandles[i].promote();
+        if (h == 0) continue;
+        if (h->priority() <= priority) break;
+    }
+    // if inserted in first place, move effect control from previous owner to this handle
+    if (i == 0) {
+        if (h != 0) {
+            h->setControl(false, true);
+        }
+        handle->setControl(true, false);
+        status = NO_ERROR;
+    } else {
+        status = ALREADY_EXISTS;
+    }
+    mHandles.insertAt(handle, i);
+    return status;
+}
+
+size_t AudioFlinger::EffectModule::removeHandle(const wp<EffectHandle>& handle)
+{
+    Mutex::Autolock _l(mLock);
+    size_t size = mHandles.size();
+    size_t i;
+    for (i = 0; i < size; i++) {
+        if (mHandles[i] == handle) break;
+    }
+    if (i == size) {
+        return size;
+    }
+    mHandles.removeAt(i);
+    size = mHandles.size();
+    // if removed from first place, move effect control from this handle to next in line
+    if (i == 0 && size != 0) {
+        sp<EffectHandle> h = mHandles[0].promote();
+        if (h != 0) {
+            h->setControl(true, true);
+        }
+    }
+
+    return size;
+}
+
+void AudioFlinger::EffectModule::disconnect(const wp<EffectHandle>& handle)
+{
+    // keep a strong reference on this EffectModule to avoid calling the
+    // destructor before we exit
+    sp<EffectModule> keep(this);
+    {
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            playbackThread->disconnectEffect(keep, handle);
+        }
+    }
+}
+
+void AudioFlinger::EffectModule::updateState() {
+    Mutex::Autolock _l(mLock);
+
+    switch (mState) {
+    case RESTART:
+        reset_l();
+        // FALL THROUGH
+
+    case STARTING:
+        // clear auxiliary effect input buffer for next accumulation
+        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+            memset(mConfig.inputCfg.buffer.raw,
+                   0,
+                   mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
+        }
+        start_l();
+        mState = ACTIVE;
+        break;
+    case STOPPING:
+        stop_l();
+        mDisableWaitCnt = mMaxDisableWaitCnt;
+        mState = STOPPED;
+        break;
+    case STOPPED:
+        // mDisableWaitCnt is forced to 1 by process() when the engine indicates the end of the
+        // turn off sequence.
+        if (--mDisableWaitCnt == 0) {
+            reset_l();
+            mState = IDLE;
+        }
+        break;
+    default: //IDLE , ACTIVE
+        break;
+    }
+}
+
+void AudioFlinger::EffectModule::process()
+{
+    Mutex::Autolock _l(mLock);
+
+    if (mEffectInterface == NULL ||
+            mConfig.inputCfg.buffer.raw == NULL ||
+            mConfig.outputCfg.buffer.raw == NULL) {
+        return;
+    }
+
+    if (mState == ACTIVE || mState == STOPPING || mState == STOPPED) {
+        // do 32 bit to 16 bit conversion for auxiliary effect input buffer
+        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+            AudioMixer::ditherAndClamp(mConfig.inputCfg.buffer.s32,
+                                        mConfig.inputCfg.buffer.s32,
+                                        mConfig.inputCfg.buffer.frameCount/2);
+        }
+
+        // do the actual processing in the effect engine
+        int ret = (*mEffectInterface)->process(mEffectInterface,
+                                               &mConfig.inputCfg.buffer,
+                                               &mConfig.outputCfg.buffer);
+
+        // force transition to IDLE state when engine is ready
+        if (mState == STOPPED && ret == -ENODATA) {
+            mDisableWaitCnt = 1;
+        }
+
+        // clear auxiliary effect input buffer for next accumulation
+        if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+            memset(mConfig.inputCfg.buffer.raw, 0, mConfig.inputCfg.buffer.frameCount*sizeof(int32_t));
+        }
+    } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
+                mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw){
+        // If an insert effect is idle and input buffer is different from output buffer, copy input to
+        // output
+        sp<EffectChain> chain = mChain.promote();
+        if (chain != 0 && chain->activeTracks() != 0) {
+            size_t size = mConfig.inputCfg.buffer.frameCount * sizeof(int16_t);
+            if (mConfig.inputCfg.channels == CHANNEL_STEREO) {
+                size *= 2;
+            }
+            memcpy(mConfig.outputCfg.buffer.raw, mConfig.inputCfg.buffer.raw, size);
+        }
+    }
+}
+
+void AudioFlinger::EffectModule::reset_l()
+{
+    if (mEffectInterface == NULL) {
+        return;
+    }
+    (*mEffectInterface)->command(mEffectInterface, EFFECT_CMD_RESET, 0, NULL, 0, NULL);
+}
+
+status_t AudioFlinger::EffectModule::configure()
+{
+    uint32_t channels;
+    if (mEffectInterface == NULL) {
+        return NO_INIT;
+    }
+
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread == 0) {
+        return DEAD_OBJECT;
+    }
+
+    // TODO: handle configuration of effects replacing track process
+    if (thread->channelCount() == 1) {
+        channels = CHANNEL_MONO;
+    } else {
+        channels = CHANNEL_STEREO;
+    }
+
+    if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+        mConfig.inputCfg.channels = CHANNEL_MONO;
+    } else {
+        mConfig.inputCfg.channels = channels;
+    }
+    mConfig.outputCfg.channels = channels;
+    mConfig.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+    mConfig.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+    mConfig.inputCfg.samplingRate = thread->sampleRate();
+    mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
+    mConfig.inputCfg.bufferProvider.cookie = NULL;
+    mConfig.inputCfg.bufferProvider.getBuffer = NULL;
+    mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
+    mConfig.outputCfg.bufferProvider.cookie = NULL;
+    mConfig.outputCfg.bufferProvider.getBuffer = NULL;
+    mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
+    mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+    // Insert effect:
+    // - in session AudioSystem::SESSION_OUTPUT_MIX or AudioSystem::SESSION_OUTPUT_STAGE,
+    // always overwrites output buffer: input buffer == output buffer
+    // - in other sessions:
+    //      last effect in the chain accumulates in output buffer: input buffer != output buffer
+    //      other effect: overwrites output buffer: input buffer == output buffer
+    // Auxiliary effect:
+    //      accumulates in output buffer: input buffer != output buffer
+    // Therefore: accumulate <=> input buffer != output buffer
+    if (mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
+        mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+    } else {
+        mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_WRITE;
+    }
+    mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
+    mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
+    mConfig.inputCfg.buffer.frameCount = thread->frameCount();
+    mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
+
+    LOGV("configure() %p thread %p buffer %p framecount %d",
+            this, thread.get(), mConfig.inputCfg.buffer.raw, mConfig.inputCfg.buffer.frameCount);
+
+    status_t cmdStatus;
+    uint32_t size = sizeof(int);
+    status_t status = (*mEffectInterface)->command(mEffectInterface,
+                                                   EFFECT_CMD_CONFIGURE,
+                                                   sizeof(effect_config_t),
+                                                   &mConfig,
+                                                   &size,
+                                                   &cmdStatus);
+    if (status == 0) {
+        status = cmdStatus;
+    }
+
+    mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
+            (1000 * mConfig.outputCfg.buffer.frameCount);
+
+    return status;
+}
+
+status_t AudioFlinger::EffectModule::init()
+{
+    Mutex::Autolock _l(mLock);
+    if (mEffectInterface == NULL) {
+        return NO_INIT;
+    }
+    status_t cmdStatus;
+    uint32_t size = sizeof(status_t);
+    status_t status = (*mEffectInterface)->command(mEffectInterface,
+                                                   EFFECT_CMD_INIT,
+                                                   0,
+                                                   NULL,
+                                                   &size,
+                                                   &cmdStatus);
+    if (status == 0) {
+        status = cmdStatus;
+    }
+    return status;
+}
+
+status_t AudioFlinger::EffectModule::start_l()
+{
+    if (mEffectInterface == NULL) {
+        return NO_INIT;
+    }
+    status_t cmdStatus;
+    uint32_t size = sizeof(status_t);
+    status_t status = (*mEffectInterface)->command(mEffectInterface,
+                                                   EFFECT_CMD_ENABLE,
+                                                   0,
+                                                   NULL,
+                                                   &size,
+                                                   &cmdStatus);
+    if (status == 0) {
+        status = cmdStatus;
+    }
+    return status;
+}
+
+status_t AudioFlinger::EffectModule::stop_l()
+{
+    if (mEffectInterface == NULL) {
+        return NO_INIT;
+    }
+    status_t cmdStatus;
+    uint32_t size = sizeof(status_t);
+    status_t status = (*mEffectInterface)->command(mEffectInterface,
+                                                   EFFECT_CMD_DISABLE,
+                                                   0,
+                                                   NULL,
+                                                   &size,
+                                                   &cmdStatus);
+    if (status == 0) {
+        status = cmdStatus;
+    }
+    return status;
+}
+
+status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
+                                             uint32_t cmdSize,
+                                             void *pCmdData,
+                                             uint32_t *replySize,
+                                             void *pReplyData)
+{
+    Mutex::Autolock _l(mLock);
+//    LOGV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface);
+
+    if (mEffectInterface == NULL) {
+        return NO_INIT;
+    }
+    status_t status = (*mEffectInterface)->command(mEffectInterface,
+                                                   cmdCode,
+                                                   cmdSize,
+                                                   pCmdData,
+                                                   replySize,
+                                                   pReplyData);
+    if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
+        uint32_t size = (replySize == NULL) ? 0 : *replySize;
+        for (size_t i = 1; i < mHandles.size(); i++) {
+            sp<EffectHandle> h = mHandles[i].promote();
+            if (h != 0) {
+                h->commandExecuted(cmdCode, cmdSize, pCmdData, size, pReplyData);
+            }
+        }
+    }
+    return status;
+}
+
+status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
+{
+    Mutex::Autolock _l(mLock);
+    LOGV("setEnabled %p enabled %d", this, enabled);
+
+    if (enabled != isEnabled()) {
+        switch (mState) {
+        // going from disabled to enabled
+        case IDLE:
+            mState = STARTING;
+            break;
+        case STOPPED:
+            mState = RESTART;
+            break;
+        case STOPPING:
+            mState = ACTIVE;
+            break;
+
+        // going from enabled to disabled
+        case RESTART:
+        case STARTING:
+            mState = IDLE;
+            break;
+        case ACTIVE:
+            mState = STOPPING;
+            break;
+        }
+        for (size_t i = 1; i < mHandles.size(); i++) {
+            sp<EffectHandle> h = mHandles[i].promote();
+            if (h != 0) {
+                h->setEnabled(enabled);
+            }
+        }
+    }
+    return NO_ERROR;
+}
+
+bool AudioFlinger::EffectModule::isEnabled()
+{
+    switch (mState) {
+    case RESTART:
+    case STARTING:
+    case ACTIVE:
+        return true;
+    case IDLE:
+    case STOPPING:
+    case STOPPED:
+    default:
+        return false;
+    }
+}
+
+status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
+{
+    Mutex::Autolock _l(mLock);
+    status_t status = NO_ERROR;
+
+    // Send volume indication if EFFECT_FLAG_VOLUME_IND is set and read back altered volume
+    // if controller flag is set (Note that controller == TRUE => EFFECT_FLAG_VOLUME_CTRL set)
+    if ((mState >= ACTIVE) &&
+            ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
+            (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND)) {
+        status_t cmdStatus;
+        uint32_t volume[2];
+        uint32_t *pVolume = NULL;
+        uint32_t size = sizeof(volume);
+        volume[0] = *left;
+        volume[1] = *right;
+        if (controller) {
+            pVolume = volume;
+        }
+        status = (*mEffectInterface)->command(mEffectInterface,
+                                              EFFECT_CMD_SET_VOLUME,
+                                              size,
+                                              volume,
+                                              &size,
+                                              pVolume);
+        if (controller && status == NO_ERROR && size == sizeof(volume)) {
+            *left = volume[0];
+            *right = volume[1];
+        }
+    }
+    return status;
+}
+
+status_t AudioFlinger::EffectModule::setDevice(uint32_t device)
+{
+    Mutex::Autolock _l(mLock);
+    status_t status = NO_ERROR;
+    if ((mDescriptor.flags & EFFECT_FLAG_DEVICE_MASK) == EFFECT_FLAG_DEVICE_IND) {
+        // convert device bit field from AudioSystem to EffectApi format.
+        device = deviceAudioSystemToEffectApi(device);
+        if (device == 0) {
+            return BAD_VALUE;
+        }
+        status_t cmdStatus;
+        uint32_t size = sizeof(status_t);
+        status = (*mEffectInterface)->command(mEffectInterface,
+                                              EFFECT_CMD_SET_DEVICE,
+                                              sizeof(uint32_t),
+                                              &device,
+                                              &size,
+                                              &cmdStatus);
+        if (status == NO_ERROR) {
+            status = cmdStatus;
+        }
+    }
+    return status;
+}
+
+status_t AudioFlinger::EffectModule::setMode(uint32_t mode)
+{
+    Mutex::Autolock _l(mLock);
+    status_t status = NO_ERROR;
+    if ((mDescriptor.flags & EFFECT_FLAG_AUDIO_MODE_MASK) == EFFECT_FLAG_AUDIO_MODE_IND) {
+        // convert audio mode from AudioSystem to EffectApi format.
+        int effectMode = modeAudioSystemToEffectApi(mode);
+        if (effectMode < 0) {
+            return BAD_VALUE;
+        }
+        status_t cmdStatus;
+        uint32_t size = sizeof(status_t);
+        status = (*mEffectInterface)->command(mEffectInterface,
+                                              EFFECT_CMD_SET_AUDIO_MODE,
+                                              sizeof(int),
+                                              &effectMode,
+                                              &size,
+                                              &cmdStatus);
+        if (status == NO_ERROR) {
+            status = cmdStatus;
+        }
+    }
+    return status;
+}
+
+// update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
+const uint32_t AudioFlinger::EffectModule::sDeviceConvTable[] = {
+    DEVICE_EARPIECE, // AudioSystem::DEVICE_OUT_EARPIECE
+    DEVICE_SPEAKER, // AudioSystem::DEVICE_OUT_SPEAKER
+    DEVICE_WIRED_HEADSET, // case AudioSystem::DEVICE_OUT_WIRED_HEADSET
+    DEVICE_WIRED_HEADPHONE, // AudioSystem::DEVICE_OUT_WIRED_HEADPHONE
+    DEVICE_BLUETOOTH_SCO, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO
+    DEVICE_BLUETOOTH_SCO_HEADSET, // AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET
+    DEVICE_BLUETOOTH_SCO_CARKIT, //  AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT
+    DEVICE_BLUETOOTH_A2DP, //  AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP
+    DEVICE_BLUETOOTH_A2DP_HEADPHONES, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
+    DEVICE_BLUETOOTH_A2DP_SPEAKER, // AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER
+    DEVICE_AUX_DIGITAL // AudioSystem::DEVICE_OUT_AUX_DIGITAL
+};
+
+uint32_t AudioFlinger::EffectModule::deviceAudioSystemToEffectApi(uint32_t device)
+{
+    uint32_t deviceOut = 0;
+    while (device) {
+        const uint32_t i = 31 - __builtin_clz(device);
+        device &= ~(1 << i);
+        if (i >= sizeof(sDeviceConvTable)/sizeof(uint32_t)) {
+            LOGE("device convertion error for AudioSystem device 0x%08x", device);
+            return 0;
+        }
+        deviceOut |= (uint32_t)sDeviceConvTable[i];
+    }
+    return deviceOut;
+}
+
+// update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
+const uint32_t AudioFlinger::EffectModule::sModeConvTable[] = {
+    AUDIO_MODE_NORMAL,   // AudioSystem::MODE_NORMAL
+    AUDIO_MODE_RINGTONE, // AudioSystem::MODE_RINGTONE
+    AUDIO_MODE_IN_CALL   // AudioSystem::MODE_IN_CALL
+};
+
+int AudioFlinger::EffectModule::modeAudioSystemToEffectApi(uint32_t mode)
+{
+    int modeOut = -1;
+    if (mode < sizeof(sModeConvTable) / sizeof(uint32_t)) {
+        modeOut = (int)sModeConvTable[mode];
+    }
+    return modeOut;
+}
+
+status_t AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "\tEffect ID %d:\n", mId);
+    result.append(buffer);
+
+    bool locked = tryLock(mLock);
+    // failed to lock - AudioFlinger is probably deadlocked
+    if (!locked) {
+        result.append("\t\tCould not lock Fx mutex:\n");
+    }
+
+    result.append("\t\tSession Status State Engine:\n");
+    snprintf(buffer, SIZE, "\t\t%05d   %03d    %03d   0x%08x\n",
+            mSessionId, mStatus, mState, (uint32_t)mEffectInterface);
+    result.append(buffer);
+
+    result.append("\t\tDescriptor:\n");
+    snprintf(buffer, SIZE, "\t\t- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+            mDescriptor.uuid.timeLow, mDescriptor.uuid.timeMid, mDescriptor.uuid.timeHiAndVersion,
+            mDescriptor.uuid.clockSeq, mDescriptor.uuid.node[0], mDescriptor.uuid.node[1],mDescriptor.uuid.node[2],
+            mDescriptor.uuid.node[3],mDescriptor.uuid.node[4],mDescriptor.uuid.node[5]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\t\t- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+                mDescriptor.type.timeLow, mDescriptor.type.timeMid, mDescriptor.type.timeHiAndVersion,
+                mDescriptor.type.clockSeq, mDescriptor.type.node[0], mDescriptor.type.node[1],mDescriptor.type.node[2],
+                mDescriptor.type.node[3],mDescriptor.type.node[4],mDescriptor.type.node[5]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\t\t- apiVersion: %04X\n\t\t- flags: %08X\n",
+            mDescriptor.apiVersion,
+            mDescriptor.flags);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\t\t- name: %s\n",
+            mDescriptor.name);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\t\t- implementor: %s\n",
+            mDescriptor.implementor);
+    result.append(buffer);
+
+    result.append("\t\t- Input configuration:\n");
+    result.append("\t\t\tBuffer     Frames  Smp rate Channels Format\n");
+    snprintf(buffer, SIZE, "\t\t\t0x%08x %05d   %05d    %08x %d\n",
+            (uint32_t)mConfig.inputCfg.buffer.raw,
+            mConfig.inputCfg.buffer.frameCount,
+            mConfig.inputCfg.samplingRate,
+            mConfig.inputCfg.channels,
+            mConfig.inputCfg.format);
+    result.append(buffer);
+
+    result.append("\t\t- Output configuration:\n");
+    result.append("\t\t\tBuffer     Frames  Smp rate Channels Format\n");
+    snprintf(buffer, SIZE, "\t\t\t0x%08x %05d   %05d    %08x %d\n",
+            (uint32_t)mConfig.outputCfg.buffer.raw,
+            mConfig.outputCfg.buffer.frameCount,
+            mConfig.outputCfg.samplingRate,
+            mConfig.outputCfg.channels,
+            mConfig.outputCfg.format);
+    result.append(buffer);
+
+    snprintf(buffer, SIZE, "\t\t%d Clients:\n", mHandles.size());
+    result.append(buffer);
+    result.append("\t\t\tPid   Priority Ctrl Locked client server\n");
+    for (size_t i = 0; i < mHandles.size(); ++i) {
+        sp<EffectHandle> handle = mHandles[i].promote();
+        if (handle != 0) {
+            handle->dump(buffer, SIZE);
+            result.append(buffer);
+        }
+    }
+
+    result.append("\n");
+
+    write(fd, result.string(), result.length());
+
+    if (locked) {
+        mLock.unlock();
+    }
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+//  EffectHandle implementation
+// ----------------------------------------------------------------------------
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::EffectHandle"
+
+AudioFlinger::EffectHandle::EffectHandle(const sp<EffectModule>& effect,
+                                        const sp<AudioFlinger::Client>& client,
+                                        const sp<IEffectClient>& effectClient,
+                                        int32_t priority)
+    : BnEffect(),
+    mEffect(effect), mEffectClient(effectClient), mClient(client), mPriority(priority), mHasControl(false)
+{
+    LOGV("constructor %p", this);
+
+    int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
+    mCblkMemory = client->heap()->allocate(EFFECT_PARAM_BUFFER_SIZE + bufOffset);
+    if (mCblkMemory != 0) {
+        mCblk = static_cast<effect_param_cblk_t *>(mCblkMemory->pointer());
+
+        if (mCblk) {
+            new(mCblk) effect_param_cblk_t();
+            mBuffer = (uint8_t *)mCblk + bufOffset;
+         }
+    } else {
+        LOGE("not enough memory for Effect size=%u", EFFECT_PARAM_BUFFER_SIZE + sizeof(effect_param_cblk_t));
+        return;
+    }
+}
+
+AudioFlinger::EffectHandle::~EffectHandle()
+{
+    LOGV("Destructor %p", this);
+    disconnect();
+}
+
+status_t AudioFlinger::EffectHandle::enable()
+{
+    if (!mHasControl) return INVALID_OPERATION;
+    if (mEffect == 0) return DEAD_OBJECT;
+
+    return mEffect->setEnabled(true);
+}
+
+status_t AudioFlinger::EffectHandle::disable()
+{
+    if (!mHasControl) return INVALID_OPERATION;
+    if (mEffect == NULL) return DEAD_OBJECT;
+
+    return mEffect->setEnabled(false);
+}
+
+void AudioFlinger::EffectHandle::disconnect()
+{
+    if (mEffect == 0) {
+        return;
+    }
+    mEffect->disconnect(this);
+    // release sp on module => module destructor can be called now
+    mEffect.clear();
+    if (mCblk) {
+        mCblk->~effect_param_cblk_t();   // destroy our shared-structure.
+    }
+    mCblkMemory.clear();            // and free the shared memory
+    if (mClient != 0) {
+        Mutex::Autolock _l(mClient->audioFlinger()->mLock);
+        mClient.clear();
+    }
+}
+
+status_t AudioFlinger::EffectHandle::command(uint32_t cmdCode,
+                                             uint32_t cmdSize,
+                                             void *pCmdData,
+                                             uint32_t *replySize,
+                                             void *pReplyData)
+{
+//    LOGV("command(), cmdCode: %d, mHasControl: %d, mEffect: %p",
+//              cmdCode, mHasControl, (mEffect == 0) ? 0 : mEffect.get());
+
+    // only get parameter command is permitted for applications not controlling the effect
+    if (!mHasControl && cmdCode != EFFECT_CMD_GET_PARAM) {
+        return INVALID_OPERATION;
+    }
+    if (mEffect == 0) return DEAD_OBJECT;
+
+    // handle commands that are not forwarded transparently to effect engine
+    if (cmdCode == EFFECT_CMD_SET_PARAM_COMMIT) {
+        // No need to trylock() here as this function is executed in the binder thread serving a particular client process:
+        // no risk to block the whole media server process or mixer threads is we are stuck here
+        Mutex::Autolock _l(mCblk->lock);
+        if (mCblk->clientIndex > EFFECT_PARAM_BUFFER_SIZE ||
+            mCblk->serverIndex > EFFECT_PARAM_BUFFER_SIZE) {
+            mCblk->serverIndex = 0;
+            mCblk->clientIndex = 0;
+            return BAD_VALUE;
+        }
+        status_t status = NO_ERROR;
+        while (mCblk->serverIndex < mCblk->clientIndex) {
+            int reply;
+            uint32_t rsize = sizeof(int);
+            int *p = (int *)(mBuffer + mCblk->serverIndex);
+            int size = *p++;
+            if (((uint8_t *)p + size) > mBuffer + mCblk->clientIndex) {
+                LOGW("command(): invalid parameter block size");
+                break;
+            }
+            effect_param_t *param = (effect_param_t *)p;
+            if (param->psize == 0 || param->vsize == 0) {
+                LOGW("command(): null parameter or value size");
+                mCblk->serverIndex += size;
+                continue;
+            }
+            uint32_t psize = sizeof(effect_param_t) +
+                             ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
+                             param->vsize;
+            status_t ret = mEffect->command(EFFECT_CMD_SET_PARAM,
+                                            psize,
+                                            p,
+                                            &rsize,
+                                            &reply);
+            if (ret == NO_ERROR) {
+                if (reply != NO_ERROR) {
+                    status = reply;
+                }
+            } else {
+                status = ret;
+            }
+            mCblk->serverIndex += size;
+        }
+        mCblk->serverIndex = 0;
+        mCblk->clientIndex = 0;
+        return status;
+    } else if (cmdCode == EFFECT_CMD_ENABLE) {
+        return enable();
+    } else if (cmdCode == EFFECT_CMD_DISABLE) {
+        return disable();
+    }
+
+    return mEffect->command(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+}
+
+sp<IMemory> AudioFlinger::EffectHandle::getCblk() const {
+    return mCblkMemory;
+}
+
+void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal)
+{
+    LOGV("setControl %p control %d", this, hasControl);
+
+    mHasControl = hasControl;
+    if (signal && mEffectClient != 0) {
+        mEffectClient->controlStatusChanged(hasControl);
+    }
+}
+
+void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
+                                                 uint32_t cmdSize,
+                                                 void *pCmdData,
+                                                 uint32_t replySize,
+                                                 void *pReplyData)
+{
+    if (mEffectClient != 0) {
+        mEffectClient->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+    }
+}
+
+
+
+void AudioFlinger::EffectHandle::setEnabled(bool enabled)
+{
+    if (mEffectClient != 0) {
+        mEffectClient->enableStatusChanged(enabled);
+    }
+}
+
+status_t AudioFlinger::EffectHandle::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    return BnEffect::onTransact(code, data, reply, flags);
+}
+
+
+void AudioFlinger::EffectHandle::dump(char* buffer, size_t size)
+{
+    bool locked = tryLock(mCblk->lock);
+
+    snprintf(buffer, size, "\t\t\t%05d %05d    %01u    %01u      %05u  %05u\n",
+            (mClient == NULL) ? getpid() : mClient->pid(),
+            mPriority,
+            mHasControl,
+            !locked,
+            mCblk->clientIndex,
+            mCblk->serverIndex
+            );
+
+    if (locked) {
+        mCblk->lock.unlock();
+    }
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger::EffectChain"
+
+AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& wThread,
+                                        int sessionId)
+    : mThread(wThread), mSessionId(sessionId), mActiveTrackCnt(0), mOwnInBuffer(false),
+            mVolumeCtrlIdx(-1), mLeftVolume(0), mRightVolume(0),
+            mNewLeftVolume(0), mNewRightVolume(0)
+{
+    mStrategy = AudioSystem::getStrategyForStream(AudioSystem::MUSIC);
+}
+
+AudioFlinger::EffectChain::~EffectChain()
+{
+    if (mOwnInBuffer) {
+        delete mInBuffer;
+    }
+
+}
+
+// getEffectFromDesc_l() must be called with PlaybackThread::mLock held
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(effect_descriptor_t *descriptor)
+{
+    sp<EffectModule> effect;
+    size_t size = mEffects.size();
+
+    for (size_t i = 0; i < size; i++) {
+        if (memcmp(&mEffects[i]->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) == 0) {
+            effect = mEffects[i];
+            break;
+        }
+    }
+    return effect;
+}
+
+// getEffectFromId_l() must be called with PlaybackThread::mLock held
+sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
+{
+    sp<EffectModule> effect;
+    size_t size = mEffects.size();
+
+    for (size_t i = 0; i < size; i++) {
+        // by convention, return first effect if id provided is 0 (0 is never a valid id)
+        if (id == 0 || mEffects[i]->id() == id) {
+            effect = mEffects[i];
+            break;
+        }
+    }
+    return effect;
+}
+
+// Must be called with EffectChain::mLock locked
+void AudioFlinger::EffectChain::process_l()
+{
+    size_t size = mEffects.size();
+    for (size_t i = 0; i < size; i++) {
+        mEffects[i]->process();
+    }
+    for (size_t i = 0; i < size; i++) {
+        mEffects[i]->updateState();
+    }
+    // if no track is active, input buffer must be cleared here as the mixer process
+    // will not do it
+    if (mSessionId > 0 && activeTracks() == 0) {
+        sp<ThreadBase> thread = mThread.promote();
+        if (thread != 0) {
+            size_t numSamples = thread->frameCount() * thread->channelCount();
+            memset(mInBuffer, 0, numSamples * sizeof(int16_t));
+        }
+    }
+}
+
+// addEffect_l() must be called with PlaybackThread::mLock held
+status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
+{
+    effect_descriptor_t desc = effect->desc();
+    uint32_t insertPref = desc.flags & EFFECT_FLAG_INSERT_MASK;
+
+    Mutex::Autolock _l(mLock);
+    effect->setChain(this);
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread == 0) {
+        return NO_INIT;
+    }
+    effect->setThread(thread);
+
+    if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+        // Auxiliary effects are inserted at the beginning of mEffects vector as
+        // they are processed first and accumulated in chain input buffer
+        mEffects.insertAt(effect, 0);
+
+        // the input buffer for auxiliary effect contains mono samples in
+        // 32 bit format. This is to avoid saturation in AudoMixer
+        // accumulation stage. Saturation is done in EffectModule::process() before
+        // calling the process in effect engine
+        size_t numSamples = thread->frameCount();
+        int32_t *buffer = new int32_t[numSamples];
+        memset(buffer, 0, numSamples * sizeof(int32_t));
+        effect->setInBuffer((int16_t *)buffer);
+        // auxiliary effects output samples to chain input buffer for further processing
+        // by insert effects
+        effect->setOutBuffer(mInBuffer);
+    } else {
+        // Insert effects are inserted at the end of mEffects vector as they are processed
+        //  after track and auxiliary effects.
+        // Insert effect order as a function of indicated preference:
+        //  if EFFECT_FLAG_INSERT_EXCLUSIVE, insert in first position or reject if
+        //  another effect is present
+        //  else if EFFECT_FLAG_INSERT_FIRST, insert in first position or after the
+        //  last effect claiming first position
+        //  else if EFFECT_FLAG_INSERT_LAST, insert in last position or before the
+        //  first effect claiming last position
+        //  else if EFFECT_FLAG_INSERT_ANY insert after first or before last
+        // Reject insertion if an effect with EFFECT_FLAG_INSERT_EXCLUSIVE is
+        // already present
+
+        int size = (int)mEffects.size();
+        int idx_insert = size;
+        int idx_insert_first = -1;
+        int idx_insert_last = -1;
+
+        for (int i = 0; i < size; i++) {
+            effect_descriptor_t d = mEffects[i]->desc();
+            uint32_t iMode = d.flags & EFFECT_FLAG_TYPE_MASK;
+            uint32_t iPref = d.flags & EFFECT_FLAG_INSERT_MASK;
+            if (iMode == EFFECT_FLAG_TYPE_INSERT) {
+                // check invalid effect chaining combinations
+                if (insertPref == EFFECT_FLAG_INSERT_EXCLUSIVE ||
+                    iPref == EFFECT_FLAG_INSERT_EXCLUSIVE) {
+                    LOGW("addEffect_l() could not insert effect %s: exclusive conflict with %s", desc.name, d.name);
+                    return INVALID_OPERATION;
+                }
+                // remember position of first insert effect and by default
+                // select this as insert position for new effect
+                if (idx_insert == size) {
+                    idx_insert = i;
+                }
+                // remember position of last insert effect claiming
+                // first position
+                if (iPref == EFFECT_FLAG_INSERT_FIRST) {
+                    idx_insert_first = i;
+                }
+                // remember position of first insert effect claiming
+                // last position
+                if (iPref == EFFECT_FLAG_INSERT_LAST &&
+                    idx_insert_last == -1) {
+                    idx_insert_last = i;
+                }
+            }
+        }
+
+        // modify idx_insert from first position if needed
+        if (insertPref == EFFECT_FLAG_INSERT_LAST) {
+            if (idx_insert_last != -1) {
+                idx_insert = idx_insert_last;
+            } else {
+                idx_insert = size;
+            }
+        } else {
+            if (idx_insert_first != -1) {
+                idx_insert = idx_insert_first + 1;
+            }
+        }
+
+        // always read samples from chain input buffer
+        effect->setInBuffer(mInBuffer);
+
+        // if last effect in the chain, output samples to chain
+        // output buffer, otherwise to chain input buffer
+        if (idx_insert == size) {
+            if (idx_insert != 0) {
+                mEffects[idx_insert-1]->setOutBuffer(mInBuffer);
+                mEffects[idx_insert-1]->configure();
+            }
+            effect->setOutBuffer(mOutBuffer);
+        } else {
+            effect->setOutBuffer(mInBuffer);
+        }
+        mEffects.insertAt(effect, idx_insert);
+
+        LOGV("addEffect_l() effect %p, added in chain %p at rank %d", effect.get(), this, idx_insert);
+    }
+    effect->configure();
+    return NO_ERROR;
+}
+
+// removeEffect_l() must be called with PlaybackThread::mLock held
+size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect)
+{
+    Mutex::Autolock _l(mLock);
+    int size = (int)mEffects.size();
+    int i;
+    uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
+
+    for (i = 0; i < size; i++) {
+        if (effect == mEffects[i]) {
+            if (type == EFFECT_FLAG_TYPE_AUXILIARY) {
+                delete[] effect->inBuffer();
+            } else {
+                if (i == size - 1 && i != 0) {
+                    mEffects[i - 1]->setOutBuffer(mOutBuffer);
+                    mEffects[i - 1]->configure();
+                }
+            }
+            mEffects.removeAt(i);
+            LOGV("removeEffect_l() effect %p, removed from chain %p at rank %d", effect.get(), this, i);
+            break;
+        }
+    }
+
+    return mEffects.size();
+}
+
+// setDevice_l() must be called with PlaybackThread::mLock held
+void AudioFlinger::EffectChain::setDevice_l(uint32_t device)
+{
+    size_t size = mEffects.size();
+    for (size_t i = 0; i < size; i++) {
+        mEffects[i]->setDevice(device);
+    }
+}
+
+// setMode_l() must be called with PlaybackThread::mLock held
+void AudioFlinger::EffectChain::setMode_l(uint32_t mode)
+{
+    size_t size = mEffects.size();
+    for (size_t i = 0; i < size; i++) {
+        mEffects[i]->setMode(mode);
+    }
+}
+
+// setVolume_l() must be called with PlaybackThread::mLock held
+bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right)
+{
+    uint32_t newLeft = *left;
+    uint32_t newRight = *right;
+    bool hasControl = false;
+    int ctrlIdx = -1;
+    size_t size = mEffects.size();
+
+    // first update volume controller
+    for (size_t i = size; i > 0; i--) {
+        if ((mEffects[i - 1]->state() >= EffectModule::ACTIVE) &&
+            (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
+            ctrlIdx = i - 1;
+            hasControl = true;
+            break;
+        }
+    }
+
+    if (ctrlIdx == mVolumeCtrlIdx && *left == mLeftVolume && *right == mRightVolume) {
+        if (hasControl) {
+            *left = mNewLeftVolume;
+            *right = mNewRightVolume;
+        }
+        return hasControl;
+    }
+
+    if (mVolumeCtrlIdx != -1) {
+        hasControl = true;
+    }
+    mVolumeCtrlIdx = ctrlIdx;
+    mLeftVolume = newLeft;
+    mRightVolume = newRight;
+
+    // second get volume update from volume controller
+    if (ctrlIdx >= 0) {
+        mEffects[ctrlIdx]->setVolume(&newLeft, &newRight, true);
+        mNewLeftVolume = newLeft;
+        mNewRightVolume = newRight;
+    }
+    // then indicate volume to all other effects in chain.
+    // Pass altered volume to effects before volume controller
+    // and requested volume to effects after controller
+    uint32_t lVol = newLeft;
+    uint32_t rVol = newRight;
+
+    for (size_t i = 0; i < size; i++) {
+        if ((int)i == ctrlIdx) continue;
+        // this also works for ctrlIdx == -1 when there is no volume controller
+        if ((int)i > ctrlIdx) {
+            lVol = *left;
+            rVol = *right;
+        }
+        mEffects[i]->setVolume(&lVol, &rVol, false);
+    }
+    *left = newLeft;
+    *right = newRight;
+
+    return hasControl;
+}
+
+status_t AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "Effects for session %d:\n", mSessionId);
+    result.append(buffer);
+
+    bool locked = tryLock(mLock);
+    // failed to lock - AudioFlinger is probably deadlocked
+    if (!locked) {
+        result.append("\tCould not lock mutex:\n");
+    }
+
+    result.append("\tNum fx In buffer   Out buffer   Active tracks:\n");
+    snprintf(buffer, SIZE, "\t%02d     0x%08x  0x%08x   %d\n",
+            mEffects.size(),
+            (uint32_t)mInBuffer,
+            (uint32_t)mOutBuffer,
+            mActiveTrackCnt);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    for (size_t i = 0; i < mEffects.size(); ++i) {
+        sp<EffectModule> effect = mEffects[i];
+        if (effect != 0) {
+            effect->dump(fd, args);
+        }
+    }
+
+    if (locked) {
+        mLock.unlock();
+    }
+
+    return NO_ERROR;
+}
+
+#undef LOG_TAG
+#define LOG_TAG "AudioFlinger"
+
+// ----------------------------------------------------------------------------
+
+status_t AudioFlinger::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    return BnAudioFlinger::onTransact(code, data, reply, flags);
+}
+
+}; // namespace android
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
new file mode 100644
index 0000000..5520551
--- /dev/null
+++ b/services/audioflinger/AudioFlinger.h
@@ -0,0 +1,1194 @@
+/* //device/include/server/AudioFlinger/AudioFlinger.h
+**
+** Copyright 2007, 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 ANDROID_AUDIO_FLINGER_H
+#define ANDROID_AUDIO_FLINGER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IAudioFlingerClient.h>
+#include <media/IAudioTrack.h>
+#include <media/IAudioRecord.h>
+#include <media/AudioTrack.h>
+
+#include <utils/Atomic.h>
+#include <utils/Errors.h>
+#include <utils/threads.h>
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
+
+#include <binder/BinderService.h>
+#include <binder/MemoryDealer.h>
+
+#include <hardware_legacy/AudioHardwareInterface.h>
+
+#include "AudioBufferProvider.h"
+
+namespace android {
+
+class audio_track_cblk_t;
+class effect_param_cblk_t;
+class AudioMixer;
+class AudioBuffer;
+class AudioResampler;
+
+
+// ----------------------------------------------------------------------------
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+
+// ----------------------------------------------------------------------------
+
+static const nsecs_t kStandbyTimeInNsecs = seconds(3);
+
+class AudioFlinger :
+    public BinderService<AudioFlinger>,
+    public BnAudioFlinger
+{
+    friend class BinderService<AudioFlinger>;
+public:
+    static char const* getServiceName() { return "media.audio_flinger"; }
+
+    virtual     status_t    dump(int fd, const Vector<String16>& args);
+
+    // IAudioFlinger interface
+    virtual sp<IAudioTrack> createTrack(
+                                pid_t pid,
+                                int streamType,
+                                uint32_t sampleRate,
+                                int format,
+                                int channelCount,
+                                int frameCount,
+                                uint32_t flags,
+                                const sp<IMemory>& sharedBuffer,
+                                int output,
+                                int *sessionId,
+                                status_t *status);
+
+    virtual     uint32_t    sampleRate(int output) const;
+    virtual     int         channelCount(int output) const;
+    virtual     int         format(int output) const;
+    virtual     size_t      frameCount(int output) const;
+    virtual     uint32_t    latency(int output) const;
+
+    virtual     status_t    setMasterVolume(float value);
+    virtual     status_t    setMasterMute(bool muted);
+
+    virtual     float       masterVolume() const;
+    virtual     bool        masterMute() const;
+
+    virtual     status_t    setStreamVolume(int stream, float value, int output);
+    virtual     status_t    setStreamMute(int stream, bool muted);
+
+    virtual     float       streamVolume(int stream, int output) const;
+    virtual     bool        streamMute(int stream) const;
+
+    virtual     status_t    setMode(int mode);
+
+    virtual     status_t    setMicMute(bool state);
+    virtual     bool        getMicMute() const;
+
+    virtual     bool        isStreamActive(int stream) const;
+
+    virtual     status_t    setParameters(int ioHandle, const String8& keyValuePairs);
+    virtual     String8     getParameters(int ioHandle, const String8& keys);
+
+    virtual     void        registerClient(const sp<IAudioFlingerClient>& client);
+
+    virtual     size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
+    virtual     unsigned int  getInputFramesLost(int ioHandle);
+
+    virtual int openOutput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t *pLatencyMs,
+                                    uint32_t flags);
+
+    virtual int openDuplicateOutput(int output1, int output2);
+
+    virtual status_t closeOutput(int output);
+
+    virtual status_t suspendOutput(int output);
+
+    virtual status_t restoreOutput(int output);
+
+    virtual int openInput(uint32_t *pDevices,
+                            uint32_t *pSamplingRate,
+                            uint32_t *pFormat,
+                            uint32_t *pChannels,
+                            uint32_t acoustics);
+
+    virtual status_t closeInput(int input);
+
+    virtual status_t setStreamOutput(uint32_t stream, int output);
+
+    virtual status_t setVoiceVolume(float volume);
+
+    virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames, int output);
+
+    virtual int newAudioSessionId();
+
+    virtual status_t loadEffectLibrary(const char *libPath, int *handle);
+
+    virtual status_t unloadEffectLibrary(int handle);
+
+    virtual status_t queryNumberEffects(uint32_t *numEffects);
+
+    virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor);
+
+    virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *descriptor);
+
+    virtual sp<IEffect> createEffect(pid_t pid,
+                        effect_descriptor_t *pDesc,
+                        const sp<IEffectClient>& effectClient,
+                        int32_t priority,
+                        int output,
+                        int sessionId,
+                        status_t *status,
+                        int *id,
+                        int *enabled);
+
+    virtual status_t moveEffects(int session, int srcOutput, int dstOutput);
+
+    enum hardware_call_state {
+        AUDIO_HW_IDLE = 0,
+        AUDIO_HW_INIT,
+        AUDIO_HW_OUTPUT_OPEN,
+        AUDIO_HW_OUTPUT_CLOSE,
+        AUDIO_HW_INPUT_OPEN,
+        AUDIO_HW_INPUT_CLOSE,
+        AUDIO_HW_STANDBY,
+        AUDIO_HW_SET_MASTER_VOLUME,
+        AUDIO_HW_GET_ROUTING,
+        AUDIO_HW_SET_ROUTING,
+        AUDIO_HW_GET_MODE,
+        AUDIO_HW_SET_MODE,
+        AUDIO_HW_GET_MIC_MUTE,
+        AUDIO_HW_SET_MIC_MUTE,
+        AUDIO_SET_VOICE_VOLUME,
+        AUDIO_SET_PARAMETER,
+    };
+
+    // record interface
+    virtual sp<IAudioRecord> openRecord(
+                                pid_t pid,
+                                int input,
+                                uint32_t sampleRate,
+                                int format,
+                                int channelCount,
+                                int frameCount,
+                                uint32_t flags,
+                                int *sessionId,
+                                status_t *status);
+
+    virtual     status_t    onTransact(
+                                uint32_t code,
+                                const Parcel& data,
+                                Parcel* reply,
+                                uint32_t flags);
+
+                uint32_t    getMode() { return mMode; }
+
+private:
+                            AudioFlinger();
+    virtual                 ~AudioFlinger();
+
+
+    // Internal dump utilites.
+    status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
+    status_t dumpClients(int fd, const Vector<String16>& args);
+    status_t dumpInternals(int fd, const Vector<String16>& args);
+
+    // --- Client ---
+    class Client : public RefBase {
+    public:
+                            Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
+        virtual             ~Client();
+        const sp<MemoryDealer>&     heap() const;
+        pid_t               pid() const { return mPid; }
+        sp<AudioFlinger>    audioFlinger() { return mAudioFlinger; }
+
+    private:
+                            Client(const Client&);
+                            Client& operator = (const Client&);
+        sp<AudioFlinger>    mAudioFlinger;
+        sp<MemoryDealer>    mMemoryDealer;
+        pid_t               mPid;
+    };
+
+    // --- Notification Client ---
+    class NotificationClient : public IBinder::DeathRecipient {
+    public:
+                            NotificationClient(const sp<AudioFlinger>& audioFlinger,
+                                                const sp<IAudioFlingerClient>& client,
+                                                pid_t pid);
+        virtual             ~NotificationClient();
+
+                sp<IAudioFlingerClient>    client() { return mClient; }
+
+                // IBinder::DeathRecipient
+                virtual     void        binderDied(const wp<IBinder>& who);
+
+    private:
+                            NotificationClient(const NotificationClient&);
+                            NotificationClient& operator = (const NotificationClient&);
+
+        sp<AudioFlinger>        mAudioFlinger;
+        pid_t                   mPid;
+        sp<IAudioFlingerClient> mClient;
+    };
+
+    class TrackHandle;
+    class RecordHandle;
+    class RecordThread;
+    class PlaybackThread;
+    class MixerThread;
+    class DirectOutputThread;
+    class DuplicatingThread;
+    class Track;
+    class RecordTrack;
+    class EffectModule;
+    class EffectHandle;
+    class EffectChain;
+
+    class ThreadBase : public Thread {
+    public:
+        ThreadBase (const sp<AudioFlinger>& audioFlinger, int id);
+        virtual             ~ThreadBase();
+
+        status_t dumpBase(int fd, const Vector<String16>& args);
+
+        // base for record and playback
+        class TrackBase : public AudioBufferProvider, public RefBase {
+
+        public:
+            enum track_state {
+                IDLE,
+                TERMINATED,
+                STOPPED,
+                RESUMING,
+                ACTIVE,
+                PAUSING,
+                PAUSED
+            };
+
+            enum track_flags {
+                STEPSERVER_FAILED = 0x01, //  StepServer could not acquire cblk->lock mutex
+                SYSTEM_FLAGS_MASK = 0x0000ffffUL,
+                // The upper 16 bits are used for track-specific flags.
+            };
+
+                                TrackBase(const wp<ThreadBase>& thread,
+                                        const sp<Client>& client,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount,
+                                        uint32_t flags,
+                                        const sp<IMemory>& sharedBuffer,
+                                        int sessionId);
+                                ~TrackBase();
+
+            virtual status_t    start() = 0;
+            virtual void        stop() = 0;
+                    sp<IMemory> getCblk() const;
+                    audio_track_cblk_t* cblk() const { return mCblk; }
+                    int         sessionId() { return mSessionId; }
+
+        protected:
+            friend class ThreadBase;
+            friend class RecordHandle;
+            friend class PlaybackThread;
+            friend class RecordThread;
+            friend class MixerThread;
+            friend class DirectOutputThread;
+
+                                TrackBase(const TrackBase&);
+                                TrackBase& operator = (const TrackBase&);
+
+            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
+            virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+
+            int format() const {
+                return mFormat;
+            }
+
+            int channelCount() const ;
+
+            int sampleRate() const;
+
+            void* getBuffer(uint32_t offset, uint32_t frames) const;
+
+            bool isStopped() const {
+                return mState == STOPPED;
+            }
+
+            bool isTerminated() const {
+                return mState == TERMINATED;
+            }
+
+            bool step();
+            void reset();
+
+            wp<ThreadBase>      mThread;
+            sp<Client>          mClient;
+            sp<IMemory>         mCblkMemory;
+            audio_track_cblk_t* mCblk;
+            void*               mBuffer;
+            void*               mBufferEnd;
+            uint32_t            mFrameCount;
+            // we don't really need a lock for these
+            int                 mState;
+            int                 mClientTid;
+            uint8_t             mFormat;
+            uint32_t            mFlags;
+            int                 mSessionId;
+        };
+
+        class ConfigEvent {
+        public:
+            ConfigEvent() : mEvent(0), mParam(0) {}
+
+            int mEvent;
+            int mParam;
+        };
+
+                    uint32_t    sampleRate() const;
+                    int         channelCount() const;
+                    int         format() const;
+                    size_t      frameCount() const;
+                    void        wakeUp()    { mWaitWorkCV.broadcast(); }
+                    void        exit();
+        virtual     bool        checkForNewParameters_l() = 0;
+        virtual     status_t    setParameters(const String8& keyValuePairs);
+        virtual     String8     getParameters(const String8& keys) = 0;
+        virtual     void        audioConfigChanged_l(int event, int param = 0) = 0;
+                    void        sendConfigEvent(int event, int param = 0);
+                    void        sendConfigEvent_l(int event, int param = 0);
+                    void        processConfigEvents();
+                    int         id() const { return mId;}
+                    bool        standby() { return mStandby; }
+
+        mutable     Mutex                   mLock;
+
+    protected:
+
+        friend class Track;
+        friend class TrackBase;
+        friend class PlaybackThread;
+        friend class MixerThread;
+        friend class DirectOutputThread;
+        friend class DuplicatingThread;
+        friend class RecordThread;
+        friend class RecordTrack;
+
+                    Condition               mWaitWorkCV;
+                    sp<AudioFlinger>        mAudioFlinger;
+                    uint32_t                mSampleRate;
+                    size_t                  mFrameCount;
+                    uint32_t                mChannels;
+                    uint16_t                mChannelCount;
+                    uint16_t                mFrameSize;
+                    int                     mFormat;
+                    Condition               mParamCond;
+                    Vector<String8>         mNewParameters;
+                    status_t                mParamStatus;
+                    Vector<ConfigEvent *>   mConfigEvents;
+                    bool                    mStandby;
+                    int                     mId;
+                    bool                    mExiting;
+    };
+
+    // --- PlaybackThread ---
+    class PlaybackThread : public ThreadBase {
+    public:
+
+        enum type {
+            MIXER,
+            DIRECT,
+            DUPLICATING
+        };
+
+        enum mixer_state {
+            MIXER_IDLE,
+            MIXER_TRACKS_ENABLED,
+            MIXER_TRACKS_READY
+        };
+
+        // playback track
+        class Track : public TrackBase {
+        public:
+                                Track(  const wp<ThreadBase>& thread,
+                                        const sp<Client>& client,
+                                        int streamType,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount,
+                                        const sp<IMemory>& sharedBuffer,
+                                        int sessionId);
+                                ~Track();
+
+                    void        dump(char* buffer, size_t size);
+            virtual status_t    start();
+            virtual void        stop();
+                    void        pause();
+
+                    void        flush();
+                    void        destroy();
+                    void        mute(bool);
+                    void        setVolume(float left, float right);
+                    int name() const {
+                        return mName;
+                    }
+
+                    int type() const {
+                        return mStreamType;
+                    }
+                    status_t    attachAuxEffect(int EffectId);
+                    void        setAuxBuffer(int EffectId, int32_t *buffer);
+                    int32_t     *auxBuffer() { return mAuxBuffer; }
+                    void        setMainBuffer(int16_t *buffer) { mMainBuffer = buffer; }
+                    int16_t     *mainBuffer() { return mMainBuffer; }
+                    int         auxEffectId() { return mAuxEffectId; }
+
+
+        protected:
+            friend class ThreadBase;
+            friend class AudioFlinger;
+            friend class TrackHandle;
+            friend class PlaybackThread;
+            friend class MixerThread;
+            friend class DirectOutputThread;
+
+                                Track(const Track&);
+                                Track& operator = (const Track&);
+
+            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+            bool isMuted() { return mMute; }
+            bool isPausing() const {
+                return mState == PAUSING;
+            }
+            bool isPaused() const {
+                return mState == PAUSED;
+            }
+            bool isReady() const;
+            void setPaused() { mState = PAUSED; }
+            void reset();
+
+            bool isOutputTrack() const {
+                return (mStreamType == AudioSystem::NUM_STREAM_TYPES);
+            }
+
+            // we don't really need a lock for these
+            float               mVolume[2];
+            volatile bool       mMute;
+            // FILLED state is used for suppressing volume ramp at begin of playing
+            enum {FS_FILLING, FS_FILLED, FS_ACTIVE};
+            mutable uint8_t     mFillingUpStatus;
+            int8_t              mRetryCount;
+            sp<IMemory>         mSharedBuffer;
+            bool                mResetDone;
+            int                 mStreamType;
+            int                 mName;
+            int16_t             *mMainBuffer;
+            int32_t             *mAuxBuffer;
+            int                 mAuxEffectId;
+        };  // end of Track
+
+
+        // playback track
+        class OutputTrack : public Track {
+        public:
+
+            class Buffer: public AudioBufferProvider::Buffer {
+            public:
+                int16_t *mBuffer;
+            };
+
+                                OutputTrack(  const wp<ThreadBase>& thread,
+                                        DuplicatingThread *sourceThread,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount);
+                                ~OutputTrack();
+
+            virtual status_t    start();
+            virtual void        stop();
+                    bool        write(int16_t* data, uint32_t frames);
+                    bool        bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; }
+                    bool        isActive() { return mActive; }
+            wp<ThreadBase>&     thread()  { return mThread; }
+
+        private:
+
+            status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs);
+            void                clearBufferQueue();
+
+            // Maximum number of pending buffers allocated by OutputTrack::write()
+            static const uint8_t kMaxOverFlowBuffers = 10;
+
+            Vector < Buffer* >          mBufferQueue;
+            AudioBufferProvider::Buffer mOutBuffer;
+            bool                        mActive;
+            DuplicatingThread*          mSourceThread;
+        };  // end of OutputTrack
+
+        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
+        virtual             ~PlaybackThread();
+
+        virtual     status_t    dump(int fd, const Vector<String16>& args);
+
+        // Thread virtuals
+        virtual     status_t    readyToRun();
+        virtual     void        onFirstRef();
+
+        virtual     uint32_t    latency() const;
+
+        virtual     status_t    setMasterVolume(float value);
+        virtual     status_t    setMasterMute(bool muted);
+
+        virtual     float       masterVolume() const;
+        virtual     bool        masterMute() const;
+
+        virtual     status_t    setStreamVolume(int stream, float value);
+        virtual     status_t    setStreamMute(int stream, bool muted);
+
+        virtual     float       streamVolume(int stream) const;
+        virtual     bool        streamMute(int stream) const;
+
+                    bool        isStreamActive(int stream) const;
+
+                    sp<Track>   createTrack_l(
+                                    const sp<AudioFlinger::Client>& client,
+                                    int streamType,
+                                    uint32_t sampleRate,
+                                    int format,
+                                    int channelCount,
+                                    int frameCount,
+                                    const sp<IMemory>& sharedBuffer,
+                                    int sessionId,
+                                    status_t *status);
+
+                    AudioStreamOut* getOutput() { return mOutput; }
+
+        virtual     int         type() const { return mType; }
+                    void        suspend() { mSuspended++; }
+                    void        restore() { if (mSuspended) mSuspended--; }
+                    bool        isSuspended() { return (mSuspended != 0); }
+        virtual     String8     getParameters(const String8& keys);
+        virtual     void        audioConfigChanged_l(int event, int param = 0);
+        virtual     status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
+                    int16_t     *mixBuffer() { return mMixBuffer; };
+
+                    sp<EffectHandle> createEffect_l(
+                                        const sp<AudioFlinger::Client>& client,
+                                        const sp<IEffectClient>& effectClient,
+                                        int32_t priority,
+                                        int sessionId,
+                                        effect_descriptor_t *desc,
+                                        int *enabled,
+                                        status_t *status);
+                    void disconnectEffect(const sp< EffectModule>& effect,
+                                          const wp<EffectHandle>& handle);
+
+                    // return values for hasAudioSession (bit field)
+                    enum effect_state {
+                        EFFECT_SESSION = 0x1,   // the audio session corresponds to at least one
+                                                // effect
+                        TRACK_SESSION = 0x2     // the audio session corresponds to at least one
+                                                // track
+                    };
+
+                    uint32_t hasAudioSession(int sessionId);
+                    sp<EffectChain> getEffectChain(int sessionId);
+                    sp<EffectChain> getEffectChain_l(int sessionId);
+                    status_t addEffectChain_l(const sp<EffectChain>& chain);
+                    size_t removeEffectChain_l(const sp<EffectChain>& chain);
+                    void lockEffectChains_l(Vector<sp <EffectChain> >& effectChains);
+                    void unlockEffectChains(Vector<sp <EffectChain> >& effectChains);
+
+                    sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId);
+                    void detachAuxEffect_l(int effectId);
+                    status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track> track,
+                            int EffectId);
+                    status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track> track,
+                            int EffectId);
+                    void setMode(uint32_t mode);
+
+                    status_t addEffect_l(const sp< EffectModule>& effect);
+                    void removeEffect_l(const sp< EffectModule>& effect);
+
+                    uint32_t getStrategyForSession_l(int sessionId);
+
+        struct  stream_type_t {
+            stream_type_t()
+                :   volume(1.0f),
+                    mute(false)
+            {
+            }
+            float       volume;
+            bool        mute;
+        };
+
+    protected:
+        int                             mType;
+        int16_t*                        mMixBuffer;
+        int                             mSuspended;
+        int                             mBytesWritten;
+        bool                            mMasterMute;
+        SortedVector< wp<Track> >       mActiveTracks;
+
+        virtual int             getTrackName_l() = 0;
+        virtual void            deleteTrackName_l(int name) = 0;
+        virtual uint32_t        activeSleepTimeUs() = 0;
+        virtual uint32_t        idleSleepTimeUs() = 0;
+
+    private:
+
+        friend class AudioFlinger;
+        friend class OutputTrack;
+        friend class Track;
+        friend class TrackBase;
+        friend class MixerThread;
+        friend class DirectOutputThread;
+        friend class DuplicatingThread;
+
+        PlaybackThread(const Client&);
+        PlaybackThread& operator = (const PlaybackThread&);
+
+        status_t    addTrack_l(const sp<Track>& track);
+        void        destroyTrack_l(const sp<Track>& track);
+
+        void        readOutputParameters();
+
+        uint32_t    device() { return mDevice; }
+
+        virtual status_t    dumpInternals(int fd, const Vector<String16>& args);
+        status_t    dumpTracks(int fd, const Vector<String16>& args);
+        status_t    dumpEffectChains(int fd, const Vector<String16>& args);
+
+        SortedVector< sp<Track> >       mTracks;
+        // mStreamTypes[] uses 1 additionnal stream type internally for the OutputTrack used by DuplicatingThread
+        stream_type_t                   mStreamTypes[AudioSystem::NUM_STREAM_TYPES + 1];
+        AudioStreamOut*                 mOutput;
+        float                           mMasterVolume;
+        nsecs_t                         mLastWriteTime;
+        int                             mNumWrites;
+        int                             mNumDelayedWrites;
+        bool                            mInWrite;
+        Vector< sp<EffectChain> >       mEffectChains;
+        uint32_t                        mDevice;
+    };
+
+    class MixerThread : public PlaybackThread {
+    public:
+        MixerThread (const sp<AudioFlinger>& audioFlinger,
+                     AudioStreamOut* output,
+                     int id,
+                     uint32_t device);
+        virtual             ~MixerThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+
+                    void        invalidateTracks(int streamType);
+        virtual     bool        checkForNewParameters_l();
+        virtual     status_t    dumpInternals(int fd, const Vector<String16>& args);
+
+    protected:
+                    uint32_t    prepareTracks_l(const SortedVector< wp<Track> >& activeTracks,
+                                                Vector< sp<Track> > *tracksToRemove);
+        virtual     int         getTrackName_l();
+        virtual     void        deleteTrackName_l(int name);
+        virtual     uint32_t    activeSleepTimeUs();
+        virtual     uint32_t    idleSleepTimeUs();
+
+        AudioMixer*                     mAudioMixer;
+    };
+
+    class DirectOutputThread : public PlaybackThread {
+    public:
+
+        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device);
+        ~DirectOutputThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+
+        virtual     bool        checkForNewParameters_l();
+
+    protected:
+        virtual     int         getTrackName_l();
+        virtual     void        deleteTrackName_l(int name);
+        virtual     uint32_t    activeSleepTimeUs();
+        virtual     uint32_t    idleSleepTimeUs();
+
+    private:
+        void applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp);
+
+        float mLeftVolFloat;
+        float mRightVolFloat;
+        uint16_t mLeftVolShort;
+        uint16_t mRightVolShort;
+    };
+
+    class DuplicatingThread : public MixerThread {
+    public:
+        DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, int id);
+        ~DuplicatingThread();
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+                    void        addOutputTrack(MixerThread* thread);
+                    void        removeOutputTrack(MixerThread* thread);
+                    uint32_t    waitTimeMs() { return mWaitTimeMs; }
+    protected:
+        virtual     uint32_t    activeSleepTimeUs();
+
+    private:
+                    bool        outputsReady(SortedVector< sp<OutputTrack> > &outputTracks);
+                    void        updateWaitTime();
+
+        SortedVector < sp<OutputTrack> >  mOutputTracks;
+                    uint32_t    mWaitTimeMs;
+    };
+
+              PlaybackThread *checkPlaybackThread_l(int output) const;
+              MixerThread *checkMixerThread_l(int output) const;
+              RecordThread *checkRecordThread_l(int input) const;
+              float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
+              void audioConfigChanged_l(int event, int ioHandle, void *param2);
+
+              int  nextUniqueId();
+              status_t moveEffectChain_l(int session,
+                                     AudioFlinger::PlaybackThread *srcThread,
+                                     AudioFlinger::PlaybackThread *dstThread,
+                                     bool reRegister);
+
+    friend class AudioBuffer;
+
+    class TrackHandle : public android::BnAudioTrack {
+    public:
+                            TrackHandle(const sp<PlaybackThread::Track>& track);
+        virtual             ~TrackHandle();
+        virtual status_t    start();
+        virtual void        stop();
+        virtual void        flush();
+        virtual void        mute(bool);
+        virtual void        pause();
+        virtual void        setVolume(float left, float right);
+        virtual sp<IMemory> getCblk() const;
+        virtual status_t    attachAuxEffect(int effectId);
+        virtual status_t onTransact(
+            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+    private:
+        sp<PlaybackThread::Track> mTrack;
+    };
+
+    friend class Client;
+    friend class PlaybackThread::Track;
+
+
+                void        removeClient_l(pid_t pid);
+                void        removeNotificationClient(pid_t pid);
+
+
+    // record thread
+    class RecordThread : public ThreadBase, public AudioBufferProvider
+    {
+    public:
+
+        // record track
+        class RecordTrack : public TrackBase {
+        public:
+                                RecordTrack(const wp<ThreadBase>& thread,
+                                        const sp<Client>& client,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount,
+                                        uint32_t flags,
+                                        int sessionId);
+                                ~RecordTrack();
+
+            virtual status_t    start();
+            virtual void        stop();
+
+                    bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
+                    bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
+
+                    void        dump(char* buffer, size_t size);
+        private:
+            friend class AudioFlinger;
+            friend class RecordThread;
+
+                                RecordTrack(const RecordTrack&);
+                                RecordTrack& operator = (const RecordTrack&);
+
+            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+
+            bool                mOverflow;
+        };
+
+
+                RecordThread(const sp<AudioFlinger>& audioFlinger,
+                        AudioStreamIn *input,
+                        uint32_t sampleRate,
+                        uint32_t channels,
+                        int id);
+                ~RecordThread();
+
+        virtual bool        threadLoop();
+        virtual status_t    readyToRun() { return NO_ERROR; }
+        virtual void        onFirstRef();
+
+                status_t    start(RecordTrack* recordTrack);
+                void        stop(RecordTrack* recordTrack);
+                status_t    dump(int fd, const Vector<String16>& args);
+                AudioStreamIn* getInput() { return mInput; }
+
+        virtual status_t    getNextBuffer(AudioBufferProvider::Buffer* buffer);
+        virtual void        releaseBuffer(AudioBufferProvider::Buffer* buffer);
+        virtual bool        checkForNewParameters_l();
+        virtual String8     getParameters(const String8& keys);
+        virtual void        audioConfigChanged_l(int event, int param = 0);
+                void        readInputParameters();
+        virtual unsigned int  getInputFramesLost();
+
+    private:
+                RecordThread();
+                AudioStreamIn                       *mInput;
+                sp<RecordTrack>                     mActiveTrack;
+                Condition                           mStartStopCond;
+                AudioResampler                      *mResampler;
+                int32_t                             *mRsmpOutBuffer;
+                int16_t                             *mRsmpInBuffer;
+                size_t                              mRsmpInIndex;
+                size_t                              mInputBytes;
+                int                                 mReqChannelCount;
+                uint32_t                            mReqSampleRate;
+                ssize_t                             mBytesRead;
+    };
+
+    class RecordHandle : public android::BnAudioRecord {
+    public:
+        RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
+        virtual             ~RecordHandle();
+        virtual status_t    start();
+        virtual void        stop();
+        virtual sp<IMemory> getCblk() const;
+        virtual status_t onTransact(
+            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+    private:
+        sp<RecordThread::RecordTrack> mRecordTrack;
+    };
+
+    //--- Audio Effect Management
+
+    // EffectModule and EffectChain classes both have their own mutex to protect
+    // state changes or resource modifications. Always respect the following order
+    // if multiple mutexes must be acquired to avoid cross deadlock:
+    // AudioFlinger -> ThreadBase -> EffectChain -> EffectModule
+
+    // The EffectModule class is a wrapper object controlling the effect engine implementation
+    // in the effect library. It prevents concurrent calls to process() and command() functions
+    // from different client threads. It keeps a list of EffectHandle objects corresponding
+    // to all client applications using this effect and notifies applications of effect state,
+    // control or parameter changes. It manages the activation state machine to send appropriate
+    // reset, enable, disable commands to effect engine and provide volume
+    // ramping when effects are activated/deactivated.
+    // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
+    // the attached track(s) to accumulate their auxiliary channel.
+    class EffectModule: public RefBase {
+    public:
+        EffectModule(const wp<ThreadBase>& wThread,
+                        const wp<AudioFlinger::EffectChain>& chain,
+                        effect_descriptor_t *desc,
+                        int id,
+                        int sessionId);
+        ~EffectModule();
+
+        enum effect_state {
+            IDLE,
+            RESTART,
+            STARTING,
+            ACTIVE,
+            STOPPING,
+            STOPPED
+        };
+
+        int         id() { return mId; }
+        void process();
+        void updateState();
+        status_t command(uint32_t cmdCode,
+                         uint32_t cmdSize,
+                         void *pCmdData,
+                         uint32_t *replySize,
+                         void *pReplyData);
+
+        void reset_l();
+        status_t configure();
+        status_t init();
+        uint32_t state() {
+            return mState;
+        }
+        uint32_t status() {
+            return mStatus;
+        }
+        int sessionId() {
+            return mSessionId;
+        }
+        status_t    setEnabled(bool enabled);
+        bool isEnabled();
+
+        void        setInBuffer(int16_t *buffer) { mConfig.inputCfg.buffer.s16 = buffer; }
+        int16_t     *inBuffer() { return mConfig.inputCfg.buffer.s16; }
+        void        setOutBuffer(int16_t *buffer) { mConfig.outputCfg.buffer.s16 = buffer; }
+        int16_t     *outBuffer() { return mConfig.outputCfg.buffer.s16; }
+        void        setChain(const wp<EffectChain>& chain) { mChain = chain; }
+        void        setThread(const wp<ThreadBase>& thread) { mThread = thread; }
+
+        status_t addHandle(sp<EffectHandle>& handle);
+        void disconnect(const wp<EffectHandle>& handle);
+        size_t removeHandle (const wp<EffectHandle>& handle);
+
+        effect_descriptor_t& desc() { return mDescriptor; }
+        wp<EffectChain>&     chain() { return mChain; }
+
+        status_t         setDevice(uint32_t device);
+        status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);
+        status_t         setMode(uint32_t mode);
+
+        status_t         dump(int fd, const Vector<String16>& args);
+
+    protected:
+
+        // Maximum time allocated to effect engines to complete the turn off sequence
+        static const uint32_t MAX_DISABLE_TIME_MS = 10000;
+
+        EffectModule(const EffectModule&);
+        EffectModule& operator = (const EffectModule&);
+
+        status_t start_l();
+        status_t stop_l();
+
+        // update this table when AudioSystem::audio_devices or audio_device_e (in EffectApi.h) are modified
+        static const uint32_t sDeviceConvTable[];
+        static uint32_t deviceAudioSystemToEffectApi(uint32_t device);
+
+        // update this table when AudioSystem::audio_mode or audio_mode_e (in EffectApi.h) are modified
+        static const uint32_t sModeConvTable[];
+        static int modeAudioSystemToEffectApi(uint32_t mode);
+
+        Mutex               mLock;      // mutex for process, commands and handles list protection
+        wp<ThreadBase>      mThread;    // parent thread
+        wp<EffectChain>     mChain;     // parent effect chain
+        int                 mId;        // this instance unique ID
+        int                 mSessionId; // audio session ID
+        effect_descriptor_t mDescriptor;// effect descriptor received from effect engine
+        effect_config_t     mConfig;    // input and output audio configuration
+        effect_interface_t  mEffectInterface; // Effect module C API
+        status_t mStatus;               // initialization status
+        uint32_t mState;                // current activation state (effect_state)
+        Vector< wp<EffectHandle> > mHandles;    // list of client handles
+        uint32_t mMaxDisableWaitCnt;    // maximum grace period before forcing an effect off after
+                                        // sending disable command.
+        uint32_t mDisableWaitCnt;       // current process() calls count during disable period.
+    };
+
+    // The EffectHandle class implements the IEffect interface. It provides resources
+    // to receive parameter updates, keeps track of effect control
+    // ownership and state and has a pointer to the EffectModule object it is controlling.
+    // There is one EffectHandle object for each application controlling (or using)
+    // an effect module.
+    // The EffectHandle is obtained by calling AudioFlinger::createEffect().
+    class EffectHandle: public android::BnEffect {
+    public:
+
+        EffectHandle(const sp<EffectModule>& effect,
+                const sp<AudioFlinger::Client>& client,
+                const sp<IEffectClient>& effectClient,
+                int32_t priority);
+        virtual ~EffectHandle();
+
+        // IEffect
+        virtual status_t enable();
+        virtual status_t disable();
+        virtual status_t command(uint32_t cmdCode,
+                                 uint32_t cmdSize,
+                                 void *pCmdData,
+                                 uint32_t *replySize,
+                                 void *pReplyData);
+        virtual void disconnect();
+        virtual sp<IMemory> getCblk() const;
+        virtual status_t onTransact(uint32_t code, const Parcel& data,
+                Parcel* reply, uint32_t flags);
+
+
+        // Give or take control of effect module
+        void setControl(bool hasControl, bool signal);
+        void commandExecuted(uint32_t cmdCode,
+                             uint32_t cmdSize,
+                             void *pCmdData,
+                             uint32_t replySize,
+                             void *pReplyData);
+        void setEnabled(bool enabled);
+
+        // Getters
+        int id() { return mEffect->id(); }
+        int priority() { return mPriority; }
+        bool hasControl() { return mHasControl; }
+        sp<EffectModule> effect() { return mEffect; }
+
+        void dump(char* buffer, size_t size);
+
+    protected:
+
+        EffectHandle(const EffectHandle&);
+        EffectHandle& operator =(const EffectHandle&);
+
+        sp<EffectModule> mEffect;           // pointer to controlled EffectModule
+        sp<IEffectClient> mEffectClient;    // callback interface for client notifications
+        sp<Client>          mClient;        // client for shared memory allocation
+        sp<IMemory>         mCblkMemory;    // shared memory for control block
+        effect_param_cblk_t* mCblk;         // control block for deferred parameter setting via shared memory
+        uint8_t*            mBuffer;        // pointer to parameter area in shared memory
+        int mPriority;                      // client application priority to control the effect
+        bool mHasControl;                   // true if this handle is controlling the effect
+    };
+
+    // the EffectChain class represents a group of effects associated to one audio session.
+    // There can be any number of EffectChain objects per output mixer thread (PlaybackThread).
+    // The EffecChain with session ID 0 contains global effects applied to the output mix.
+    // Effects in this chain can be insert or auxiliary. Effects in other chains (attached to tracks)
+    // are insert only. The EffectChain maintains an ordered list of effect module, the order corresponding
+    // in the effect process order. When attached to a track (session ID != 0), it also provide it's own
+    // input buffer used by the track as accumulation buffer.
+    class EffectChain: public RefBase {
+    public:
+        EffectChain(const wp<ThreadBase>& wThread, int sessionId);
+        ~EffectChain();
+
+        void process_l();
+
+        void lock() {
+            mLock.lock();
+        }
+        void unlock() {
+            mLock.unlock();
+        }
+
+        status_t addEffect_l(const sp<EffectModule>& handle);
+        size_t removeEffect_l(const sp<EffectModule>& handle);
+
+        int sessionId() {
+            return mSessionId;
+        }
+
+        sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
+        sp<EffectModule> getEffectFromId_l(int id);
+        bool setVolume_l(uint32_t *left, uint32_t *right);
+        void setDevice_l(uint32_t device);
+        void setMode_l(uint32_t mode);
+
+        void setInBuffer(int16_t *buffer, bool ownsBuffer = false) {
+            mInBuffer = buffer;
+            mOwnInBuffer = ownsBuffer;
+        }
+        int16_t *inBuffer() {
+            return mInBuffer;
+        }
+        void setOutBuffer(int16_t *buffer) {
+            mOutBuffer = buffer;
+        }
+        int16_t *outBuffer() {
+            return mOutBuffer;
+        }
+
+        void startTrack() {mActiveTrackCnt++;}
+        void stopTrack() {mActiveTrackCnt--;}
+        int activeTracks() { return mActiveTrackCnt;}
+
+        uint32_t strategy() { return mStrategy; }
+        void setStrategy(uint32_t strategy)
+                 { mStrategy = strategy; }
+
+        status_t dump(int fd, const Vector<String16>& args);
+
+    protected:
+
+        EffectChain(const EffectChain&);
+        EffectChain& operator =(const EffectChain&);
+
+        wp<ThreadBase> mThread;     // parent mixer thread
+        Mutex mLock;                // mutex protecting effect list
+        Vector<sp<EffectModule> > mEffects; // list of effect modules
+        int mSessionId;             // audio session ID
+        int16_t *mInBuffer;         // chain input buffer
+        int16_t *mOutBuffer;        // chain output buffer
+        int mActiveTrackCnt;        // number of active tracks connected
+        bool mOwnInBuffer;          // true if the chain owns its input buffer
+        int mVolumeCtrlIdx;         // index of insert effect having control over volume
+        uint32_t mLeftVolume;       // previous volume on left channel
+        uint32_t mRightVolume;      // previous volume on right channel
+        uint32_t mNewLeftVolume;       // new volume on left channel
+        uint32_t mNewRightVolume;      // new volume on right channel
+        uint32_t mStrategy; // strategy for this effect chain
+    };
+
+    friend class RecordThread;
+    friend class PlaybackThread;
+
+
+    mutable     Mutex                               mLock;
+
+                DefaultKeyedVector< pid_t, wp<Client> >     mClients;
+
+                mutable     Mutex                   mHardwareLock;
+                AudioHardwareInterface*             mAudioHardware;
+    mutable     int                                 mHardwareStatus;
+
+
+                DefaultKeyedVector< int, sp<PlaybackThread> >  mPlaybackThreads;
+                PlaybackThread::stream_type_t       mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
+                float                               mMasterVolume;
+                bool                                mMasterMute;
+
+                DefaultKeyedVector< int, sp<RecordThread> >    mRecordThreads;
+
+                DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients;
+                volatile int32_t                    mNextUniqueId;
+#ifdef LVMX
+                int mLifeVibesClientPid;
+#endif
+                uint32_t mMode;
+
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_FLINGER_H
diff --git a/services/audioflinger/AudioHardwareGeneric.cpp b/services/audioflinger/AudioHardwareGeneric.cpp
new file mode 100644
index 0000000..d63c031
--- /dev/null
+++ b/services/audioflinger/AudioHardwareGeneric.cpp
@@ -0,0 +1,411 @@
+/*
+**
+** Copyright 2007, 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.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#define LOG_TAG "AudioHardware"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include "AudioHardwareGeneric.h"
+#include <media/AudioRecord.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+static char const * const kAudioDeviceName = "/dev/eac";
+
+// ----------------------------------------------------------------------------
+
+AudioHardwareGeneric::AudioHardwareGeneric()
+    : mOutput(0), mInput(0),  mFd(-1), mMicMute(false)
+{
+    mFd = ::open(kAudioDeviceName, O_RDWR);
+}
+
+AudioHardwareGeneric::~AudioHardwareGeneric()
+{
+    if (mFd >= 0) ::close(mFd);
+    closeOutputStream((AudioStreamOut *)mOutput);
+    closeInputStream((AudioStreamIn *)mInput);
+}
+
+status_t AudioHardwareGeneric::initCheck()
+{
+    if (mFd >= 0) {
+        if (::access(kAudioDeviceName, O_RDWR) == NO_ERROR)
+            return NO_ERROR;
+    }
+    return NO_INIT;
+}
+
+AudioStreamOut* AudioHardwareGeneric::openOutputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
+{
+    AutoMutex lock(mLock);
+
+    // only one output stream allowed
+    if (mOutput) {
+        if (status) {
+            *status = INVALID_OPERATION;
+        }
+        return 0;
+    }
+
+    // create new output stream
+    AudioStreamOutGeneric* out = new AudioStreamOutGeneric();
+    status_t lStatus = out->set(this, mFd, devices, format, channels, sampleRate);
+    if (status) {
+        *status = lStatus;
+    }
+    if (lStatus == NO_ERROR) {
+        mOutput = out;
+    } else {
+        delete out;
+    }
+    return mOutput;
+}
+
+void AudioHardwareGeneric::closeOutputStream(AudioStreamOut* out) {
+    if (mOutput && out == mOutput) {
+        delete mOutput;
+        mOutput = 0;
+    }
+}
+
+AudioStreamIn* AudioHardwareGeneric::openInputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
+        status_t *status, AudioSystem::audio_in_acoustics acoustics)
+{
+    // check for valid input source
+    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
+        return 0;
+    }
+
+    AutoMutex lock(mLock);
+
+    // only one input stream allowed
+    if (mInput) {
+        if (status) {
+            *status = INVALID_OPERATION;
+        }
+        return 0;
+    }
+
+    // create new output stream
+    AudioStreamInGeneric* in = new AudioStreamInGeneric();
+    status_t lStatus = in->set(this, mFd, devices, format, channels, sampleRate, acoustics);
+    if (status) {
+        *status = lStatus;
+    }
+    if (lStatus == NO_ERROR) {
+        mInput = in;
+    } else {
+        delete in;
+    }
+    return mInput;
+}
+
+void AudioHardwareGeneric::closeInputStream(AudioStreamIn* in) {
+    if (mInput && in == mInput) {
+        delete mInput;
+        mInput = 0;
+    }
+}
+
+status_t AudioHardwareGeneric::setVoiceVolume(float v)
+{
+    // Implement: set voice volume
+    return NO_ERROR;
+}
+
+status_t AudioHardwareGeneric::setMasterVolume(float v)
+{
+    // Implement: set master volume
+    // return error - software mixer will handle it
+    return INVALID_OPERATION;
+}
+
+status_t AudioHardwareGeneric::setMicMute(bool state)
+{
+    mMicMute = state;
+    return NO_ERROR;
+}
+
+status_t AudioHardwareGeneric::getMicMute(bool* state)
+{
+    *state = mMicMute;
+    return NO_ERROR;
+}
+
+status_t AudioHardwareGeneric::dumpInternals(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    result.append("AudioHardwareGeneric::dumpInternals\n");
+    snprintf(buffer, SIZE, "\tmFd: %d mMicMute: %s\n",  mFd, mMicMute? "true": "false");
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioHardwareGeneric::dump(int fd, const Vector<String16>& args)
+{
+    dumpInternals(fd, args);
+    if (mInput) {
+        mInput->dump(fd, args);
+    }
+    if (mOutput) {
+        mOutput->dump(fd, args);
+    }
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+status_t AudioStreamOutGeneric::set(
+        AudioHardwareGeneric *hw,
+        int fd,
+        uint32_t devices,
+        int *pFormat,
+        uint32_t *pChannels,
+        uint32_t *pRate)
+{
+    int lFormat = pFormat ? *pFormat : 0;
+    uint32_t lChannels = pChannels ? *pChannels : 0;
+    uint32_t lRate = pRate ? *pRate : 0;
+
+    // fix up defaults
+    if (lFormat == 0) lFormat = format();
+    if (lChannels == 0) lChannels = channels();
+    if (lRate == 0) lRate = sampleRate();
+
+    // check values
+    if ((lFormat != format()) ||
+            (lChannels != channels()) ||
+            (lRate != sampleRate())) {
+        if (pFormat) *pFormat = format();
+        if (pChannels) *pChannels = channels();
+        if (pRate) *pRate = sampleRate();
+        return BAD_VALUE;
+    }
+
+    if (pFormat) *pFormat = lFormat;
+    if (pChannels) *pChannels = lChannels;
+    if (pRate) *pRate = lRate;
+
+    mAudioHardware = hw;
+    mFd = fd;
+    mDevice = devices;
+    return NO_ERROR;
+}
+
+AudioStreamOutGeneric::~AudioStreamOutGeneric()
+{
+}
+
+ssize_t AudioStreamOutGeneric::write(const void* buffer, size_t bytes)
+{
+    Mutex::Autolock _l(mLock);
+    return ssize_t(::write(mFd, buffer, bytes));
+}
+
+status_t AudioStreamOutGeneric::standby()
+{
+    // Implement: audio hardware to standby mode
+    return NO_ERROR;
+}
+
+status_t AudioStreamOutGeneric::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "AudioStreamOutGeneric::dump\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tformat: %d\n", format());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioStreamOutGeneric::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 key = String8(AudioParameter::keyRouting);
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("setParameters() %s", keyValuePairs.string());
+
+    if (param.getInt(key, device) == NO_ERROR) {
+        mDevice = device;
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 AudioStreamOutGeneric::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8(AudioParameter::keyRouting);
+
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
+status_t AudioStreamOutGeneric::getRenderPosition(uint32_t *dspFrames)
+{
+    return INVALID_OPERATION;
+}
+
+// ----------------------------------------------------------------------------
+
+// record functions
+status_t AudioStreamInGeneric::set(
+        AudioHardwareGeneric *hw,
+        int fd,
+        uint32_t devices,
+        int *pFormat,
+        uint32_t *pChannels,
+        uint32_t *pRate,
+        AudioSystem::audio_in_acoustics acoustics)
+{
+    if (pFormat == 0 || pChannels == 0 || pRate == 0) return BAD_VALUE;
+    LOGV("AudioStreamInGeneric::set(%p, %d, %d, %d, %u)", hw, fd, *pFormat, *pChannels, *pRate);
+    // check values
+    if ((*pFormat != format()) ||
+        (*pChannels != channels()) ||
+        (*pRate != sampleRate())) {
+        LOGE("Error opening input channel");
+        *pFormat = format();
+        *pChannels = channels();
+        *pRate = sampleRate();
+        return BAD_VALUE;
+    }
+
+    mAudioHardware = hw;
+    mFd = fd;
+    mDevice = devices;
+    return NO_ERROR;
+}
+
+AudioStreamInGeneric::~AudioStreamInGeneric()
+{
+}
+
+ssize_t AudioStreamInGeneric::read(void* buffer, ssize_t bytes)
+{
+    AutoMutex lock(mLock);
+    if (mFd < 0) {
+        LOGE("Attempt to read from unopened device");
+        return NO_INIT;
+    }
+    return ::read(mFd, buffer, bytes);
+}
+
+status_t AudioStreamInGeneric::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "AudioStreamInGeneric::dump\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tformat: %d\n", format());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tdevice: %d\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tmAudioHardware: %p\n", mAudioHardware);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioStreamInGeneric::setParameters(const String8& keyValuePairs)
+{
+    AudioParameter param = AudioParameter(keyValuePairs);
+    String8 key = String8(AudioParameter::keyRouting);
+    status_t status = NO_ERROR;
+    int device;
+    LOGV("setParameters() %s", keyValuePairs.string());
+
+    if (param.getInt(key, device) == NO_ERROR) {
+        mDevice = device;
+        param.remove(key);
+    }
+
+    if (param.size()) {
+        status = BAD_VALUE;
+    }
+    return status;
+}
+
+String8 AudioStreamInGeneric::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    String8 value;
+    String8 key = String8(AudioParameter::keyRouting);
+
+    if (param.get(key, value) == NO_ERROR) {
+        param.addInt(key, (int)mDevice);
+    }
+
+    LOGV("getParameters() %s", param.toString().string());
+    return param.toString();
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/audioflinger/AudioHardwareGeneric.h b/services/audioflinger/AudioHardwareGeneric.h
new file mode 100644
index 0000000..aa4e78d
--- /dev/null
+++ b/services/audioflinger/AudioHardwareGeneric.h
@@ -0,0 +1,151 @@
+/*
+**
+** Copyright 2007, 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 ANDROID_AUDIO_HARDWARE_GENERIC_H
+#define ANDROID_AUDIO_HARDWARE_GENERIC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/threads.h>
+
+#include <hardware_legacy/AudioHardwareBase.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class AudioHardwareGeneric;
+
+class AudioStreamOutGeneric : public AudioStreamOut {
+public:
+                        AudioStreamOutGeneric() : mAudioHardware(0), mFd(-1) {}
+    virtual             ~AudioStreamOutGeneric();
+
+    virtual status_t    set(
+            AudioHardwareGeneric *hw,
+            int mFd,
+            uint32_t devices,
+            int *pFormat,
+            uint32_t *pChannels,
+            uint32_t *pRate);
+
+    virtual uint32_t    sampleRate() const { return 44100; }
+    virtual size_t      bufferSize() const { return 4096; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
+    virtual int         format() const { return AudioSystem::PCM_16_BIT; }
+    virtual uint32_t    latency() const { return 20; }
+    virtual status_t    setVolume(float left, float right) { return INVALID_OPERATION; }
+    virtual ssize_t     write(const void* buffer, size_t bytes);
+    virtual status_t    standby();
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+    virtual status_t    getRenderPosition(uint32_t *dspFrames);
+
+private:
+    AudioHardwareGeneric *mAudioHardware;
+    Mutex   mLock;
+    int     mFd;
+    uint32_t mDevice;
+};
+
+class AudioStreamInGeneric : public AudioStreamIn {
+public:
+                        AudioStreamInGeneric() : mAudioHardware(0), mFd(-1) {}
+    virtual             ~AudioStreamInGeneric();
+
+    virtual status_t    set(
+            AudioHardwareGeneric *hw,
+            int mFd,
+            uint32_t devices,
+            int *pFormat,
+            uint32_t *pChannels,
+            uint32_t *pRate,
+            AudioSystem::audio_in_acoustics acoustics);
+
+    virtual uint32_t    sampleRate() const { return 8000; }
+    virtual size_t      bufferSize() const { return 320; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_IN_MONO; }
+    virtual int         format() const { return AudioSystem::PCM_16_BIT; }
+    virtual status_t    setGain(float gain) { return INVALID_OPERATION; }
+    virtual ssize_t     read(void* buffer, ssize_t bytes);
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    standby() { return NO_ERROR; }
+    virtual status_t    setParameters(const String8& keyValuePairs);
+    virtual String8     getParameters(const String8& keys);
+    virtual unsigned int  getInputFramesLost() const { return 0; }
+
+private:
+    AudioHardwareGeneric *mAudioHardware;
+    Mutex   mLock;
+    int     mFd;
+    uint32_t mDevice;
+};
+
+
+class AudioHardwareGeneric : public AudioHardwareBase
+{
+public:
+                        AudioHardwareGeneric();
+    virtual             ~AudioHardwareGeneric();
+    virtual status_t    initCheck();
+    virtual status_t    setVoiceVolume(float volume);
+    virtual status_t    setMasterVolume(float volume);
+
+    // mic mute
+    virtual status_t    setMicMute(bool state);
+    virtual status_t    getMicMute(bool* state);
+
+    // create I/O streams
+    virtual AudioStreamOut* openOutputStream(
+            uint32_t devices,
+            int *format=0,
+            uint32_t *channels=0,
+            uint32_t *sampleRate=0,
+            status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
+
+    virtual AudioStreamIn* openInputStream(
+            uint32_t devices,
+            int *format,
+            uint32_t *channels,
+            uint32_t *sampleRate,
+            status_t *status,
+            AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
+
+            void            closeOutputStream(AudioStreamOutGeneric* out);
+            void            closeInputStream(AudioStreamInGeneric* in);
+protected:
+    virtual status_t        dump(int fd, const Vector<String16>& args);
+
+private:
+    status_t                dumpInternals(int fd, const Vector<String16>& args);
+
+    Mutex                   mLock;
+    AudioStreamOutGeneric   *mOutput;
+    AudioStreamInGeneric    *mInput;
+    int                     mFd;
+    bool                    mMicMute;
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_HARDWARE_GENERIC_H
diff --git a/services/audioflinger/AudioHardwareInterface.cpp b/services/audioflinger/AudioHardwareInterface.cpp
new file mode 100644
index 0000000..9a4a7f9
--- /dev/null
+++ b/services/audioflinger/AudioHardwareInterface.cpp
@@ -0,0 +1,182 @@
+/*
+**
+** Copyright 2007, 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.
+*/
+
+#include <cutils/properties.h>
+#include <string.h>
+#include <unistd.h>
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "AudioHardwareInterface"
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include "AudioHardwareStub.h"
+#include "AudioHardwareGeneric.h"
+#ifdef WITH_A2DP
+#include "A2dpAudioInterface.h"
+#endif
+
+#ifdef ENABLE_AUDIO_DUMP
+#include "AudioDumpInterface.h"
+#endif
+
+
+// change to 1 to log routing calls
+#define LOG_ROUTING_CALLS 1
+
+namespace android {
+
+#if LOG_ROUTING_CALLS
+static const char* routingModeStrings[] =
+{
+    "OUT OF RANGE",
+    "INVALID",
+    "CURRENT",
+    "NORMAL",
+    "RINGTONE",
+    "IN_CALL"
+};
+
+static const char* routeNone = "NONE";
+
+static const char* displayMode(int mode)
+{
+    if ((mode < -2) || (mode > 2))
+        return routingModeStrings[0];
+    return routingModeStrings[mode+3];
+}
+#endif
+
+// ----------------------------------------------------------------------------
+
+AudioHardwareInterface* AudioHardwareInterface::create()
+{
+    /*
+     * FIXME: This code needs to instantiate the correct audio device
+     * interface. For now - we use compile-time switches.
+     */
+    AudioHardwareInterface* hw = 0;
+    char value[PROPERTY_VALUE_MAX];
+
+#ifdef GENERIC_AUDIO
+    hw = new AudioHardwareGeneric();
+#else
+    // if running in emulation - use the emulator driver
+    if (property_get("ro.kernel.qemu", value, 0)) {
+        LOGD("Running in emulation - using generic audio driver");
+        hw = new AudioHardwareGeneric();
+    }
+    else {
+        LOGV("Creating Vendor Specific AudioHardware");
+        hw = createAudioHardware();
+    }
+#endif
+    if (hw->initCheck() != NO_ERROR) {
+        LOGW("Using stubbed audio hardware. No sound will be produced.");
+        delete hw;
+        hw = new AudioHardwareStub();
+    }
+    
+#ifdef WITH_A2DP
+    hw = new A2dpAudioInterface(hw);
+#endif
+
+#ifdef ENABLE_AUDIO_DUMP
+    // This code adds a record of buffers in a file to write calls made by AudioFlinger.
+    // It replaces the current AudioHardwareInterface object by an intermediate one which
+    // will record buffers in a file (after sending them to hardware) for testing purpose.
+    // This feature is enabled by defining symbol ENABLE_AUDIO_DUMP.
+    // The output file is set with setParameters("test_cmd_file_name=<name>"). Pause are not recorded in the file.
+    LOGV("opening PCM dump interface");
+    hw = new AudioDumpInterface(hw);    // replace interface
+#endif
+    return hw;
+}
+
+AudioStreamOut::~AudioStreamOut()
+{
+}
+
+AudioStreamIn::~AudioStreamIn() {}
+
+AudioHardwareBase::AudioHardwareBase()
+{
+    mMode = 0;
+}
+
+status_t AudioHardwareBase::setMode(int mode)
+{
+#if LOG_ROUTING_CALLS
+    LOGD("setMode(%s)", displayMode(mode));
+#endif
+    if ((mode < 0) || (mode >= AudioSystem::NUM_MODES))
+        return BAD_VALUE;
+    if (mMode == mode)
+        return ALREADY_EXISTS;
+    mMode = mode;
+    return NO_ERROR;
+}
+
+// default implementation
+status_t AudioHardwareBase::setParameters(const String8& keyValuePairs)
+{
+    return NO_ERROR;
+}
+
+// default implementation
+String8 AudioHardwareBase::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
+// default implementation
+size_t AudioHardwareBase::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+    if (sampleRate != 8000) {
+        LOGW("getInputBufferSize bad sampling rate: %d", sampleRate);
+        return 0;
+    }
+    if (format != AudioSystem::PCM_16_BIT) {
+        LOGW("getInputBufferSize bad format: %d", format);
+        return 0;
+    }
+    if (channelCount != 1) {
+        LOGW("getInputBufferSize bad channel count: %d", channelCount);
+        return 0;
+    }
+
+    return 320;
+}
+
+status_t AudioHardwareBase::dumpState(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "AudioHardwareBase::dumpState\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tmMode: %d\n", mMode);
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    dump(fd, args);  // Dump the state of the concrete child.
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/audioflinger/AudioHardwareStub.cpp b/services/audioflinger/AudioHardwareStub.cpp
new file mode 100644
index 0000000..d481150
--- /dev/null
+++ b/services/audioflinger/AudioHardwareStub.cpp
@@ -0,0 +1,209 @@
+/* //device/servers/AudioFlinger/AudioHardwareStub.cpp
+**
+** Copyright 2007, 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.
+*/
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <utils/String8.h>
+
+#include "AudioHardwareStub.h"
+#include <media/AudioRecord.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+AudioHardwareStub::AudioHardwareStub() : mMicMute(false)
+{
+}
+
+AudioHardwareStub::~AudioHardwareStub()
+{
+}
+
+status_t AudioHardwareStub::initCheck()
+{
+    return NO_ERROR;
+}
+
+AudioStreamOut* AudioHardwareStub::openOutputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
+{
+    AudioStreamOutStub* out = new AudioStreamOutStub();
+    status_t lStatus = out->set(format, channels, sampleRate);
+    if (status) {
+        *status = lStatus;
+    }
+    if (lStatus == NO_ERROR)
+        return out;
+    delete out;
+    return 0;
+}
+
+void AudioHardwareStub::closeOutputStream(AudioStreamOut* out)
+{
+    delete out;
+}
+
+AudioStreamIn* AudioHardwareStub::openInputStream(
+        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate,
+        status_t *status, AudioSystem::audio_in_acoustics acoustics)
+{
+    // check for valid input source
+    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
+        return 0;
+    }
+
+    AudioStreamInStub* in = new AudioStreamInStub();
+    status_t lStatus = in->set(format, channels, sampleRate, acoustics);
+    if (status) {
+        *status = lStatus;
+    }
+    if (lStatus == NO_ERROR)
+        return in;
+    delete in;
+    return 0;
+}
+
+void AudioHardwareStub::closeInputStream(AudioStreamIn* in)
+{
+    delete in;
+}
+
+status_t AudioHardwareStub::setVoiceVolume(float volume)
+{
+    return NO_ERROR;
+}
+
+status_t AudioHardwareStub::setMasterVolume(float volume)
+{
+    return NO_ERROR;
+}
+
+status_t AudioHardwareStub::dumpInternals(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    result.append("AudioHardwareStub::dumpInternals\n");
+    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioHardwareStub::dump(int fd, const Vector<String16>& args)
+{
+    dumpInternals(fd, args);
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+status_t AudioStreamOutStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate)
+{
+    if (pFormat) *pFormat = format();
+    if (pChannels) *pChannels = channels();
+    if (pRate) *pRate = sampleRate();
+
+    return NO_ERROR;
+}
+
+ssize_t AudioStreamOutStub::write(const void* buffer, size_t bytes)
+{
+    // fake timing for audio output
+    usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
+    return bytes;
+}
+
+status_t AudioStreamOutStub::standby()
+{
+    return NO_ERROR;
+}
+
+status_t AudioStreamOutStub::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "AudioStreamOutStub::dump\n");
+    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
+    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
+    snprintf(buffer, SIZE, "\tformat: %d\n", format());
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+String8 AudioStreamOutStub::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
+status_t AudioStreamOutStub::getRenderPosition(uint32_t *dspFrames)
+{
+    return INVALID_OPERATION;
+}
+
+// ----------------------------------------------------------------------------
+
+status_t AudioStreamInStub::set(int *pFormat, uint32_t *pChannels, uint32_t *pRate,
+                AudioSystem::audio_in_acoustics acoustics)
+{
+    return NO_ERROR;
+}
+
+ssize_t AudioStreamInStub::read(void* buffer, ssize_t bytes)
+{
+    // fake timing for audio input
+    usleep(bytes * 1000000 / sizeof(int16_t) / AudioSystem::popCount(channels()) / sampleRate());
+    memset(buffer, 0, bytes);
+    return bytes;
+}
+
+status_t AudioStreamInStub::dump(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "AudioStreamInStub::dump\n");
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "\tformat: %d\n", format());
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+String8 AudioStreamInStub::getParameters(const String8& keys)
+{
+    AudioParameter param = AudioParameter(keys);
+    return param.toString();
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/audioflinger/AudioHardwareStub.h b/services/audioflinger/AudioHardwareStub.h
new file mode 100644
index 0000000..06a29de
--- /dev/null
+++ b/services/audioflinger/AudioHardwareStub.h
@@ -0,0 +1,106 @@
+/* //device/servers/AudioFlinger/AudioHardwareStub.h
+**
+** Copyright 2007, 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 ANDROID_AUDIO_HARDWARE_STUB_H
+#define ANDROID_AUDIO_HARDWARE_STUB_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <hardware_legacy/AudioHardwareBase.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class AudioStreamOutStub : public AudioStreamOut {
+public:
+    virtual status_t    set(int *pFormat, uint32_t *pChannels, uint32_t *pRate);
+    virtual uint32_t    sampleRate() const { return 44100; }
+    virtual size_t      bufferSize() const { return 4096; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
+    virtual int         format() const { return AudioSystem::PCM_16_BIT; }
+    virtual uint32_t    latency() const { return 0; }
+    virtual status_t    setVolume(float left, float right) { return NO_ERROR; }
+    virtual ssize_t     write(const void* buffer, size_t bytes);
+    virtual status_t    standby();
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    setParameters(const String8& keyValuePairs) { return NO_ERROR;}
+    virtual String8     getParameters(const String8& keys);
+    virtual status_t    getRenderPosition(uint32_t *dspFrames);
+};
+
+class AudioStreamInStub : public AudioStreamIn {
+public:
+    virtual status_t    set(int *pFormat, uint32_t *pChannels, uint32_t *pRate, AudioSystem::audio_in_acoustics acoustics);
+    virtual uint32_t    sampleRate() const { return 8000; }
+    virtual size_t      bufferSize() const { return 320; }
+    virtual uint32_t    channels() const { return AudioSystem::CHANNEL_IN_MONO; }
+    virtual int         format() const { return AudioSystem::PCM_16_BIT; }
+    virtual status_t    setGain(float gain) { return NO_ERROR; }
+    virtual ssize_t     read(void* buffer, ssize_t bytes);
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    standby() { return NO_ERROR; }
+    virtual status_t    setParameters(const String8& keyValuePairs) { return NO_ERROR;}
+    virtual String8     getParameters(const String8& keys);
+    virtual unsigned int  getInputFramesLost() const { return 0; }
+};
+
+class AudioHardwareStub : public  AudioHardwareBase
+{
+public:
+                        AudioHardwareStub();
+    virtual             ~AudioHardwareStub();
+    virtual status_t    initCheck();
+    virtual status_t    setVoiceVolume(float volume);
+    virtual status_t    setMasterVolume(float volume);
+
+    // mic mute
+    virtual status_t    setMicMute(bool state) { mMicMute = state;  return  NO_ERROR; }
+    virtual status_t    getMicMute(bool* state) { *state = mMicMute ; return NO_ERROR; }
+
+    // create I/O streams
+    virtual AudioStreamOut* openOutputStream(
+                                uint32_t devices,
+                                int *format=0,
+                                uint32_t *channels=0,
+                                uint32_t *sampleRate=0,
+                                status_t *status=0);
+    virtual    void        closeOutputStream(AudioStreamOut* out);
+
+    virtual AudioStreamIn* openInputStream(
+                                uint32_t devices,
+                                int *format,
+                                uint32_t *channels,
+                                uint32_t *sampleRate,
+                                status_t *status,
+                                AudioSystem::audio_in_acoustics acoustics);
+    virtual    void        closeInputStream(AudioStreamIn* in);
+
+protected:
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+
+            bool        mMicMute;
+private:
+    status_t            dumpInternals(int fd, const Vector<String16>& args);
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_AUDIO_HARDWARE_STUB_H
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
new file mode 100644
index 0000000..8aaa325
--- /dev/null
+++ b/services/audioflinger/AudioMixer.cpp
@@ -0,0 +1,1195 @@
+/* //device/include/server/AudioFlinger/AudioMixer.cpp
+**
+** Copyright 2007, 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_TAG "AudioMixer"
+//#define LOG_NDEBUG 0
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include "AudioMixer.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+static inline int16_t clamp16(int32_t sample)
+{
+    if ((sample>>15) ^ (sample>>31))
+        sample = 0x7FFF ^ (sample>>31);
+    return sample;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioMixer::AudioMixer(size_t frameCount, uint32_t sampleRate)
+    :   mActiveTrack(0), mTrackNames(0), mSampleRate(sampleRate)
+{
+    mState.enabledTracks= 0;
+    mState.needsChanged = 0;
+    mState.frameCount   = frameCount;
+    mState.outputTemp   = 0;
+    mState.resampleTemp = 0;
+    mState.hook         = process__nop;
+    track_t* t = mState.tracks;
+    for (int i=0 ; i<32 ; i++) {
+        t->needs = 0;
+        t->volume[0] = UNITY_GAIN;
+        t->volume[1] = UNITY_GAIN;
+        t->volumeInc[0] = 0;
+        t->volumeInc[1] = 0;
+        t->auxLevel = 0;
+        t->auxInc = 0;
+        t->channelCount = 2;
+        t->enabled = 0;
+        t->format = 16;
+        t->buffer.raw = 0;
+        t->bufferProvider = 0;
+        t->hook = 0;
+        t->resampler = 0;
+        t->sampleRate = mSampleRate;
+        t->in = 0;
+        t->mainBuffer = NULL;
+        t->auxBuffer = NULL;
+        t++;
+    }
+}
+
+ AudioMixer::~AudioMixer()
+ {
+     track_t* t = mState.tracks;
+     for (int i=0 ; i<32 ; i++) {
+         delete t->resampler;
+         t++;
+     }
+     delete [] mState.outputTemp;
+     delete [] mState.resampleTemp;
+ }
+
+ int AudioMixer::getTrackName()
+ {
+    uint32_t names = mTrackNames;
+    uint32_t mask = 1;
+    int n = 0;
+    while (names & mask) {
+        mask <<= 1;
+        n++;
+    }
+    if (mask) {
+        LOGV("add track (%d)", n);
+        mTrackNames |= mask;
+        return TRACK0 + n;
+    }
+    return -1;
+ }
+
+ void AudioMixer::invalidateState(uint32_t mask)
+ {
+    if (mask) {
+        mState.needsChanged |= mask;
+        mState.hook = process__validate;
+    }
+ }
+
+ void AudioMixer::deleteTrackName(int name)
+ {
+    name -= TRACK0;
+    if (uint32_t(name) < MAX_NUM_TRACKS) {
+        LOGV("deleteTrackName(%d)", name);
+        track_t& track(mState.tracks[ name ]);
+        if (track.enabled != 0) {
+            track.enabled = 0;
+            invalidateState(1<<name);
+        }
+        if (track.resampler) {
+            // delete  the resampler
+            delete track.resampler;
+            track.resampler = 0;
+            track.sampleRate = mSampleRate;
+            invalidateState(1<<name);
+        }
+        track.volumeInc[0] = 0;
+        track.volumeInc[1] = 0;
+        mTrackNames &= ~(1<<name);
+    }
+ }
+
+status_t AudioMixer::enable(int name)
+{
+    switch (name) {
+        case MIXING: {
+            if (mState.tracks[ mActiveTrack ].enabled != 1) {
+                mState.tracks[ mActiveTrack ].enabled = 1;
+                LOGV("enable(%d)", mActiveTrack);
+                invalidateState(1<<mActiveTrack);
+            }
+        } break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+status_t AudioMixer::disable(int name)
+{
+    switch (name) {
+        case MIXING: {
+            if (mState.tracks[ mActiveTrack ].enabled != 0) {
+                mState.tracks[ mActiveTrack ].enabled = 0;
+                LOGV("disable(%d)", mActiveTrack);
+                invalidateState(1<<mActiveTrack);
+            }
+        } break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
+status_t AudioMixer::setActiveTrack(int track)
+{
+    if (uint32_t(track-TRACK0) >= MAX_NUM_TRACKS) {
+        return BAD_VALUE;
+    }
+    mActiveTrack = track - TRACK0;
+    return NO_ERROR;
+}
+
+status_t AudioMixer::setParameter(int target, int name, void *value)
+{
+    int valueInt = (int)value;
+    int32_t *valueBuf = (int32_t *)value;
+
+    switch (target) {
+    case TRACK:
+        if (name == CHANNEL_COUNT) {
+            if ((uint32_t(valueInt) <= MAX_NUM_CHANNELS) && (valueInt)) {
+                if (mState.tracks[ mActiveTrack ].channelCount != valueInt) {
+                    mState.tracks[ mActiveTrack ].channelCount = valueInt;
+                    LOGV("setParameter(TRACK, CHANNEL_COUNT, %d)", valueInt);
+                    invalidateState(1<<mActiveTrack);
+                }
+                return NO_ERROR;
+            }
+        }
+        if (name == MAIN_BUFFER) {
+            if (mState.tracks[ mActiveTrack ].mainBuffer != valueBuf) {
+                mState.tracks[ mActiveTrack ].mainBuffer = valueBuf;
+                LOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
+                invalidateState(1<<mActiveTrack);
+            }
+            return NO_ERROR;
+        }
+        if (name == AUX_BUFFER) {
+            if (mState.tracks[ mActiveTrack ].auxBuffer != valueBuf) {
+                mState.tracks[ mActiveTrack ].auxBuffer = valueBuf;
+                LOGV("setParameter(TRACK, AUX_BUFFER, %p)", valueBuf);
+                invalidateState(1<<mActiveTrack);
+            }
+            return NO_ERROR;
+        }
+
+        break;
+    case RESAMPLE:
+        if (name == SAMPLE_RATE) {
+            if (valueInt > 0) {
+                track_t& track = mState.tracks[ mActiveTrack ];
+                if (track.setResampler(uint32_t(valueInt), mSampleRate)) {
+                    LOGV("setParameter(RESAMPLE, SAMPLE_RATE, %u)",
+                            uint32_t(valueInt));
+                    invalidateState(1<<mActiveTrack);
+                }
+                return NO_ERROR;
+            }
+        }
+        break;
+    case RAMP_VOLUME:
+    case VOLUME:
+        if ((uint32_t(name-VOLUME0) < MAX_NUM_CHANNELS)) {
+            track_t& track = mState.tracks[ mActiveTrack ];
+            if (track.volume[name-VOLUME0] != valueInt) {
+                LOGV("setParameter(VOLUME, VOLUME0/1: %04x)", valueInt);
+                track.prevVolume[name-VOLUME0] = track.volume[name-VOLUME0] << 16;
+                track.volume[name-VOLUME0] = valueInt;
+                if (target == VOLUME) {
+                    track.prevVolume[name-VOLUME0] = valueInt << 16;
+                    track.volumeInc[name-VOLUME0] = 0;
+                } else {
+                    int32_t d = (valueInt<<16) - track.prevVolume[name-VOLUME0];
+                    int32_t volInc = d / int32_t(mState.frameCount);
+                    track.volumeInc[name-VOLUME0] = volInc;
+                    if (volInc == 0) {
+                        track.prevVolume[name-VOLUME0] = valueInt << 16;
+                    }
+                }
+                invalidateState(1<<mActiveTrack);
+            }
+            return NO_ERROR;
+        } else if (name == AUXLEVEL) {
+            track_t& track = mState.tracks[ mActiveTrack ];
+            if (track.auxLevel != valueInt) {
+                LOGV("setParameter(VOLUME, AUXLEVEL: %04x)", valueInt);
+                track.prevAuxLevel = track.auxLevel << 16;
+                track.auxLevel = valueInt;
+                if (target == VOLUME) {
+                    track.prevAuxLevel = valueInt << 16;
+                    track.auxInc = 0;
+                } else {
+                    int32_t d = (valueInt<<16) - track.prevAuxLevel;
+                    int32_t volInc = d / int32_t(mState.frameCount);
+                    track.auxInc = volInc;
+                    if (volInc == 0) {
+                        track.prevAuxLevel = valueInt << 16;
+                    }
+                }
+                invalidateState(1<<mActiveTrack);
+            }
+            return NO_ERROR;
+        }
+        break;
+    }
+    return BAD_VALUE;
+}
+
+bool AudioMixer::track_t::setResampler(uint32_t value, uint32_t devSampleRate)
+{
+    if (value!=devSampleRate || resampler) {
+        if (sampleRate != value) {
+            sampleRate = value;
+            if (resampler == 0) {
+                resampler = AudioResampler::create(
+                        format, channelCount, devSampleRate);
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+bool AudioMixer::track_t::doesResample() const
+{
+    return resampler != 0;
+}
+
+inline
+void AudioMixer::track_t::adjustVolumeRamp(bool aux)
+{
+    for (int i=0 ; i<2 ; i++) {
+        if (((volumeInc[i]>0) && (((prevVolume[i]+volumeInc[i])>>16) >= volume[i])) ||
+            ((volumeInc[i]<0) && (((prevVolume[i]+volumeInc[i])>>16) <= volume[i]))) {
+            volumeInc[i] = 0;
+            prevVolume[i] = volume[i]<<16;
+        }
+    }
+    if (aux) {
+        if (((auxInc>0) && (((prevAuxLevel+auxInc)>>16) >= auxLevel)) ||
+            ((auxInc<0) && (((prevAuxLevel+auxInc)>>16) <= auxLevel))) {
+            auxInc = 0;
+            prevAuxLevel = auxLevel<<16;
+        }
+    }
+}
+
+
+status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
+{
+    mState.tracks[ mActiveTrack ].bufferProvider = buffer;
+    return NO_ERROR;
+}
+
+
+
+void AudioMixer::process()
+{
+    mState.hook(&mState);
+}
+
+
+void AudioMixer::process__validate(state_t* state)
+{
+    LOGW_IF(!state->needsChanged,
+        "in process__validate() but nothing's invalid");
+
+    uint32_t changed = state->needsChanged;
+    state->needsChanged = 0; // clear the validation flag
+
+    // recompute which tracks are enabled / disabled
+    uint32_t enabled = 0;
+    uint32_t disabled = 0;
+    while (changed) {
+        const int i = 31 - __builtin_clz(changed);
+        const uint32_t mask = 1<<i;
+        changed &= ~mask;
+        track_t& t = state->tracks[i];
+        (t.enabled ? enabled : disabled) |= mask;
+    }
+    state->enabledTracks &= ~disabled;
+    state->enabledTracks |=  enabled;
+
+    // compute everything we need...
+    int countActiveTracks = 0;
+    int all16BitsStereoNoResample = 1;
+    int resampling = 0;
+    int volumeRamp = 0;
+    uint32_t en = state->enabledTracks;
+    while (en) {
+        const int i = 31 - __builtin_clz(en);
+        en &= ~(1<<i);
+
+        countActiveTracks++;
+        track_t& t = state->tracks[i];
+        uint32_t n = 0;
+        n |= NEEDS_CHANNEL_1 + t.channelCount - 1;
+        n |= NEEDS_FORMAT_16;
+        n |= t.doesResample() ? NEEDS_RESAMPLE_ENABLED : NEEDS_RESAMPLE_DISABLED;
+        if (t.auxLevel != 0 && t.auxBuffer != NULL) {
+            n |= NEEDS_AUX_ENABLED;
+        }
+
+        if (t.volumeInc[0]|t.volumeInc[1]) {
+            volumeRamp = 1;
+        } else if (!t.doesResample() && t.volumeRL == 0) {
+            n |= NEEDS_MUTE_ENABLED;
+        }
+        t.needs = n;
+
+        if ((n & NEEDS_MUTE__MASK) == NEEDS_MUTE_ENABLED) {
+            t.hook = track__nop;
+        } else {
+            if ((n & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
+                all16BitsStereoNoResample = 0;
+            }
+            if ((n & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
+                all16BitsStereoNoResample = 0;
+                resampling = 1;
+                t.hook = track__genericResample;
+            } else {
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_1){
+                    t.hook = track__16BitsMono;
+                    all16BitsStereoNoResample = 0;
+                }
+                if ((n & NEEDS_CHANNEL_COUNT__MASK) == NEEDS_CHANNEL_2){
+                    t.hook = track__16BitsStereo;
+                }
+            }
+        }
+    }
+
+    // select the processing hooks
+    state->hook = process__nop;
+    if (countActiveTracks) {
+        if (resampling) {
+            if (!state->outputTemp) {
+                state->outputTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
+            }
+            if (!state->resampleTemp) {
+                state->resampleTemp = new int32_t[MAX_NUM_CHANNELS * state->frameCount];
+            }
+            state->hook = process__genericResampling;
+        } else {
+            if (state->outputTemp) {
+                delete [] state->outputTemp;
+                state->outputTemp = 0;
+            }
+            if (state->resampleTemp) {
+                delete [] state->resampleTemp;
+                state->resampleTemp = 0;
+            }
+            state->hook = process__genericNoResampling;
+            if (all16BitsStereoNoResample && !volumeRamp) {
+                if (countActiveTracks == 1) {
+                    state->hook = process__OneTrack16BitsStereoNoResampling;
+                }
+            }
+        }
+    }
+
+    LOGV("mixer configuration change: %d activeTracks (%08x) "
+        "all16BitsStereoNoResample=%d, resampling=%d, volumeRamp=%d",
+        countActiveTracks, state->enabledTracks,
+        all16BitsStereoNoResample, resampling, volumeRamp);
+
+   state->hook(state);
+
+   // Now that the volume ramp has been done, set optimal state and
+   // track hooks for subsequent mixer process
+   if (countActiveTracks) {
+       int allMuted = 1;
+       uint32_t en = state->enabledTracks;
+       while (en) {
+           const int i = 31 - __builtin_clz(en);
+           en &= ~(1<<i);
+           track_t& t = state->tracks[i];
+           if (!t.doesResample() && t.volumeRL == 0)
+           {
+               t.needs |= NEEDS_MUTE_ENABLED;
+               t.hook = track__nop;
+           } else {
+               allMuted = 0;
+           }
+       }
+       if (allMuted) {
+           state->hook = process__nop;
+       } else if (all16BitsStereoNoResample) {
+           if (countActiveTracks == 1) {
+              state->hook = process__OneTrack16BitsStereoNoResampling;
+           }
+       }
+   }
+}
+
+static inline
+int32_t mulAdd(int16_t in, int16_t v, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    asm( "smlabb %[out], %[in], %[v], %[a] \n"
+         : [out]"=r"(out)
+         : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
+         : );
+    return out;
+#else
+    return a + in * int32_t(v);
+#endif
+}
+
+static inline
+int32_t mul(int16_t in, int16_t v)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    asm( "smulbb %[out], %[in], %[v] \n"
+         : [out]"=r"(out)
+         : [in]"%r"(in), [v]"r"(v)
+         : );
+    return out;
+#else
+    return in * int32_t(v);
+#endif
+}
+
+static inline
+int32_t mulAddRL(int left, uint32_t inRL, uint32_t vRL, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    if (left) {
+        asm( "smlabb %[out], %[inRL], %[vRL], %[a] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
+             : );
+    } else {
+        asm( "smlatt %[out], %[inRL], %[vRL], %[a] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL), [a]"r"(a)
+             : );
+    }
+    return out;
+#else
+    if (left) {
+        return a + int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
+    } else {
+        return a + int16_t(inRL>>16) * int16_t(vRL>>16);
+    }
+#endif
+}
+
+static inline
+int32_t mulRL(int left, uint32_t inRL, uint32_t vRL)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    if (left) {
+        asm( "smulbb %[out], %[inRL], %[vRL] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
+             : );
+    } else {
+        asm( "smultt %[out], %[inRL], %[vRL] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [vRL]"r"(vRL)
+             : );
+    }
+    return out;
+#else
+    if (left) {
+        return int16_t(inRL&0xFFFF) * int16_t(vRL&0xFFFF);
+    } else {
+        return int16_t(inRL>>16) * int16_t(vRL>>16);
+    }
+#endif
+}
+
+
+void AudioMixer::track__genericResample(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
+{
+    t->resampler->setSampleRate(t->sampleRate);
+
+    // ramp gain - resample to temp buffer and scale/mix in 2nd step
+    if (aux != NULL) {
+        // always resample with unity gain when sending to auxiliary buffer to be able
+        // to apply send level after resampling
+        // TODO: modify each resampler to support aux channel?
+        t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
+        memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
+        t->resampler->resample(temp, outFrameCount, t->bufferProvider);
+        if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
+            volumeRampStereo(t, out, outFrameCount, temp, aux);
+        } else {
+            volumeStereo(t, out, outFrameCount, temp, aux);
+        }
+    } else {
+        if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
+            t->resampler->setVolume(UNITY_GAIN, UNITY_GAIN);
+            memset(temp, 0, outFrameCount * MAX_NUM_CHANNELS * sizeof(int32_t));
+            t->resampler->resample(temp, outFrameCount, t->bufferProvider);
+            volumeRampStereo(t, out, outFrameCount, temp, aux);
+        }
+
+        // constant gain
+        else {
+            t->resampler->setVolume(t->volume[0], t->volume[1]);
+            t->resampler->resample(out, outFrameCount, t->bufferProvider);
+        }
+    }
+}
+
+void AudioMixer::track__nop(track_t* t, int32_t* out, size_t outFrameCount, int32_t* temp, int32_t* aux)
+{
+}
+
+void AudioMixer::volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+    int32_t vl = t->prevVolume[0];
+    int32_t vr = t->prevVolume[1];
+    const int32_t vlInc = t->volumeInc[0];
+    const int32_t vrInc = t->volumeInc[1];
+
+    //LOGD("[0] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+    //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+    //       (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+    // ramp volume
+    if UNLIKELY(aux != NULL) {
+        int32_t va = t->prevAuxLevel;
+        const int32_t vaInc = t->auxInc;
+        int32_t l;
+        int32_t r;
+
+        do {
+            l = (*temp++ >> 12);
+            r = (*temp++ >> 12);
+            *out++ += (vl >> 16) * l;
+            *out++ += (vr >> 16) * r;
+            *aux++ += (va >> 17) * (l + r);
+            vl += vlInc;
+            vr += vrInc;
+            va += vaInc;
+        } while (--frameCount);
+        t->prevAuxLevel = va;
+    } else {
+        do {
+            *out++ += (vl >> 16) * (*temp++ >> 12);
+            *out++ += (vr >> 16) * (*temp++ >> 12);
+            vl += vlInc;
+            vr += vrInc;
+        } while (--frameCount);
+    }
+    t->prevVolume[0] = vl;
+    t->prevVolume[1] = vr;
+    t->adjustVolumeRamp((aux != NULL));
+}
+
+void AudioMixer::volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+    const int16_t vl = t->volume[0];
+    const int16_t vr = t->volume[1];
+
+    if UNLIKELY(aux != NULL) {
+        const int16_t va = (int16_t)t->auxLevel;
+        do {
+            int16_t l = (int16_t)(*temp++ >> 12);
+            int16_t r = (int16_t)(*temp++ >> 12);
+            out[0] = mulAdd(l, vl, out[0]);
+            int16_t a = (int16_t)(((int32_t)l + r) >> 1);
+            out[1] = mulAdd(r, vr, out[1]);
+            out += 2;
+            aux[0] = mulAdd(a, va, aux[0]);
+            aux++;
+        } while (--frameCount);
+    } else {
+        do {
+            int16_t l = (int16_t)(*temp++ >> 12);
+            int16_t r = (int16_t)(*temp++ >> 12);
+            out[0] = mulAdd(l, vl, out[0]);
+            out[1] = mulAdd(r, vr, out[1]);
+            out += 2;
+        } while (--frameCount);
+    }
+}
+
+void AudioMixer::track__16BitsStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+    int16_t const *in = static_cast<int16_t const *>(t->in);
+
+    if UNLIKELY(aux != NULL) {
+        int32_t l;
+        int32_t r;
+        // ramp gain
+        if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
+            int32_t vl = t->prevVolume[0];
+            int32_t vr = t->prevVolume[1];
+            int32_t va = t->prevAuxLevel;
+            const int32_t vlInc = t->volumeInc[0];
+            const int32_t vrInc = t->volumeInc[1];
+            const int32_t vaInc = t->auxInc;
+            // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                l = (int32_t)*in++;
+                r = (int32_t)*in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * r;
+                *aux++ += (va >> 17) * (l + r);
+                vl += vlInc;
+                vr += vrInc;
+                va += vaInc;
+            } while (--frameCount);
+
+            t->prevVolume[0] = vl;
+            t->prevVolume[1] = vr;
+            t->prevAuxLevel = va;
+            t->adjustVolumeRamp(true);
+        }
+
+        // constant gain
+        else {
+            const uint32_t vrl = t->volumeRL;
+            const int16_t va = (int16_t)t->auxLevel;
+            do {
+                uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
+                int16_t a = (int16_t)(((int32_t)in[0] + in[1]) >> 1);
+                in += 2;
+                out[0] = mulAddRL(1, rl, vrl, out[0]);
+                out[1] = mulAddRL(0, rl, vrl, out[1]);
+                out += 2;
+                aux[0] = mulAdd(a, va, aux[0]);
+                aux++;
+            } while (--frameCount);
+        }
+    } else {
+        // ramp gain
+        if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
+            int32_t vl = t->prevVolume[0];
+            int32_t vr = t->prevVolume[1];
+            const int32_t vlInc = t->volumeInc[0];
+            const int32_t vrInc = t->volumeInc[1];
+
+            // LOGD("[1] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //        t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+            //        (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                *out++ += (vl >> 16) * (int32_t) *in++;
+                *out++ += (vr >> 16) * (int32_t) *in++;
+                vl += vlInc;
+                vr += vrInc;
+            } while (--frameCount);
+
+            t->prevVolume[0] = vl;
+            t->prevVolume[1] = vr;
+            t->adjustVolumeRamp(false);
+        }
+
+        // constant gain
+        else {
+            const uint32_t vrl = t->volumeRL;
+            do {
+                uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
+                in += 2;
+                out[0] = mulAddRL(1, rl, vrl, out[0]);
+                out[1] = mulAddRL(0, rl, vrl, out[1]);
+                out += 2;
+            } while (--frameCount);
+        }
+    }
+    t->in = in;
+}
+
+void AudioMixer::track__16BitsMono(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux)
+{
+    int16_t const *in = static_cast<int16_t const *>(t->in);
+
+    if UNLIKELY(aux != NULL) {
+        // ramp gain
+        if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]|t->auxInc) {
+            int32_t vl = t->prevVolume[0];
+            int32_t vr = t->prevVolume[1];
+            int32_t va = t->prevAuxLevel;
+            const int32_t vlInc = t->volumeInc[0];
+            const int32_t vrInc = t->volumeInc[1];
+            const int32_t vaInc = t->auxInc;
+
+            // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //         t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                int32_t l = *in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * l;
+                *aux++ += (va >> 16) * l;
+                vl += vlInc;
+                vr += vrInc;
+                va += vaInc;
+            } while (--frameCount);
+
+            t->prevVolume[0] = vl;
+            t->prevVolume[1] = vr;
+            t->prevAuxLevel = va;
+            t->adjustVolumeRamp(true);
+        }
+        // constant gain
+        else {
+            const int16_t vl = t->volume[0];
+            const int16_t vr = t->volume[1];
+            const int16_t va = (int16_t)t->auxLevel;
+            do {
+                int16_t l = *in++;
+                out[0] = mulAdd(l, vl, out[0]);
+                out[1] = mulAdd(l, vr, out[1]);
+                out += 2;
+                aux[0] = mulAdd(l, va, aux[0]);
+                aux++;
+            } while (--frameCount);
+        }
+    } else {
+        // ramp gain
+        if UNLIKELY(t->volumeInc[0]|t->volumeInc[1]) {
+            int32_t vl = t->prevVolume[0];
+            int32_t vr = t->prevVolume[1];
+            const int32_t vlInc = t->volumeInc[0];
+            const int32_t vrInc = t->volumeInc[1];
+
+            // LOGD("[2] %p: inc=%f, v0=%f, v1=%d, final=%f, count=%d",
+            //         t, vlInc/65536.0f, vl/65536.0f, t->volume[0],
+            //         (vl + vlInc*frameCount)/65536.0f, frameCount);
+
+            do {
+                int32_t l = *in++;
+                *out++ += (vl >> 16) * l;
+                *out++ += (vr >> 16) * l;
+                vl += vlInc;
+                vr += vrInc;
+            } while (--frameCount);
+
+            t->prevVolume[0] = vl;
+            t->prevVolume[1] = vr;
+            t->adjustVolumeRamp(false);
+        }
+        // constant gain
+        else {
+            const int16_t vl = t->volume[0];
+            const int16_t vr = t->volume[1];
+            do {
+                int16_t l = *in++;
+                out[0] = mulAdd(l, vl, out[0]);
+                out[1] = mulAdd(l, vr, out[1]);
+                out += 2;
+            } while (--frameCount);
+        }
+    }
+    t->in = in;
+}
+
+void AudioMixer::ditherAndClamp(int32_t* out, int32_t const *sums, size_t c)
+{
+    for (size_t i=0 ; i<c ; i++) {
+        int32_t l = *sums++;
+        int32_t r = *sums++;
+        int32_t nl = l >> 12;
+        int32_t nr = r >> 12;
+        l = clamp16(nl);
+        r = clamp16(nr);
+        *out++ = (r<<16) | (l & 0xFFFF);
+    }
+}
+
+// no-op case
+void AudioMixer::process__nop(state_t* state)
+{
+    uint32_t e0 = state->enabledTracks;
+    size_t bufSize = state->frameCount * sizeof(int16_t) * MAX_NUM_CHANNELS;
+    while (e0) {
+        // process by group of tracks with same output buffer to
+        // avoid multiple memset() on same buffer
+        uint32_t e1 = e0, e2 = e0;
+        int i = 31 - __builtin_clz(e1);
+        track_t& t1 = state->tracks[i];
+        e2 &= ~(1<<i);
+        while (e2) {
+            i = 31 - __builtin_clz(e2);
+            e2 &= ~(1<<i);
+            track_t& t2 = state->tracks[i];
+            if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
+                e1 &= ~(1<<i);
+            }
+        }
+        e0 &= ~(e1);
+
+        memset(t1.mainBuffer, 0, bufSize);
+
+        while (e1) {
+            i = 31 - __builtin_clz(e1);
+            e1 &= ~(1<<i);
+            t1 = state->tracks[i];
+            size_t outFrames = state->frameCount;
+            while (outFrames) {
+                t1.buffer.frameCount = outFrames;
+                t1.bufferProvider->getNextBuffer(&t1.buffer);
+                if (!t1.buffer.raw) break;
+                outFrames -= t1.buffer.frameCount;
+                t1.bufferProvider->releaseBuffer(&t1.buffer);
+            }
+        }
+    }
+}
+
+// generic code without resampling
+void AudioMixer::process__genericNoResampling(state_t* state)
+{
+    int32_t outTemp[BLOCKSIZE * MAX_NUM_CHANNELS] __attribute__((aligned(32)));
+
+    // acquire each track's buffer
+    uint32_t enabledTracks = state->enabledTracks;
+    uint32_t e0 = enabledTracks;
+    while (e0) {
+        const int i = 31 - __builtin_clz(e0);
+        e0 &= ~(1<<i);
+        track_t& t = state->tracks[i];
+        t.buffer.frameCount = state->frameCount;
+        t.bufferProvider->getNextBuffer(&t.buffer);
+        t.frameCount = t.buffer.frameCount;
+        t.in = t.buffer.raw;
+        // t.in == NULL can happen if the track was flushed just after having
+        // been enabled for mixing.
+        if (t.in == NULL)
+            enabledTracks &= ~(1<<i);
+    }
+
+    e0 = enabledTracks;
+    while (e0) {
+        // process by group of tracks with same output buffer to
+        // optimize cache use
+        uint32_t e1 = e0, e2 = e0;
+        int j = 31 - __builtin_clz(e1);
+        track_t& t1 = state->tracks[j];
+        e2 &= ~(1<<j);
+        while (e2) {
+            j = 31 - __builtin_clz(e2);
+            e2 &= ~(1<<j);
+            track_t& t2 = state->tracks[j];
+            if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
+                e1 &= ~(1<<j);
+            }
+        }
+        e0 &= ~(e1);
+        // this assumes output 16 bits stereo, no resampling
+        int32_t *out = t1.mainBuffer;
+        size_t numFrames = 0;
+        do {
+            memset(outTemp, 0, sizeof(outTemp));
+            e2 = e1;
+            while (e2) {
+                const int i = 31 - __builtin_clz(e2);
+                e2 &= ~(1<<i);
+                track_t& t = state->tracks[i];
+                size_t outFrames = BLOCKSIZE;
+                int32_t *aux = NULL;
+                if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
+                    aux = t.auxBuffer + numFrames;
+                }
+                while (outFrames) {
+                    size_t inFrames = (t.frameCount > outFrames)?outFrames:t.frameCount;
+                    if (inFrames) {
+                        (t.hook)(&t, outTemp + (BLOCKSIZE-outFrames)*MAX_NUM_CHANNELS, inFrames, state->resampleTemp, aux);
+                        t.frameCount -= inFrames;
+                        outFrames -= inFrames;
+                        if UNLIKELY(aux != NULL) {
+                            aux += inFrames;
+                        }
+                    }
+                    if (t.frameCount == 0 && outFrames) {
+                        t.bufferProvider->releaseBuffer(&t.buffer);
+                        t.buffer.frameCount = (state->frameCount - numFrames) - (BLOCKSIZE - outFrames);
+                        t.bufferProvider->getNextBuffer(&t.buffer);
+                        t.in = t.buffer.raw;
+                        if (t.in == NULL) {
+                            enabledTracks &= ~(1<<i);
+                            e1 &= ~(1<<i);
+                            break;
+                        }
+                        t.frameCount = t.buffer.frameCount;
+                    }
+                }
+            }
+            ditherAndClamp(out, outTemp, BLOCKSIZE);
+            out += BLOCKSIZE;
+            numFrames += BLOCKSIZE;
+        } while (numFrames < state->frameCount);
+    }
+
+    // release each track's buffer
+    e0 = enabledTracks;
+    while (e0) {
+        const int i = 31 - __builtin_clz(e0);
+        e0 &= ~(1<<i);
+        track_t& t = state->tracks[i];
+        t.bufferProvider->releaseBuffer(&t.buffer);
+    }
+}
+
+
+  // generic code with resampling
+void AudioMixer::process__genericResampling(state_t* state)
+{
+    int32_t* const outTemp = state->outputTemp;
+    const size_t size = sizeof(int32_t) * MAX_NUM_CHANNELS * state->frameCount;
+    memset(outTemp, 0, size);
+
+    size_t numFrames = state->frameCount;
+
+    uint32_t e0 = state->enabledTracks;
+    while (e0) {
+        // process by group of tracks with same output buffer
+        // to optimize cache use
+        uint32_t e1 = e0, e2 = e0;
+        int j = 31 - __builtin_clz(e1);
+        track_t& t1 = state->tracks[j];
+        e2 &= ~(1<<j);
+        while (e2) {
+            j = 31 - __builtin_clz(e2);
+            e2 &= ~(1<<j);
+            track_t& t2 = state->tracks[j];
+            if UNLIKELY(t2.mainBuffer != t1.mainBuffer) {
+                e1 &= ~(1<<j);
+            }
+        }
+        e0 &= ~(e1);
+        int32_t *out = t1.mainBuffer;
+        while (e1) {
+            const int i = 31 - __builtin_clz(e1);
+            e1 &= ~(1<<i);
+            track_t& t = state->tracks[i];
+            int32_t *aux = NULL;
+            if UNLIKELY((t.needs & NEEDS_AUX__MASK) == NEEDS_AUX_ENABLED) {
+                aux = t.auxBuffer;
+            }
+
+            // this is a little goofy, on the resampling case we don't
+            // acquire/release the buffers because it's done by
+            // the resampler.
+            if ((t.needs & NEEDS_RESAMPLE__MASK) == NEEDS_RESAMPLE_ENABLED) {
+                (t.hook)(&t, outTemp, numFrames, state->resampleTemp, aux);
+            } else {
+
+                size_t outFrames = 0;
+
+                while (outFrames < numFrames) {
+                    t.buffer.frameCount = numFrames - outFrames;
+                    t.bufferProvider->getNextBuffer(&t.buffer);
+                    t.in = t.buffer.raw;
+                    // t.in == NULL can happen if the track was flushed just after having
+                    // been enabled for mixing.
+                    if (t.in == NULL) break;
+
+                    if UNLIKELY(aux != NULL) {
+                        aux += outFrames;
+                    }
+                    (t.hook)(&t, outTemp + outFrames*MAX_NUM_CHANNELS, t.buffer.frameCount, state->resampleTemp, aux);
+                    outFrames += t.buffer.frameCount;
+                    t.bufferProvider->releaseBuffer(&t.buffer);
+                }
+            }
+        }
+        ditherAndClamp(out, outTemp, numFrames);
+    }
+}
+
+// one track, 16 bits stereo without resampling is the most common case
+void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state)
+{
+    const int i = 31 - __builtin_clz(state->enabledTracks);
+    const track_t& t = state->tracks[i];
+
+    AudioBufferProvider::Buffer& b(t.buffer);
+
+    int32_t* out = t.mainBuffer;
+    size_t numFrames = state->frameCount;
+
+    const int16_t vl = t.volume[0];
+    const int16_t vr = t.volume[1];
+    const uint32_t vrl = t.volumeRL;
+    while (numFrames) {
+        b.frameCount = numFrames;
+        t.bufferProvider->getNextBuffer(&b);
+        int16_t const *in = b.i16;
+
+        // in == NULL can happen if the track was flushed just after having
+        // been enabled for mixing.
+        if (in == NULL || ((unsigned long)in & 3)) {
+            memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
+            LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
+                    in, i, t.channelCount, t.needs);
+            return;
+        }
+        size_t outFrames = b.frameCount;
+
+        if (UNLIKELY(uint32_t(vl) > UNITY_GAIN || uint32_t(vr) > UNITY_GAIN)) {
+            // volume is boosted, so we might need to clamp even though
+            // we process only one track.
+            do {
+                uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
+                in += 2;
+                int32_t l = mulRL(1, rl, vrl) >> 12;
+                int32_t r = mulRL(0, rl, vrl) >> 12;
+                // clamping...
+                l = clamp16(l);
+                r = clamp16(r);
+                *out++ = (r<<16) | (l & 0xFFFF);
+            } while (--outFrames);
+        } else {
+            do {
+                uint32_t rl = *reinterpret_cast<uint32_t const *>(in);
+                in += 2;
+                int32_t l = mulRL(1, rl, vrl) >> 12;
+                int32_t r = mulRL(0, rl, vrl) >> 12;
+                *out++ = (r<<16) | (l & 0xFFFF);
+            } while (--outFrames);
+        }
+        numFrames -= b.frameCount;
+        t.bufferProvider->releaseBuffer(&b);
+    }
+}
+
+// 2 tracks is also a common case
+// NEVER used in current implementation of process__validate()
+// only use if the 2 tracks have the same output buffer
+void AudioMixer::process__TwoTracks16BitsStereoNoResampling(state_t* state)
+{
+    int i;
+    uint32_t en = state->enabledTracks;
+
+    i = 31 - __builtin_clz(en);
+    const track_t& t0 = state->tracks[i];
+    AudioBufferProvider::Buffer& b0(t0.buffer);
+
+    en &= ~(1<<i);
+    i = 31 - __builtin_clz(en);
+    const track_t& t1 = state->tracks[i];
+    AudioBufferProvider::Buffer& b1(t1.buffer);
+
+    int16_t const *in0;
+    const int16_t vl0 = t0.volume[0];
+    const int16_t vr0 = t0.volume[1];
+    size_t frameCount0 = 0;
+
+    int16_t const *in1;
+    const int16_t vl1 = t1.volume[0];
+    const int16_t vr1 = t1.volume[1];
+    size_t frameCount1 = 0;
+
+    //FIXME: only works if two tracks use same buffer
+    int32_t* out = t0.mainBuffer;
+    size_t numFrames = state->frameCount;
+    int16_t const *buff = NULL;
+
+
+    while (numFrames) {
+
+        if (frameCount0 == 0) {
+            b0.frameCount = numFrames;
+            t0.bufferProvider->getNextBuffer(&b0);
+            if (b0.i16 == NULL) {
+                if (buff == NULL) {
+                    buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
+                }
+                in0 = buff;
+                b0.frameCount = numFrames;
+            } else {
+                in0 = b0.i16;
+            }
+            frameCount0 = b0.frameCount;
+        }
+        if (frameCount1 == 0) {
+            b1.frameCount = numFrames;
+            t1.bufferProvider->getNextBuffer(&b1);
+            if (b1.i16 == NULL) {
+                if (buff == NULL) {
+                    buff = new int16_t[MAX_NUM_CHANNELS * state->frameCount];
+                }
+                in1 = buff;
+                b1.frameCount = numFrames;
+               } else {
+                in1 = b1.i16;
+            }
+            frameCount1 = b1.frameCount;
+        }
+
+        size_t outFrames = frameCount0 < frameCount1?frameCount0:frameCount1;
+
+        numFrames -= outFrames;
+        frameCount0 -= outFrames;
+        frameCount1 -= outFrames;
+
+        do {
+            int32_t l0 = *in0++;
+            int32_t r0 = *in0++;
+            l0 = mul(l0, vl0);
+            r0 = mul(r0, vr0);
+            int32_t l = *in1++;
+            int32_t r = *in1++;
+            l = mulAdd(l, vl1, l0) >> 12;
+            r = mulAdd(r, vr1, r0) >> 12;
+            // clamping...
+            l = clamp16(l);
+            r = clamp16(r);
+            *out++ = (r<<16) | (l & 0xFFFF);
+        } while (--outFrames);
+
+        if (frameCount0 == 0) {
+            t0.bufferProvider->releaseBuffer(&b0);
+        }
+        if (frameCount1 == 0) {
+            t1.bufferProvider->releaseBuffer(&b1);
+        }
+    }
+
+    if (buff != NULL) {
+        delete [] buff;
+    }
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
new file mode 100644
index 0000000..aee3e17
--- /dev/null
+++ b/services/audioflinger/AudioMixer.h
@@ -0,0 +1,207 @@
+/* //device/include/server/AudioFlinger/AudioMixer.h
+**
+** Copyright 2007, 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 ANDROID_AUDIO_MIXER_H
+#define ANDROID_AUDIO_MIXER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "AudioBufferProvider.h"
+#include "AudioResampler.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// ----------------------------------------------------------------------------
+
+class AudioMixer
+{
+public:
+                            AudioMixer(size_t frameCount, uint32_t sampleRate);
+
+                            ~AudioMixer();
+
+    static const uint32_t MAX_NUM_TRACKS = 32;
+    static const uint32_t MAX_NUM_CHANNELS = 2;
+
+    static const uint16_t UNITY_GAIN = 0x1000;
+
+    enum { // names
+
+        // track units (32 units)
+        TRACK0          = 0x1000,
+
+        // enable/disable
+        MIXING          = 0x2000,
+
+        // setParameter targets
+        TRACK           = 0x3000,
+        RESAMPLE        = 0x3001,
+        RAMP_VOLUME     = 0x3002, // ramp to new volume
+        VOLUME          = 0x3003, // don't ramp
+
+        // set Parameter names
+        // for target TRACK
+        CHANNEL_COUNT   = 0x4000,
+        FORMAT          = 0x4001,
+        MAIN_BUFFER     = 0x4002,
+        AUX_BUFFER      = 0x4003,
+        // for TARGET RESAMPLE
+        SAMPLE_RATE     = 0x4100,
+        // for TARGET VOLUME (8 channels max)
+        VOLUME0         = 0x4200,
+        VOLUME1         = 0x4201,
+        AUXLEVEL        = 0x4210,
+    };
+
+
+    int         getTrackName();
+    void        deleteTrackName(int name);
+
+    status_t    enable(int name);
+    status_t    disable(int name);
+
+    status_t    setActiveTrack(int track);
+    status_t    setParameter(int target, int name, void *value);
+
+    status_t    setBufferProvider(AudioBufferProvider* bufferProvider);
+    void        process();
+
+    uint32_t    trackNames() const { return mTrackNames; }
+
+    static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
+
+private:
+
+    enum {
+        NEEDS_CHANNEL_COUNT__MASK   = 0x00000003,
+        NEEDS_FORMAT__MASK          = 0x000000F0,
+        NEEDS_MUTE__MASK            = 0x00000100,
+        NEEDS_RESAMPLE__MASK        = 0x00001000,
+        NEEDS_AUX__MASK             = 0x00010000,
+    };
+
+    enum {
+        NEEDS_CHANNEL_1             = 0x00000000,
+        NEEDS_CHANNEL_2             = 0x00000001,
+
+        NEEDS_FORMAT_16             = 0x00000010,
+
+        NEEDS_MUTE_DISABLED         = 0x00000000,
+        NEEDS_MUTE_ENABLED          = 0x00000100,
+
+        NEEDS_RESAMPLE_DISABLED     = 0x00000000,
+        NEEDS_RESAMPLE_ENABLED      = 0x00001000,
+
+        NEEDS_AUX_DISABLED     = 0x00000000,
+        NEEDS_AUX_ENABLED      = 0x00010000,
+    };
+
+    static inline int32_t applyVolume(int32_t in, int32_t v) {
+        return in * v;
+    }
+
+
+    struct state_t;
+    struct track_t;
+
+    typedef void (*mix_t)(state_t* state);
+    typedef void (*hook_t)(track_t* t, int32_t* output, size_t numOutFrames, int32_t* temp, int32_t* aux);
+    static const int BLOCKSIZE = 16; // 4 cache lines
+
+    struct track_t {
+        uint32_t    needs;
+
+        union {
+        int16_t     volume[2];      // [0]3.12 fixed point
+        int32_t     volumeRL;
+        };
+
+        int32_t     prevVolume[2];
+
+        int32_t     volumeInc[2];
+        int32_t     auxLevel;
+        int32_t     auxInc;
+        int32_t     prevAuxLevel;
+
+        uint16_t    frameCount;
+
+        uint8_t     channelCount : 4;
+        uint8_t     enabled      : 1;
+        uint8_t     reserved0    : 3;
+        uint8_t     format;
+
+        AudioBufferProvider*                bufferProvider;
+        mutable AudioBufferProvider::Buffer buffer;
+
+        hook_t      hook;
+        void const* in;             // current location in buffer
+
+        AudioResampler*     resampler;
+        uint32_t            sampleRate;
+        int32_t*           mainBuffer;
+        int32_t*           auxBuffer;
+
+        bool        setResampler(uint32_t sampleRate, uint32_t devSampleRate);
+        bool        doesResample() const;
+        void        adjustVolumeRamp(bool aux);
+    };
+
+    // pad to 32-bytes to fill cache line
+    struct state_t {
+        uint32_t        enabledTracks;
+        uint32_t        needsChanged;
+        size_t          frameCount;
+        mix_t           hook;
+        int32_t         *outputTemp;
+        int32_t         *resampleTemp;
+        int32_t         reserved[2];
+        track_t         tracks[32]; __attribute__((aligned(32)));
+    };
+
+    int             mActiveTrack;
+    uint32_t        mTrackNames;
+    const uint32_t  mSampleRate;
+
+    state_t         mState __attribute__((aligned(32)));
+
+    void invalidateState(uint32_t mask);
+
+    static void track__genericResample(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+    static void track__nop(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+    static void track__16BitsStereo(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+    static void track__16BitsMono(track_t* t, int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
+    static void volumeRampStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
+    static void volumeStereo(track_t* t, int32_t* out, size_t frameCount, int32_t* temp, int32_t* aux);
+
+    static void process__validate(state_t* state);
+    static void process__nop(state_t* state);
+    static void process__genericNoResampling(state_t* state);
+    static void process__genericResampling(state_t* state);
+    static void process__OneTrack16BitsStereoNoResampling(state_t* state);
+    static void process__TwoTracks16BitsStereoNoResampling(state_t* state);
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_AUDIO_MIXER_H
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
new file mode 100644
index 0000000..1d87c0d
--- /dev/null
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -0,0 +1,2121 @@
+/*
+ * Copyright (C) 2009 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_TAG "AudioPolicyManagerBase"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <hardware_legacy/AudioPolicyManagerBase.h>
+#include <media/mediarecorder.h>
+
+namespace android {
+
+
+// ----------------------------------------------------------------------------
+// AudioPolicyInterface implementation
+// ----------------------------------------------------------------------------
+
+
+status_t AudioPolicyManagerBase::setDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  AudioSystem::device_connection_state state,
+                                                  const char *device_address)
+{
+
+    LOGV("setDeviceConnectionState() device: %x, state %d, address %s", device, state, device_address);
+
+    // connect/disconnect only 1 device at a time
+    if (AudioSystem::popCount(device) != 1) return BAD_VALUE;
+
+    if (strlen(device_address) >= MAX_DEVICE_ADDRESS_LEN) {
+        LOGE("setDeviceConnectionState() invalid address: %s", device_address);
+        return BAD_VALUE;
+    }
+
+    // handle output devices
+    if (AudioSystem::isOutputDevice(device)) {
+
+#ifndef WITH_A2DP
+        if (AudioSystem::isA2dpDevice(device)) {
+            LOGE("setDeviceConnectionState() invalid device: %x", device);
+            return BAD_VALUE;
+        }
+#endif
+
+        switch (state)
+        {
+        // handle output device connection
+        case AudioSystem::DEVICE_STATE_AVAILABLE:
+            if (mAvailableOutputDevices & device) {
+                LOGW("setDeviceConnectionState() device already connected: %x", device);
+                return INVALID_OPERATION;
+            }
+            LOGV("setDeviceConnectionState() connecting device %x", device);
+
+            // register new device as available
+            mAvailableOutputDevices |= device;
+
+#ifdef WITH_A2DP
+            // handle A2DP device connection
+            if (AudioSystem::isA2dpDevice(device)) {
+                status_t status = handleA2dpConnection(device, device_address);
+                if (status != NO_ERROR) {
+                    mAvailableOutputDevices &= ~device;
+                    return status;
+                }
+            } else
+#endif
+            {
+                if (AudioSystem::isBluetoothScoDevice(device)) {
+                    LOGV("setDeviceConnectionState() BT SCO  device, address %s", device_address);
+                    // keep track of SCO device address
+                    mScoDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
+#ifdef WITH_A2DP
+                    if (mA2dpOutput != 0 &&
+                        mPhoneState != AudioSystem::MODE_NORMAL) {
+                        mpClientInterface->suspendOutput(mA2dpOutput);
+                    }
+#endif
+                }
+            }
+            break;
+        // handle output device disconnection
+        case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
+            if (!(mAvailableOutputDevices & device)) {
+                LOGW("setDeviceConnectionState() device not connected: %x", device);
+                return INVALID_OPERATION;
+            }
+
+
+            LOGV("setDeviceConnectionState() disconnecting device %x", device);
+            // remove device from available output devices
+            mAvailableOutputDevices &= ~device;
+
+#ifdef WITH_A2DP
+            // handle A2DP device disconnection
+            if (AudioSystem::isA2dpDevice(device)) {
+                status_t status = handleA2dpDisconnection(device, device_address);
+                if (status != NO_ERROR) {
+                    mAvailableOutputDevices |= device;
+                    return status;
+                }
+            } else
+#endif
+            {
+                if (AudioSystem::isBluetoothScoDevice(device)) {
+                    mScoDeviceAddress = "";
+#ifdef WITH_A2DP
+                    if (mA2dpOutput != 0 &&
+                        mPhoneState != AudioSystem::MODE_NORMAL) {
+                        mpClientInterface->restoreOutput(mA2dpOutput);
+                    }
+#endif
+                }
+            }
+            } break;
+
+        default:
+            LOGE("setDeviceConnectionState() invalid state: %x", state);
+            return BAD_VALUE;
+        }
+
+        // request routing change if necessary
+        uint32_t newDevice = getNewDevice(mHardwareOutput, false);
+#ifdef WITH_A2DP
+        checkOutputForAllStrategies(newDevice);
+        // A2DP outputs must be closed after checkOutputForAllStrategies() is executed
+        if (state == AudioSystem::DEVICE_STATE_UNAVAILABLE && AudioSystem::isA2dpDevice(device)) {
+            closeA2dpOutputs();
+        }
+#endif
+        updateDeviceForStrategy();
+        setOutputDevice(mHardwareOutput, newDevice);
+
+        if (device == AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
+            device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
+        } else if (device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO ||
+                   device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET ||
+                   device == AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
+            device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+        } else {
+            return NO_ERROR;
+        }
+    }
+    // handle input devices
+    if (AudioSystem::isInputDevice(device)) {
+
+        switch (state)
+        {
+        // handle input device connection
+        case AudioSystem::DEVICE_STATE_AVAILABLE: {
+            if (mAvailableInputDevices & device) {
+                LOGW("setDeviceConnectionState() device already connected: %d", device);
+                return INVALID_OPERATION;
+            }
+            mAvailableInputDevices |= device;
+            }
+            break;
+
+        // handle input device disconnection
+        case AudioSystem::DEVICE_STATE_UNAVAILABLE: {
+            if (!(mAvailableInputDevices & device)) {
+                LOGW("setDeviceConnectionState() device not connected: %d", device);
+                return INVALID_OPERATION;
+            }
+            mAvailableInputDevices &= ~device;
+            } break;
+
+        default:
+            LOGE("setDeviceConnectionState() invalid state: %x", state);
+            return BAD_VALUE;
+        }
+
+        audio_io_handle_t activeInput = getActiveInput();
+        if (activeInput != 0) {
+            AudioInputDescriptor *inputDesc = mInputs.valueFor(activeInput);
+            uint32_t newDevice = getDeviceForInputSource(inputDesc->mInputSource);
+            if (newDevice != inputDesc->mDevice) {
+                LOGV("setDeviceConnectionState() changing device from %x to %x for input %d",
+                        inputDesc->mDevice, newDevice, activeInput);
+                inputDesc->mDevice = newDevice;
+                AudioParameter param = AudioParameter();
+                param.addInt(String8(AudioParameter::keyRouting), (int)newDevice);
+                mpClientInterface->setParameters(activeInput, param.toString());
+            }
+        }
+
+        return NO_ERROR;
+    }
+
+    LOGW("setDeviceConnectionState() invalid device: %x", device);
+    return BAD_VALUE;
+}
+
+AudioSystem::device_connection_state AudioPolicyManagerBase::getDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  const char *device_address)
+{
+    AudioSystem::device_connection_state state = AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    String8 address = String8(device_address);
+    if (AudioSystem::isOutputDevice(device)) {
+        if (device & mAvailableOutputDevices) {
+#ifdef WITH_A2DP
+            if (AudioSystem::isA2dpDevice(device) &&
+                address != "" && mA2dpDeviceAddress != address) {
+                return state;
+            }
+#endif
+            if (AudioSystem::isBluetoothScoDevice(device) &&
+                address != "" && mScoDeviceAddress != address) {
+                return state;
+            }
+            state = AudioSystem::DEVICE_STATE_AVAILABLE;
+        }
+    } else if (AudioSystem::isInputDevice(device)) {
+        if (device & mAvailableInputDevices) {
+            state = AudioSystem::DEVICE_STATE_AVAILABLE;
+        }
+    }
+
+    return state;
+}
+
+void AudioPolicyManagerBase::setPhoneState(int state)
+{
+    LOGV("setPhoneState() state %d", state);
+    uint32_t newDevice = 0;
+    if (state < 0 || state >= AudioSystem::NUM_MODES) {
+        LOGW("setPhoneState() invalid state %d", state);
+        return;
+    }
+
+    if (state == mPhoneState ) {
+        LOGW("setPhoneState() setting same state %d", state);
+        return;
+    }
+
+    // if leaving call state, handle special case of active streams
+    // pertaining to sonification strategy see handleIncallSonification()
+    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+        LOGV("setPhoneState() in call state management: new state is %d", state);
+        for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+            handleIncallSonification(stream, false, true);
+        }
+    }
+
+    // store previous phone state for management of sonification strategy below
+    int oldState = mPhoneState;
+    mPhoneState = state;
+    bool force = false;
+
+    // are we entering or starting a call
+    if ((oldState != AudioSystem::MODE_IN_CALL) && (state == AudioSystem::MODE_IN_CALL)) {
+        LOGV("  Entering call in setPhoneState()");
+        // force routing command to audio hardware when starting a call
+        // even if no device change is needed
+        force = true;
+    } else if ((oldState == AudioSystem::MODE_IN_CALL) && (state != AudioSystem::MODE_IN_CALL)) {
+        LOGV("  Exiting call in setPhoneState()");
+        // force routing command to audio hardware when exiting a call
+        // even if no device change is needed
+        force = true;
+    }
+
+    // check for device and output changes triggered by new phone state
+    newDevice = getNewDevice(mHardwareOutput, false);
+#ifdef WITH_A2DP
+    checkOutputForAllStrategies(newDevice);
+    // suspend A2DP output if a SCO device is present.
+    if (mA2dpOutput != 0 && mScoDeviceAddress != "") {
+        if (oldState == AudioSystem::MODE_NORMAL) {
+            mpClientInterface->suspendOutput(mA2dpOutput);
+        } else if (state == AudioSystem::MODE_NORMAL) {
+            mpClientInterface->restoreOutput(mA2dpOutput);
+        }
+    }
+#endif
+    updateDeviceForStrategy();
+
+    AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
+
+    // force routing command to audio hardware when ending call
+    // even if no device change is needed
+    if (oldState == AudioSystem::MODE_IN_CALL && newDevice == 0) {
+        newDevice = hwOutputDesc->device();
+    }
+
+    // when changing from ring tone to in call mode, mute the ringing tone
+    // immediately and delay the route change to avoid sending the ring tone
+    // tail into the earpiece or headset.
+    int delayMs = 0;
+    if (state == AudioSystem::MODE_IN_CALL && oldState == AudioSystem::MODE_RINGTONE) {
+        // delay the device change command by twice the output latency to have some margin
+        // and be sure that audio buffers not yet affected by the mute are out when
+        // we actually apply the route change
+        delayMs = hwOutputDesc->mLatency*2;
+        setStreamMute(AudioSystem::RING, true, mHardwareOutput);
+    }
+
+    // change routing is necessary
+    setOutputDevice(mHardwareOutput, newDevice, force, delayMs);
+
+    // if entering in call state, handle special case of active streams
+    // pertaining to sonification strategy see handleIncallSonification()
+    if (state == AudioSystem::MODE_IN_CALL) {
+        LOGV("setPhoneState() in call state management: new state is %d", state);
+        // unmute the ringing tone after a sufficient delay if it was muted before
+        // setting output device above
+        if (oldState == AudioSystem::MODE_RINGTONE) {
+            setStreamMute(AudioSystem::RING, false, mHardwareOutput, MUTE_TIME_MS);
+        }
+        for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+            handleIncallSonification(stream, true, true);
+        }
+    }
+
+    // Flag that ringtone volume must be limited to music volume until we exit MODE_RINGTONE
+    if (state == AudioSystem::MODE_RINGTONE &&
+        (hwOutputDesc->mRefCount[AudioSystem::MUSIC] ||
+        (systemTime() - mMusicStopTime) < seconds(SONIFICATION_HEADSET_MUSIC_DELAY))) {
+        mLimitRingtoneVolume = true;
+    } else {
+        mLimitRingtoneVolume = false;
+    }
+}
+
+void AudioPolicyManagerBase::setRingerMode(uint32_t mode, uint32_t mask)
+{
+    LOGV("setRingerMode() mode %x, mask %x", mode, mask);
+
+    mRingerMode = mode;
+}
+
+void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config)
+{
+    LOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mPhoneState);
+
+    bool forceVolumeReeval = false;
+    switch(usage) {
+    case AudioSystem::FOR_COMMUNICATION:
+        if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO &&
+            config != AudioSystem::FORCE_NONE) {
+            LOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config);
+            return;
+        }
+        mForceUse[usage] = config;
+        break;
+    case AudioSystem::FOR_MEDIA:
+        if (config != AudioSystem::FORCE_HEADPHONES && config != AudioSystem::FORCE_BT_A2DP &&
+            config != AudioSystem::FORCE_WIRED_ACCESSORY && config != AudioSystem::FORCE_NONE) {
+            LOGW("setForceUse() invalid config %d for FOR_MEDIA", config);
+            return;
+        }
+        mForceUse[usage] = config;
+        break;
+    case AudioSystem::FOR_RECORD:
+        if (config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_WIRED_ACCESSORY &&
+            config != AudioSystem::FORCE_NONE) {
+            LOGW("setForceUse() invalid config %d for FOR_RECORD", config);
+            return;
+        }
+        mForceUse[usage] = config;
+        break;
+    case AudioSystem::FOR_DOCK:
+        if (config != AudioSystem::FORCE_NONE && config != AudioSystem::FORCE_BT_CAR_DOCK &&
+            config != AudioSystem::FORCE_BT_DESK_DOCK && config != AudioSystem::FORCE_WIRED_ACCESSORY) {
+            LOGW("setForceUse() invalid config %d for FOR_DOCK", config);
+        }
+        forceVolumeReeval = true;
+        mForceUse[usage] = config;
+        break;
+    default:
+        LOGW("setForceUse() invalid usage %d", usage);
+        break;
+    }
+
+    // check for device and output changes triggered by new phone state
+    uint32_t newDevice = getNewDevice(mHardwareOutput, false);
+#ifdef WITH_A2DP
+    checkOutputForAllStrategies(newDevice);
+#endif
+    updateDeviceForStrategy();
+    setOutputDevice(mHardwareOutput, newDevice);
+    if (forceVolumeReeval) {
+        applyStreamVolumes(mHardwareOutput, newDevice);
+    }
+}
+
+AudioSystem::forced_config AudioPolicyManagerBase::getForceUse(AudioSystem::force_use usage)
+{
+    return mForceUse[usage];
+}
+
+void AudioPolicyManagerBase::setSystemProperty(const char* property, const char* value)
+{
+    LOGV("setSystemProperty() property %s, value %s", property, value);
+    if (strcmp(property, "ro.camera.sound.forced") == 0) {
+        if (atoi(value)) {
+            LOGV("ENFORCED_AUDIBLE cannot be muted");
+            mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = false;
+        } else {
+            LOGV("ENFORCED_AUDIBLE can be muted");
+            mStreams[AudioSystem::ENFORCED_AUDIBLE].mCanBeMuted = true;
+        }
+    }
+}
+
+audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::output_flags flags)
+{
+    audio_io_handle_t output = 0;
+    uint32_t latency = 0;
+    routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
+    uint32_t device = getDeviceForStrategy(strategy);
+    LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags);
+
+#ifdef AUDIO_POLICY_TEST
+    if (mCurOutput != 0) {
+        LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channels %x, mDirectOutput %d",
+                mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput);
+
+        if (mTestOutputs[mCurOutput] == 0) {
+            LOGV("getOutput() opening test output");
+            AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+            outputDesc->mDevice = mTestDevice;
+            outputDesc->mSamplingRate = mTestSamplingRate;
+            outputDesc->mFormat = mTestFormat;
+            outputDesc->mChannels = mTestChannels;
+            outputDesc->mLatency = mTestLatencyMs;
+            outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0);
+            outputDesc->mRefCount[stream] = 0;
+            mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                            &outputDesc->mSamplingRate,
+                                            &outputDesc->mFormat,
+                                            &outputDesc->mChannels,
+                                            &outputDesc->mLatency,
+                                            outputDesc->mFlags);
+            if (mTestOutputs[mCurOutput]) {
+                AudioParameter outputCmd = AudioParameter();
+                outputCmd.addInt(String8("set_id"),mCurOutput);
+                mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString());
+                addOutput(mTestOutputs[mCurOutput], outputDesc);
+            }
+        }
+        return mTestOutputs[mCurOutput];
+    }
+#endif //AUDIO_POLICY_TEST
+
+    // open a direct output if required by specified parameters
+    if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) {
+
+        LOGV("getOutput() opening direct output device %x", device);
+        AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+        outputDesc->mDevice = device;
+        outputDesc->mSamplingRate = samplingRate;
+        outputDesc->mFormat = format;
+        outputDesc->mChannels = channels;
+        outputDesc->mLatency = 0;
+        outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
+        outputDesc->mRefCount[stream] = 0;
+        output = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                        &outputDesc->mSamplingRate,
+                                        &outputDesc->mFormat,
+                                        &outputDesc->mChannels,
+                                        &outputDesc->mLatency,
+                                        outputDesc->mFlags);
+
+        // only accept an output with the requeted parameters
+        if (output == 0 ||
+            (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) ||
+            (format != 0 && format != outputDesc->mFormat) ||
+            (channels != 0 && channels != outputDesc->mChannels)) {
+            LOGV("getOutput() failed opening direct output: samplingRate %d, format %d, channels %d",
+                    samplingRate, format, channels);
+            if (output != 0) {
+                mpClientInterface->closeOutput(output);
+            }
+            delete outputDesc;
+            return 0;
+        }
+        addOutput(output, outputDesc);
+        return output;
+    }
+
+    if (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO &&
+        channels != AudioSystem::CHANNEL_OUT_STEREO) {
+        return 0;
+    }
+    // open a non direct output
+
+    // get which output is suitable for the specified stream. The actual routing change will happen
+    // when startOutput() will be called
+    uint32_t a2dpDevice = device & AudioSystem::DEVICE_OUT_ALL_A2DP;
+    if (AudioSystem::popCount((AudioSystem::audio_devices)device) == 2) {
+#ifdef WITH_A2DP
+        if (a2dpUsedForSonification() && a2dpDevice != 0) {
+            // if playing on 2 devices among which one is A2DP, use duplicated output
+            LOGV("getOutput() using duplicated output");
+            LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device in multiple %x selected but A2DP output not opened", device);
+            output = mDuplicatedOutput;
+        } else
+#endif
+        {
+            // if playing on 2 devices among which none is A2DP, use hardware output
+            output = mHardwareOutput;
+        }
+        LOGV("getOutput() using output %d for 2 devices %x", output, device);
+    } else {
+#ifdef WITH_A2DP
+        if (a2dpDevice != 0) {
+            // if playing on A2DP device, use a2dp output
+            LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device %x selected but A2DP output not opened", device);
+            output = mA2dpOutput;
+        } else
+#endif
+        {
+            // if playing on not A2DP device, use hardware output
+            output = mHardwareOutput;
+        }
+    }
+
+
+    LOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d, format %d, channels %x, flags %x",
+                stream, samplingRate, format, channels, flags);
+
+    return output;
+}
+
+status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output,
+                                             AudioSystem::stream_type stream,
+                                             int session)
+{
+    LOGV("startOutput() output %d, stream %d, session %d", output, stream, session);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("startOutput() unknow output %d", output);
+        return BAD_VALUE;
+    }
+
+    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+    routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
+
+#ifdef WITH_A2DP
+    if (mA2dpOutput != 0  && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) {
+        setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
+    }
+#endif
+
+    // incremenent usage count for this stream on the requested output:
+    // NOTE that the usage count is the same for duplicated output and hardware output which is
+    // necassary for a correct control of hardware output routing by startOutput() and stopOutput()
+    outputDesc->changeRefCount(stream, 1);
+
+    setOutputDevice(output, getNewDevice(output));
+
+    // handle special case for sonification while in call
+    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+        handleIncallSonification(stream, true, false);
+    }
+
+    // apply volume rules for current stream and device if necessary
+    checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device());
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output,
+                                            AudioSystem::stream_type stream,
+                                            int session)
+{
+    LOGV("stopOutput() output %d, stream %d, session %d", output, stream, session);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("stopOutput() unknow output %d", output);
+        return BAD_VALUE;
+    }
+
+    AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+    routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream);
+
+    // handle special case for sonification while in call
+    if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+        handleIncallSonification(stream, false, false);
+    }
+
+    if (outputDesc->mRefCount[stream] > 0) {
+        // decrement usage count of this stream on the output
+        outputDesc->changeRefCount(stream, -1);
+        // store time at which the last music track was stopped - see computeVolume()
+        if (stream == AudioSystem::MUSIC) {
+            mMusicStopTime = systemTime();
+        }
+
+        setOutputDevice(output, getNewDevice(output));
+
+#ifdef WITH_A2DP
+        if (mA2dpOutput != 0 && !a2dpUsedForSonification() &&
+                strategy == STRATEGY_SONIFICATION) {
+            setStrategyMute(STRATEGY_MEDIA,
+                            false,
+                            mA2dpOutput,
+                            mOutputs.valueFor(mHardwareOutput)->mLatency*2);
+        }
+#endif
+        if (output != mHardwareOutput) {
+            setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true);
+        }
+        return NO_ERROR;
+    } else {
+        LOGW("stopOutput() refcount is already 0 for output %d", output);
+        return INVALID_OPERATION;
+    }
+}
+
+void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output)
+{
+    LOGV("releaseOutput() %d", output);
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("releaseOutput() releasing unknown output %d", output);
+        return;
+    }
+
+#ifdef AUDIO_POLICY_TEST
+    int testIndex = testOutputIndex(output);
+    if (testIndex != 0) {
+        AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index);
+        if (outputDesc->refCount() == 0) {
+            mpClientInterface->closeOutput(output);
+            delete mOutputs.valueAt(index);
+            mOutputs.removeItem(output);
+            mTestOutputs[testIndex] = 0;
+        }
+        return;
+    }
+#endif //AUDIO_POLICY_TEST
+
+    if (mOutputs.valueAt(index)->mFlags & AudioSystem::OUTPUT_FLAG_DIRECT) {
+        mpClientInterface->closeOutput(output);
+        delete mOutputs.valueAt(index);
+        mOutputs.removeItem(output);
+    }
+}
+
+audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::audio_in_acoustics acoustics)
+{
+    audio_io_handle_t input = 0;
+    uint32_t device = getDeviceForInputSource(inputSource);
+
+    LOGV("getInput() inputSource %d, samplingRate %d, format %d, channels %x, acoustics %x", inputSource, samplingRate, format, channels, acoustics);
+
+    if (device == 0) {
+        return 0;
+    }
+
+    // adapt channel selection to input source
+    switch(inputSource) {
+    case AUDIO_SOURCE_VOICE_UPLINK:
+        channels = AudioSystem::CHANNEL_IN_VOICE_UPLINK;
+        break;
+    case AUDIO_SOURCE_VOICE_DOWNLINK:
+        channels = AudioSystem::CHANNEL_IN_VOICE_DNLINK;
+        break;
+    case AUDIO_SOURCE_VOICE_CALL:
+        channels = (AudioSystem::CHANNEL_IN_VOICE_UPLINK | AudioSystem::CHANNEL_IN_VOICE_DNLINK);
+        break;
+    default:
+        break;
+    }
+
+    AudioInputDescriptor *inputDesc = new AudioInputDescriptor();
+
+    inputDesc->mInputSource = inputSource;
+    inputDesc->mDevice = device;
+    inputDesc->mSamplingRate = samplingRate;
+    inputDesc->mFormat = format;
+    inputDesc->mChannels = channels;
+    inputDesc->mAcoustics = acoustics;
+    inputDesc->mRefCount = 0;
+    input = mpClientInterface->openInput(&inputDesc->mDevice,
+                                    &inputDesc->mSamplingRate,
+                                    &inputDesc->mFormat,
+                                    &inputDesc->mChannels,
+                                    inputDesc->mAcoustics);
+
+    // only accept input with the exact requested set of parameters
+    if (input == 0 ||
+        (samplingRate != inputDesc->mSamplingRate) ||
+        (format != inputDesc->mFormat) ||
+        (channels != inputDesc->mChannels)) {
+        LOGV("getInput() failed opening input: samplingRate %d, format %d, channels %d",
+                samplingRate, format, channels);
+        if (input != 0) {
+            mpClientInterface->closeInput(input);
+        }
+        delete inputDesc;
+        return 0;
+    }
+    mInputs.add(input, inputDesc);
+    return input;
+}
+
+status_t AudioPolicyManagerBase::startInput(audio_io_handle_t input)
+{
+    LOGV("startInput() input %d", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("startInput() unknow input %d", input);
+        return BAD_VALUE;
+    }
+    AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
+
+#ifdef AUDIO_POLICY_TEST
+    if (mTestInput == 0)
+#endif //AUDIO_POLICY_TEST
+    {
+        // refuse 2 active AudioRecord clients at the same time
+        if (getActiveInput() != 0) {
+            LOGW("startInput() input %d failed: other input already started", input);
+            return INVALID_OPERATION;
+        }
+    }
+
+    AudioParameter param = AudioParameter();
+    param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
+
+    // use Voice Recognition mode or not for this input based on input source
+    int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
+    param.addInt(String8("vr_mode"), vr_enabled);
+    LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
+
+    mpClientInterface->setParameters(input, param.toString());
+
+    inputDesc->mRefCount = 1;
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerBase::stopInput(audio_io_handle_t input)
+{
+    LOGV("stopInput() input %d", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("stopInput() unknow input %d", input);
+        return BAD_VALUE;
+    }
+    AudioInputDescriptor *inputDesc = mInputs.valueAt(index);
+
+    if (inputDesc->mRefCount == 0) {
+        LOGW("stopInput() input %d already stopped", input);
+        return INVALID_OPERATION;
+    } else {
+        AudioParameter param = AudioParameter();
+        param.addInt(String8(AudioParameter::keyRouting), 0);
+        mpClientInterface->setParameters(input, param.toString());
+        inputDesc->mRefCount = 0;
+        return NO_ERROR;
+    }
+}
+
+void AudioPolicyManagerBase::releaseInput(audio_io_handle_t input)
+{
+    LOGV("releaseInput() %d", input);
+    ssize_t index = mInputs.indexOfKey(input);
+    if (index < 0) {
+        LOGW("releaseInput() releasing unknown input %d", input);
+        return;
+    }
+    mpClientInterface->closeInput(input);
+    delete mInputs.valueAt(index);
+    mInputs.removeItem(input);
+    LOGV("releaseInput() exit");
+}
+
+void AudioPolicyManagerBase::initStreamVolume(AudioSystem::stream_type stream,
+                                            int indexMin,
+                                            int indexMax)
+{
+    LOGV("initStreamVolume() stream %d, min %d, max %d", stream , indexMin, indexMax);
+    if (indexMin < 0 || indexMin >= indexMax) {
+        LOGW("initStreamVolume() invalid index limits for stream %d, min %d, max %d", stream , indexMin, indexMax);
+        return;
+    }
+    mStreams[stream].mIndexMin = indexMin;
+    mStreams[stream].mIndexMax = indexMax;
+}
+
+status_t AudioPolicyManagerBase::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+{
+
+    if ((index < mStreams[stream].mIndexMin) || (index > mStreams[stream].mIndexMax)) {
+        return BAD_VALUE;
+    }
+
+    // Force max volume if stream cannot be muted
+    if (!mStreams[stream].mCanBeMuted) index = mStreams[stream].mIndexMax;
+
+    LOGV("setStreamVolumeIndex() stream %d, index %d", stream, index);
+    mStreams[stream].mIndexCur = index;
+
+    // compute and apply stream volume on all outputs according to connected device
+    status_t status = NO_ERROR;
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        status_t volStatus = checkAndSetVolume(stream, index, mOutputs.keyAt(i), mOutputs.valueAt(i)->device());
+        if (volStatus != NO_ERROR) {
+            status = volStatus;
+        }
+    }
+    return status;
+}
+
+status_t AudioPolicyManagerBase::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+{
+    if (index == 0) {
+        return BAD_VALUE;
+    }
+    LOGV("getStreamVolumeIndex() stream %d", stream);
+    *index =  mStreams[stream].mIndexCur;
+    return NO_ERROR;
+}
+
+audio_io_handle_t AudioPolicyManagerBase::getOutputForEffect(effect_descriptor_t *desc)
+{
+    LOGV("getOutputForEffect()");
+    // apply simple rule where global effects are attached to the same output as MUSIC streams
+    return getOutput(AudioSystem::MUSIC);
+}
+
+status_t AudioPolicyManagerBase::registerEffect(effect_descriptor_t *desc,
+                                audio_io_handle_t output,
+                                uint32_t strategy,
+                                int session,
+                                int id)
+{
+    ssize_t index = mOutputs.indexOfKey(output);
+    if (index < 0) {
+        LOGW("registerEffect() unknown output %d", output);
+        return INVALID_OPERATION;
+    }
+
+    if (mTotalEffectsCpuLoad + desc->cpuLoad > getMaxEffectsCpuLoad()) {
+        LOGW("registerEffect() CPU Load limit exceeded for Fx %s, CPU %f MIPS",
+                desc->name, (float)desc->cpuLoad/10);
+        return INVALID_OPERATION;
+    }
+    if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
+        LOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
+                desc->name, desc->memoryUsage);
+        return INVALID_OPERATION;
+    }
+    mTotalEffectsCpuLoad += desc->cpuLoad;
+    mTotalEffectsMemory += desc->memoryUsage;
+    LOGV("registerEffect() effect %s, output %d, strategy %d session %d id %d",
+            desc->name, output, strategy, session, id);
+
+    LOGV("registerEffect() CPU %d, memory %d", desc->cpuLoad, desc->memoryUsage);
+    LOGV("  total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
+
+    EffectDescriptor *pDesc = new EffectDescriptor();
+    memcpy (&pDesc->mDesc, desc, sizeof(effect_descriptor_t));
+    pDesc->mOutput = output;
+    pDesc->mStrategy = (routing_strategy)strategy;
+    pDesc->mSession = session;
+    mEffects.add(id, pDesc);
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerBase::unregisterEffect(int id)
+{
+    ssize_t index = mEffects.indexOfKey(id);
+    if (index < 0) {
+        LOGW("unregisterEffect() unknown effect ID %d", id);
+        return INVALID_OPERATION;
+    }
+
+    EffectDescriptor *pDesc = mEffects.valueAt(index);
+
+    if (mTotalEffectsCpuLoad < pDesc->mDesc.cpuLoad) {
+        LOGW("unregisterEffect() CPU load %d too high for total %d",
+                pDesc->mDesc.cpuLoad, mTotalEffectsCpuLoad);
+        pDesc->mDesc.cpuLoad = mTotalEffectsCpuLoad;
+    }
+    mTotalEffectsCpuLoad -= pDesc->mDesc.cpuLoad;
+    if (mTotalEffectsMemory < pDesc->mDesc.memoryUsage) {
+        LOGW("unregisterEffect() memory %d too big for total %d",
+                pDesc->mDesc.memoryUsage, mTotalEffectsMemory);
+        pDesc->mDesc.memoryUsage = mTotalEffectsMemory;
+    }
+    mTotalEffectsMemory -= pDesc->mDesc.memoryUsage;
+    LOGV("unregisterEffect() effect %s, ID %d, CPU %d, memory %d",
+            pDesc->mDesc.name, id, pDesc->mDesc.cpuLoad, pDesc->mDesc.memoryUsage);
+    LOGV("  total CPU %d, total memory %d", mTotalEffectsCpuLoad, mTotalEffectsMemory);
+
+    mEffects.removeItem(id);
+    delete pDesc;
+
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerBase::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "\nAudioPolicyManager Dump: %p\n", this);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Hardware Output: %d\n", mHardwareOutput);
+    result.append(buffer);
+#ifdef WITH_A2DP
+    snprintf(buffer, SIZE, " A2DP Output: %d\n", mA2dpOutput);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Duplicated Output: %d\n", mDuplicatedOutput);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " A2DP device address: %s\n", mA2dpDeviceAddress.string());
+    result.append(buffer);
+#endif
+    snprintf(buffer, SIZE, " SCO device address: %s\n", mScoDeviceAddress.string());
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Output devices: %08x\n", mAvailableOutputDevices);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Input devices: %08x\n", mAvailableInputDevices);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Phone state: %d\n", mPhoneState);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Ringer mode: %d\n", mRingerMode);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for communications %d\n", mForceUse[AudioSystem::FOR_COMMUNICATION]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for media %d\n", mForceUse[AudioSystem::FOR_MEDIA]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for record %d\n", mForceUse[AudioSystem::FOR_RECORD]);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Force use for dock %d\n", mForceUse[AudioSystem::FOR_DOCK]);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    snprintf(buffer, SIZE, "\nOutputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < mOutputs.size(); i++) {
+        snprintf(buffer, SIZE, "- Output %d dump:\n", mOutputs.keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        mOutputs.valueAt(i)->dump(fd);
+    }
+
+    snprintf(buffer, SIZE, "\nInputs dump:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < mInputs.size(); i++) {
+        snprintf(buffer, SIZE, "- Input %d dump:\n", mInputs.keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        mInputs.valueAt(i)->dump(fd);
+    }
+
+    snprintf(buffer, SIZE, "\nStreams dump:\n");
+    write(fd, buffer, strlen(buffer));
+    snprintf(buffer, SIZE, " Stream  Index Min  Index Max  Index Cur  Can be muted\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        snprintf(buffer, SIZE, " %02d", i);
+        mStreams[i].dump(buffer + 3, SIZE);
+        write(fd, buffer, strlen(buffer));
+    }
+
+    snprintf(buffer, SIZE, "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB\n",
+            (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory);
+    write(fd, buffer, strlen(buffer));
+
+    snprintf(buffer, SIZE, "Registered effects:\n");
+    write(fd, buffer, strlen(buffer));
+    for (size_t i = 0; i < mEffects.size(); i++) {
+        snprintf(buffer, SIZE, "- Effect %d dump:\n", mEffects.keyAt(i));
+        write(fd, buffer, strlen(buffer));
+        mEffects.valueAt(i)->dump(fd);
+    }
+
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+// AudioPolicyManagerBase
+// ----------------------------------------------------------------------------
+
+AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface)
+    :
+#ifdef AUDIO_POLICY_TEST
+    Thread(false),
+#endif //AUDIO_POLICY_TEST
+    mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0),
+    mLimitRingtoneVolume(false), mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0)
+{
+    mpClientInterface = clientInterface;
+
+    for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) {
+        mForceUse[i] = AudioSystem::FORCE_NONE;
+    }
+
+    // devices available by default are speaker, ear piece and microphone
+    mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE |
+                        AudioSystem::DEVICE_OUT_SPEAKER;
+    mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+
+#ifdef WITH_A2DP
+    mA2dpOutput = 0;
+    mDuplicatedOutput = 0;
+    mA2dpDeviceAddress = String8("");
+#endif
+    mScoDeviceAddress = String8("");
+
+    // open hardware output
+    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+    outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
+    mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                    &outputDesc->mSamplingRate,
+                                    &outputDesc->mFormat,
+                                    &outputDesc->mChannels,
+                                    &outputDesc->mLatency,
+                                    outputDesc->mFlags);
+
+    if (mHardwareOutput == 0) {
+        LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d",
+                outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
+    } else {
+        addOutput(mHardwareOutput, outputDesc);
+        setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true);
+        //TODO: configure audio effect output stage here
+    }
+
+    updateDeviceForStrategy();
+#ifdef AUDIO_POLICY_TEST
+    AudioParameter outputCmd = AudioParameter();
+    outputCmd.addInt(String8("set_id"), 0);
+    mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
+
+    mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER;
+    mTestSamplingRate = 44100;
+    mTestFormat = AudioSystem::PCM_16_BIT;
+    mTestChannels =  AudioSystem::CHANNEL_OUT_STEREO;
+    mTestLatencyMs = 0;
+    mCurOutput = 0;
+    mDirectOutput = false;
+    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
+        mTestOutputs[i] = 0;
+    }
+
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    snprintf(buffer, SIZE, "AudioPolicyManagerTest");
+    run(buffer, ANDROID_PRIORITY_AUDIO);
+#endif //AUDIO_POLICY_TEST
+}
+
+AudioPolicyManagerBase::~AudioPolicyManagerBase()
+{
+#ifdef AUDIO_POLICY_TEST
+    exit();
+#endif //AUDIO_POLICY_TEST
+   for (size_t i = 0; i < mOutputs.size(); i++) {
+        mpClientInterface->closeOutput(mOutputs.keyAt(i));
+        delete mOutputs.valueAt(i);
+   }
+   mOutputs.clear();
+   for (size_t i = 0; i < mInputs.size(); i++) {
+        mpClientInterface->closeInput(mInputs.keyAt(i));
+        delete mInputs.valueAt(i);
+   }
+   mInputs.clear();
+}
+
+#ifdef AUDIO_POLICY_TEST
+bool AudioPolicyManagerBase::threadLoop()
+{
+    LOGV("entering threadLoop()");
+    while (!exitPending())
+    {
+        String8 command;
+        int valueInt;
+        String8 value;
+
+        Mutex::Autolock _l(mLock);
+        mWaitWorkCV.waitRelative(mLock, milliseconds(50));
+
+        command = mpClientInterface->getParameters(0, String8("test_cmd_policy"));
+        AudioParameter param = AudioParameter(command);
+
+        if (param.getInt(String8("test_cmd_policy"), valueInt) == NO_ERROR &&
+            valueInt != 0) {
+            LOGV("Test command %s received", command.string());
+            String8 target;
+            if (param.get(String8("target"), target) != NO_ERROR) {
+                target = "Manager";
+            }
+            if (param.getInt(String8("test_cmd_policy_output"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_output"));
+                mCurOutput = valueInt;
+            }
+            if (param.get(String8("test_cmd_policy_direct"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_direct"));
+                if (value == "false") {
+                    mDirectOutput = false;
+                } else if (value == "true") {
+                    mDirectOutput = true;
+                }
+            }
+            if (param.getInt(String8("test_cmd_policy_input"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_input"));
+                mTestInput = valueInt;
+            }
+
+            if (param.get(String8("test_cmd_policy_format"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_format"));
+                int format = AudioSystem::INVALID_FORMAT;
+                if (value == "PCM 16 bits") {
+                    format = AudioSystem::PCM_16_BIT;
+                } else if (value == "PCM 8 bits") {
+                    format = AudioSystem::PCM_8_BIT;
+                } else if (value == "Compressed MP3") {
+                    format = AudioSystem::MP3;
+                }
+                if (format != AudioSystem::INVALID_FORMAT) {
+                    if (target == "Manager") {
+                        mTestFormat = format;
+                    } else if (mTestOutputs[mCurOutput] != 0) {
+                        AudioParameter outputParam = AudioParameter();
+                        outputParam.addInt(String8("format"), format);
+                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
+                    }
+                }
+            }
+            if (param.get(String8("test_cmd_policy_channels"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_channels"));
+                int channels = 0;
+
+                if (value == "Channels Stereo") {
+                    channels =  AudioSystem::CHANNEL_OUT_STEREO;
+                } else if (value == "Channels Mono") {
+                    channels =  AudioSystem::CHANNEL_OUT_MONO;
+                }
+                if (channels != 0) {
+                    if (target == "Manager") {
+                        mTestChannels = channels;
+                    } else if (mTestOutputs[mCurOutput] != 0) {
+                        AudioParameter outputParam = AudioParameter();
+                        outputParam.addInt(String8("channels"), channels);
+                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
+                    }
+                }
+            }
+            if (param.getInt(String8("test_cmd_policy_sampleRate"), valueInt) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_sampleRate"));
+                if (valueInt >= 0 && valueInt <= 96000) {
+                    int samplingRate = valueInt;
+                    if (target == "Manager") {
+                        mTestSamplingRate = samplingRate;
+                    } else if (mTestOutputs[mCurOutput] != 0) {
+                        AudioParameter outputParam = AudioParameter();
+                        outputParam.addInt(String8("sampling_rate"), samplingRate);
+                        mpClientInterface->setParameters(mTestOutputs[mCurOutput], outputParam.toString());
+                    }
+                }
+            }
+
+            if (param.get(String8("test_cmd_policy_reopen"), value) == NO_ERROR) {
+                param.remove(String8("test_cmd_policy_reopen"));
+
+                mpClientInterface->closeOutput(mHardwareOutput);
+                delete mOutputs.valueFor(mHardwareOutput);
+                mOutputs.removeItem(mHardwareOutput);
+
+                AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+                outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER;
+                mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                                &outputDesc->mSamplingRate,
+                                                &outputDesc->mFormat,
+                                                &outputDesc->mChannels,
+                                                &outputDesc->mLatency,
+                                                outputDesc->mFlags);
+                if (mHardwareOutput == 0) {
+                    LOGE("Failed to reopen hardware output stream, samplingRate: %d, format %d, channels %d",
+                            outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels);
+                } else {
+                    AudioParameter outputCmd = AudioParameter();
+                    outputCmd.addInt(String8("set_id"), 0);
+                    mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString());
+                    addOutput(mHardwareOutput, outputDesc);
+                }
+            }
+
+
+            mpClientInterface->setParameters(0, String8("test_cmd_policy="));
+        }
+    }
+    return false;
+}
+
+void AudioPolicyManagerBase::exit()
+{
+    {
+        AutoMutex _l(mLock);
+        requestExit();
+        mWaitWorkCV.signal();
+    }
+    requestExitAndWait();
+}
+
+int AudioPolicyManagerBase::testOutputIndex(audio_io_handle_t output)
+{
+    for (int i = 0; i < NUM_TEST_OUTPUTS; i++) {
+        if (output == mTestOutputs[i]) return i;
+    }
+    return 0;
+}
+#endif //AUDIO_POLICY_TEST
+
+// ---
+
+void AudioPolicyManagerBase::addOutput(audio_io_handle_t id, AudioOutputDescriptor *outputDesc)
+{
+    outputDesc->mId = id;
+    mOutputs.add(id, outputDesc);
+}
+
+
+#ifdef WITH_A2DP
+status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices device,
+                                                 const char *device_address)
+{
+    // when an A2DP device is connected, open an A2DP and a duplicated output
+    LOGV("opening A2DP output for device %s", device_address);
+    AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
+    outputDesc->mDevice = device;
+    mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice,
+                                            &outputDesc->mSamplingRate,
+                                            &outputDesc->mFormat,
+                                            &outputDesc->mChannels,
+                                            &outputDesc->mLatency,
+                                            outputDesc->mFlags);
+    if (mA2dpOutput) {
+        // add A2DP output descriptor
+        addOutput(mA2dpOutput, outputDesc);
+
+        //TODO: configure audio effect output stage here
+
+        // set initial stream volume for A2DP device
+        applyStreamVolumes(mA2dpOutput, device);
+        if (a2dpUsedForSonification()) {
+            mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput);
+        }
+        if (mDuplicatedOutput != 0 ||
+            !a2dpUsedForSonification()) {
+            // If both A2DP and duplicated outputs are open, send device address to A2DP hardware
+            // interface
+            AudioParameter param;
+            param.add(String8("a2dp_sink_address"), String8(device_address));
+            mpClientInterface->setParameters(mA2dpOutput, param.toString());
+            mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN);
+
+            if (a2dpUsedForSonification()) {
+                // add duplicated output descriptor
+                AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor();
+                dupOutputDesc->mOutput1 = mOutputs.valueFor(mHardwareOutput);
+                dupOutputDesc->mOutput2 = mOutputs.valueFor(mA2dpOutput);
+                dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate;
+                dupOutputDesc->mFormat = outputDesc->mFormat;
+                dupOutputDesc->mChannels = outputDesc->mChannels;
+                dupOutputDesc->mLatency = outputDesc->mLatency;
+                addOutput(mDuplicatedOutput, dupOutputDesc);
+                applyStreamVolumes(mDuplicatedOutput, device);
+            }
+        } else {
+            LOGW("getOutput() could not open duplicated output for %d and %d",
+                    mHardwareOutput, mA2dpOutput);
+            mpClientInterface->closeOutput(mA2dpOutput);
+            mOutputs.removeItem(mA2dpOutput);
+            mA2dpOutput = 0;
+            delete outputDesc;
+            return NO_INIT;
+        }
+    } else {
+        LOGW("setDeviceConnectionState() could not open A2DP output for device %x", device);
+        delete outputDesc;
+        return NO_INIT;
+    }
+    AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
+
+    if (mScoDeviceAddress != "") {
+        // It is normal to suspend twice if we are both in call,
+        // and have the hardware audio output routed to BT SCO
+        if (mPhoneState != AudioSystem::MODE_NORMAL) {
+            mpClientInterface->suspendOutput(mA2dpOutput);
+        }
+        if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)hwOutputDesc->device())) {
+            mpClientInterface->suspendOutput(mA2dpOutput);
+        }
+    }
+
+    if (!a2dpUsedForSonification()) {
+        // mute music on A2DP output if a notification or ringtone is playing
+        uint32_t refCount = hwOutputDesc->strategyRefCount(STRATEGY_SONIFICATION);
+        for (uint32_t i = 0; i < refCount; i++) {
+            setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput);
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyManagerBase::handleA2dpDisconnection(AudioSystem::audio_devices device,
+                                                    const char *device_address)
+{
+    if (mA2dpOutput == 0) {
+        LOGW("setDeviceConnectionState() disconnecting A2DP and no A2DP output!");
+        return INVALID_OPERATION;
+    }
+
+    if (mA2dpDeviceAddress != device_address) {
+        LOGW("setDeviceConnectionState() disconnecting unknow A2DP sink address %s", device_address);
+        return INVALID_OPERATION;
+    }
+
+    // mute media strategy to avoid outputting sound on hardware output while music stream
+    // is switched from A2DP output and before music is paused by music application
+    setStrategyMute(STRATEGY_MEDIA, true, mHardwareOutput);
+    setStrategyMute(STRATEGY_MEDIA, false, mHardwareOutput, MUTE_TIME_MS);
+
+    if (!a2dpUsedForSonification()) {
+        // unmute music on A2DP output if a notification or ringtone is playing
+        uint32_t refCount = mOutputs.valueFor(mHardwareOutput)->strategyRefCount(STRATEGY_SONIFICATION);
+        for (uint32_t i = 0; i < refCount; i++) {
+            setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput);
+        }
+    }
+    mA2dpDeviceAddress = "";
+    return NO_ERROR;
+}
+
+void AudioPolicyManagerBase::closeA2dpOutputs()
+{
+    LOGV("setDeviceConnectionState() closing A2DP and duplicated output!");
+
+    if (mDuplicatedOutput != 0) {
+        AudioOutputDescriptor *dupOutputDesc = mOutputs.valueFor(mDuplicatedOutput);
+        AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput);
+        // As all active tracks on duplicated output will be deleted,
+        // and as they were also referenced on hardware output, the reference
+        // count for their stream type must be adjusted accordingly on
+        // hardware output.
+        for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+            int refCount = dupOutputDesc->mRefCount[i];
+            hwOutputDesc->changeRefCount((AudioSystem::stream_type)i,-refCount);
+        }
+
+        mpClientInterface->closeOutput(mDuplicatedOutput);
+        delete mOutputs.valueFor(mDuplicatedOutput);
+        mOutputs.removeItem(mDuplicatedOutput);
+        mDuplicatedOutput = 0;
+    }
+    if (mA2dpOutput != 0) {
+        AudioParameter param;
+        param.add(String8("closing"), String8("true"));
+        mpClientInterface->setParameters(mA2dpOutput, param.toString());
+
+        mpClientInterface->closeOutput(mA2dpOutput);
+        delete mOutputs.valueFor(mA2dpOutput);
+        mOutputs.removeItem(mA2dpOutput);
+        mA2dpOutput = 0;
+    }
+}
+
+void AudioPolicyManagerBase::checkOutputForStrategy(routing_strategy strategy, uint32_t &newDevice)
+{
+    uint32_t prevDevice = getDeviceForStrategy(strategy);
+    uint32_t curDevice = getDeviceForStrategy(strategy, false);
+    bool a2dpWasUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(prevDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
+    bool a2dpIsUsed = AudioSystem::isA2dpDevice((AudioSystem::audio_devices)(curDevice & ~AudioSystem::DEVICE_OUT_SPEAKER));
+    audio_io_handle_t srcOutput = 0;
+    audio_io_handle_t dstOutput = 0;
+
+    if (a2dpWasUsed && !a2dpIsUsed) {
+        bool dupUsed = a2dpUsedForSonification() && a2dpWasUsed && (AudioSystem::popCount(prevDevice) == 2);
+        dstOutput = mHardwareOutput;
+        if (dupUsed) {
+            LOGV("checkOutputForStrategy() moving strategy %d from duplicated", strategy);
+            srcOutput = mDuplicatedOutput;
+        } else {
+            LOGV("checkOutputForStrategy() moving strategy %d from a2dp", strategy);
+            srcOutput = mA2dpOutput;
+        }
+
+        // do not change newDevice if it was already set before this call by a previous call to
+        // getNewDevice() or checkOutputForStrategy() for a strategy with higher priority
+        if (newDevice == 0 && mOutputs.valueFor(mHardwareOutput)->isUsedByStrategy(strategy)) {
+            newDevice = getDeviceForStrategy(strategy, false);
+        }
+    }
+    if (a2dpIsUsed && !a2dpWasUsed) {
+        bool dupUsed = a2dpUsedForSonification() && a2dpIsUsed && (AudioSystem::popCount(curDevice) == 2);
+        srcOutput = mHardwareOutput;
+        if (dupUsed) {
+            LOGV("checkOutputForStrategy() moving strategy %d to duplicated", strategy);
+            dstOutput = mDuplicatedOutput;
+        } else {
+            LOGV("checkOutputForStrategy() moving strategy %d to a2dp", strategy);
+            dstOutput = mA2dpOutput;
+        }
+    }
+
+    if (srcOutput != 0 && dstOutput != 0) {
+        // Move effects associated to this strategy from previous output to new output
+        for (size_t i = 0; i < mEffects.size(); i++) {
+            EffectDescriptor *desc = mEffects.valueAt(i);
+            if (desc->mSession != AudioSystem::SESSION_OUTPUT_STAGE &&
+                    desc->mStrategy == strategy &&
+                    desc->mOutput == srcOutput) {
+                LOGV("checkOutputForStrategy() moving effect %d to output %d", mEffects.keyAt(i), dstOutput);
+                mpClientInterface->moveEffects(desc->mSession, srcOutput, dstOutput);
+                desc->mOutput = dstOutput;
+            }
+        }
+        // Move tracks associated to this strategy from previous output to new output
+        for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+            if (getStrategy((AudioSystem::stream_type)i) == strategy) {
+                mpClientInterface->setStreamOutput((AudioSystem::stream_type)i, dstOutput);
+            }
+        }
+    }
+}
+
+void AudioPolicyManagerBase::checkOutputForAllStrategies(uint32_t &newDevice)
+{
+    // Check strategies in order of priority so that once newDevice is set
+    // for a given strategy it is not modified by subsequent calls to
+    // checkOutputForStrategy()
+    checkOutputForStrategy(STRATEGY_PHONE, newDevice);
+    checkOutputForStrategy(STRATEGY_SONIFICATION, newDevice);
+    checkOutputForStrategy(STRATEGY_MEDIA, newDevice);
+    checkOutputForStrategy(STRATEGY_DTMF, newDevice);
+}
+
+#endif
+
+uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache)
+{
+    uint32_t device = 0;
+
+    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
+    // check the following by order of priority to request a routing change if necessary:
+    // 1: we are in call or the strategy phone is active on the hardware output:
+    //      use device for strategy phone
+    // 2: the strategy sonification is active on the hardware output:
+    //      use device for strategy sonification
+    // 3: the strategy media is active on the hardware output:
+    //      use device for strategy media
+    // 4: the strategy DTMF is active on the hardware output:
+    //      use device for strategy DTMF
+    if (mPhoneState == AudioSystem::MODE_IN_CALL ||
+        outputDesc->isUsedByStrategy(STRATEGY_PHONE)) {
+        device = getDeviceForStrategy(STRATEGY_PHONE, fromCache);
+    } else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) {
+        device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache);
+    } else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) {
+        device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache);
+    } else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) {
+        device = getDeviceForStrategy(STRATEGY_DTMF, fromCache);
+    }
+
+    LOGV("getNewDevice() selected device %x", device);
+    return device;
+}
+
+uint32_t AudioPolicyManagerBase::getStrategyForStream(AudioSystem::stream_type stream) {
+    return (uint32_t)getStrategy(stream);
+}
+
+AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy(
+        AudioSystem::stream_type stream) {
+    // stream to strategy mapping
+    switch (stream) {
+    case AudioSystem::VOICE_CALL:
+    case AudioSystem::BLUETOOTH_SCO:
+        return STRATEGY_PHONE;
+    case AudioSystem::RING:
+    case AudioSystem::NOTIFICATION:
+    case AudioSystem::ALARM:
+    case AudioSystem::ENFORCED_AUDIBLE:
+        return STRATEGY_SONIFICATION;
+    case AudioSystem::DTMF:
+        return STRATEGY_DTMF;
+    default:
+        LOGE("unknown stream type");
+    case AudioSystem::SYSTEM:
+        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
+        // while key clicks are played produces a poor result
+    case AudioSystem::TTS:
+    case AudioSystem::MUSIC:
+        return STRATEGY_MEDIA;
+    }
+}
+
+uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache)
+{
+    uint32_t device = 0;
+
+    if (fromCache) {
+        LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]);
+        return mDeviceForStrategy[strategy];
+    }
+
+    switch (strategy) {
+    case STRATEGY_DTMF:
+        if (mPhoneState != AudioSystem::MODE_IN_CALL) {
+            // when off call, DTMF strategy follows the same rules as MEDIA strategy
+            device = getDeviceForStrategy(STRATEGY_MEDIA, false);
+            break;
+        }
+        // when in call, DTMF and PHONE strategies follow the same rules
+        // FALL THROUGH
+
+    case STRATEGY_PHONE:
+        // for phone strategy, we first consider the forced use and then the available devices by order
+        // of priority
+        switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) {
+        case AudioSystem::FORCE_BT_SCO:
+            if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
+                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+                if (device) break;
+            }
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+            if (device) break;
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
+            if (device) break;
+            // if SCO device is requested but no SCO device is available, fall back to default case
+            // FALL THROUGH
+
+        default:    // FORCE_NONE
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
+            if (device) break;
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
+            if (device) break;
+#ifdef WITH_A2DP
+            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP
+            if (mPhoneState != AudioSystem::MODE_IN_CALL) {
+                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
+                if (device) break;
+                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+                if (device) break;
+            }
+#endif
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE;
+            if (device == 0) {
+                LOGE("getDeviceForStrategy() earpiece device not found");
+            }
+            break;
+
+        case AudioSystem::FORCE_SPEAKER:
+            if (mPhoneState != AudioSystem::MODE_IN_CALL || strategy != STRATEGY_DTMF) {
+                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+                if (device) break;
+            }
+#ifdef WITH_A2DP
+            // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
+            // A2DP speaker when forcing to speaker output
+            if (mPhoneState != AudioSystem::MODE_IN_CALL) {
+                device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+                if (device) break;
+            }
+#endif
+            device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
+            if (device == 0) {
+                LOGE("getDeviceForStrategy() speaker device not found");
+            }
+            break;
+        }
+    break;
+
+    case STRATEGY_SONIFICATION:
+
+        // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by
+        // handleIncallSonification().
+        if (mPhoneState == AudioSystem::MODE_IN_CALL) {
+            device = getDeviceForStrategy(STRATEGY_PHONE, false);
+            break;
+        }
+        device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
+        if (device == 0) {
+            LOGE("getDeviceForStrategy() speaker device not found");
+        }
+        // The second device used for sonification is the same as the device used by media strategy
+        // FALL THROUGH
+
+    case STRATEGY_MEDIA: {
+        uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL;
+        if (device2 == 0) {
+            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE;
+        }
+        if (device2 == 0) {
+            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET;
+        }
+#ifdef WITH_A2DP
+        if (mA2dpOutput != 0) {
+            if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) {
+                break;
+            }
+            if (device2 == 0) {
+                device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
+            }
+            if (device2 == 0) {
+                device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
+            }
+            if (device2 == 0) {
+                device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
+            }
+        }
+#endif
+        if (device2 == 0) {
+            device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER;
+        }
+
+        // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise
+        device |= device2;
+        if (device == 0) {
+            LOGE("getDeviceForStrategy() speaker device not found");
+        }
+        } break;
+
+    default:
+        LOGW("getDeviceForStrategy() unknown strategy: %d", strategy);
+        break;
+    }
+
+    LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device);
+    return device;
+}
+
+void AudioPolicyManagerBase::updateDeviceForStrategy()
+{
+    for (int i = 0; i < NUM_STRATEGIES; i++) {
+        mDeviceForStrategy[i] = getDeviceForStrategy((routing_strategy)i, false);
+    }
+}
+
+void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs)
+{
+    LOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs);
+    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
+
+
+    if (outputDesc->isDuplicated()) {
+        setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs);
+        setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs);
+        return;
+    }
+#ifdef WITH_A2DP
+    // filter devices according to output selected
+    if (output == mA2dpOutput) {
+        device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
+    } else {
+        device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
+    }
+#endif
+
+    uint32_t prevDevice = (uint32_t)outputDesc->device();
+    // Do not change the routing if:
+    //  - the requestede device is 0
+    //  - the requested device is the same as current device and force is not specified.
+    // Doing this check here allows the caller to call setOutputDevice() without conditions
+    if ((device == 0 || device == prevDevice) && !force) {
+        LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
+        return;
+    }
+
+    outputDesc->mDevice = device;
+    // mute media streams if both speaker and headset are selected
+    if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) {
+        setStrategyMute(STRATEGY_MEDIA, true, output);
+        // wait for the PCM output buffers to empty before proceeding with the rest of the command
+        usleep(outputDesc->mLatency*2*1000);
+    }
+#ifdef WITH_A2DP
+    // suspend A2DP output if SCO device is selected
+    if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)device)) {
+         if (mA2dpOutput != 0) {
+             mpClientInterface->suspendOutput(mA2dpOutput);
+         }
+    }
+#endif
+    // do the routing
+    AudioParameter param = AudioParameter();
+    param.addInt(String8(AudioParameter::keyRouting), (int)device);
+    mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs);
+    // update stream volumes according to new device
+    applyStreamVolumes(output, device, delayMs);
+
+#ifdef WITH_A2DP
+    // if disconnecting SCO device, restore A2DP output
+    if (AudioSystem::isBluetoothScoDevice((AudioSystem::audio_devices)prevDevice)) {
+         if (mA2dpOutput != 0) {
+             LOGV("restore A2DP output");
+             mpClientInterface->restoreOutput(mA2dpOutput);
+         }
+    }
+#endif
+    // if changing from a combined headset + speaker route, unmute media streams
+    if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) {
+        setStrategyMute(STRATEGY_MEDIA, false, output, delayMs);
+    }
+}
+
+uint32_t AudioPolicyManagerBase::getDeviceForInputSource(int inputSource)
+{
+    uint32_t device;
+
+    switch(inputSource) {
+    case AUDIO_SOURCE_DEFAULT:
+    case AUDIO_SOURCE_MIC:
+    case AUDIO_SOURCE_VOICE_RECOGNITION:
+        if (mForceUse[AudioSystem::FOR_RECORD] == AudioSystem::FORCE_BT_SCO &&
+            mAvailableInputDevices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
+            device = AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+        } else if (mAvailableInputDevices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
+            device = AudioSystem::DEVICE_IN_WIRED_HEADSET;
+        } else {
+            device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+        }
+        break;
+    case AUDIO_SOURCE_CAMCORDER:
+        if (hasBackMicrophone()) {
+            device = AudioSystem::DEVICE_IN_BACK_MIC;
+        } else {
+            device = AudioSystem::DEVICE_IN_BUILTIN_MIC;
+        }
+        break;
+    case AUDIO_SOURCE_VOICE_UPLINK:
+    case AUDIO_SOURCE_VOICE_DOWNLINK:
+    case AUDIO_SOURCE_VOICE_CALL:
+        device = AudioSystem::DEVICE_IN_VOICE_CALL;
+        break;
+    default:
+        LOGW("getInput() invalid input source %d", inputSource);
+        device = 0;
+        break;
+    }
+    LOGV("getDeviceForInputSource()input source %d, device %08x", inputSource, device);
+    return device;
+}
+
+audio_io_handle_t AudioPolicyManagerBase::getActiveInput()
+{
+    for (size_t i = 0; i < mInputs.size(); i++) {
+        if (mInputs.valueAt(i)->mRefCount > 0) {
+            return mInputs.keyAt(i);
+        }
+    }
+    return 0;
+}
+
+float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device)
+{
+    float volume = 1.0;
+    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
+    StreamDescriptor &streamDesc = mStreams[stream];
+
+    if (device == 0) {
+        device = outputDesc->device();
+    }
+
+    int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
+    volume = AudioSystem::linearToLog(volInt);
+
+    // if a headset is connected, apply the following rules to ring tones and notifications
+    // to avoid sound level bursts in user's ears:
+    // - always attenuate ring tones and notifications volume by 6dB
+    // - if music is playing, always limit the volume to current music volume,
+    // with a minimum threshold at -36dB so that notification is always perceived.
+    if ((device &
+        (AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP |
+        AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
+        AudioSystem::DEVICE_OUT_WIRED_HEADSET |
+        AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) &&
+        (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) &&
+        streamDesc.mCanBeMuted) {
+        volume *= SONIFICATION_HEADSET_VOLUME_FACTOR;
+        // when the phone is ringing we must consider that music could have been paused just before
+        // by the music application and behave as if music was active if the last music track was
+        // just stopped
+        if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) {
+            float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device);
+            float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN;
+            if (volume > minVol) {
+                volume = minVol;
+                LOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol);
+            }
+        }
+    }
+
+    return volume;
+}
+
+status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force)
+{
+
+    // do not change actual stream volume if the stream is muted
+    if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) {
+        LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]);
+        return NO_ERROR;
+    }
+
+    // do not change in call volume if bluetooth is connected and vice versa
+    if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) ||
+        (stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) {
+        LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm",
+             stream, mForceUse[AudioSystem::FOR_COMMUNICATION]);
+        return INVALID_OPERATION;
+    }
+
+    float volume = computeVolume(stream, index, output, device);
+    // do not set volume if the float value did not change
+    if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || force) {
+        mOutputs.valueFor(output)->mCurVolume[stream] = volume;
+        LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs);
+        if (stream == AudioSystem::VOICE_CALL ||
+            stream == AudioSystem::DTMF ||
+            stream == AudioSystem::BLUETOOTH_SCO) {
+            float voiceVolume = -1.0;
+            // offset value to reflect actual hardware volume that never reaches 0
+            // 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java)
+            volume = 0.01 + 0.99 * volume;
+            if (stream == AudioSystem::VOICE_CALL) {
+                voiceVolume = (float)index/(float)mStreams[stream].mIndexMax;
+            } else if (stream == AudioSystem::BLUETOOTH_SCO) {
+                voiceVolume = 1.0;
+            }
+            if (voiceVolume >= 0 && output == mHardwareOutput) {
+                mpClientInterface->setVoiceVolume(voiceVolume, delayMs);
+            }
+        }
+        mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs);
+    }
+
+    return NO_ERROR;
+}
+
+void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, uint32_t device, int delayMs)
+{
+    LOGV("applyStreamVolumes() for output %d and device %x", output, device);
+
+    for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+        checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, device, delayMs);
+    }
+}
+
+void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, int delayMs)
+{
+    LOGV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output);
+    for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) {
+        if (getStrategy((AudioSystem::stream_type)stream) == strategy) {
+            setStreamMute(stream, on, output, delayMs);
+        }
+    }
+}
+
+void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs)
+{
+    StreamDescriptor &streamDesc = mStreams[stream];
+    AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);
+
+    LOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]);
+
+    if (on) {
+        if (outputDesc->mMuteCount[stream] == 0) {
+            if (streamDesc.mCanBeMuted) {
+                checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs);
+            }
+        }
+        // increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored
+        outputDesc->mMuteCount[stream]++;
+    } else {
+        if (outputDesc->mMuteCount[stream] == 0) {
+            LOGW("setStreamMute() unmuting non muted stream!");
+            return;
+        }
+        if (--outputDesc->mMuteCount[stream] == 0) {
+            checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs);
+        }
+    }
+}
+
+void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting, bool stateChange)
+{
+    // if the stream pertains to sonification strategy and we are in call we must
+    // mute the stream if it is low visibility. If it is high visibility, we must play a tone
+    // in the device used for phone strategy and play the tone if the selected device does not
+    // interfere with the device used for phone strategy
+    // if stateChange is true, we are called from setPhoneState() and we must mute or unmute as
+    // many times as there are active tracks on the output
+
+    if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) {
+        AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput);
+        LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d",
+                stream, starting, outputDesc->mDevice, stateChange);
+        if (outputDesc->mRefCount[stream]) {
+            int muteCount = 1;
+            if (stateChange) {
+                muteCount = outputDesc->mRefCount[stream];
+            }
+            if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) {
+                LOGV("handleIncallSonification() low visibility, muteCount %d", muteCount);
+                for (int i = 0; i < muteCount; i++) {
+                    setStreamMute(stream, starting, mHardwareOutput);
+                }
+            } else {
+                LOGV("handleIncallSonification() high visibility");
+                if (outputDesc->device() & getDeviceForStrategy(STRATEGY_PHONE)) {
+                    LOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount);
+                    for (int i = 0; i < muteCount; i++) {
+                        setStreamMute(stream, starting, mHardwareOutput);
+                    }
+                }
+                if (starting) {
+                    mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL);
+                } else {
+                    mpClientInterface->stopTone();
+                }
+            }
+        }
+    }
+}
+
+bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::output_flags flags,
+                                    uint32_t device)
+{
+   return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
+          (format !=0 && !AudioSystem::isLinearPCM(format)));
+}
+
+uint32_t AudioPolicyManagerBase::getMaxEffectsCpuLoad()
+{
+    return MAX_EFFECTS_CPU_LOAD;
+}
+
+uint32_t AudioPolicyManagerBase::getMaxEffectsMemory()
+{
+    return MAX_EFFECTS_MEMORY;
+}
+
+// --- AudioOutputDescriptor class implementation
+
+AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
+    : mId(0), mSamplingRate(0), mFormat(0), mChannels(0), mLatency(0),
+    mFlags((AudioSystem::output_flags)0), mDevice(0), mOutput1(0), mOutput2(0)
+{
+    // clear usage count for all stream types
+    for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        mRefCount[i] = 0;
+        mCurVolume[i] = -1.0;
+        mMuteCount[i] = 0;
+    }
+}
+
+uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::device()
+{
+    uint32_t device = 0;
+    if (isDuplicated()) {
+        device = mOutput1->mDevice | mOutput2->mDevice;
+    } else {
+        device = mDevice;
+    }
+    return device;
+}
+
+void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta)
+{
+    // forward usage count change to attached outputs
+    if (isDuplicated()) {
+        mOutput1->changeRefCount(stream, delta);
+        mOutput2->changeRefCount(stream, delta);
+    }
+    if ((delta + (int)mRefCount[stream]) < 0) {
+        LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]);
+        mRefCount[stream] = 0;
+        return;
+    }
+    mRefCount[stream] += delta;
+    LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]);
+}
+
+uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::refCount()
+{
+    uint32_t refcount = 0;
+    for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+        refcount += mRefCount[i];
+    }
+    return refcount;
+}
+
+uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing_strategy strategy)
+{
+    uint32_t refCount = 0;
+    for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) {
+        if (getStrategy((AudioSystem::stream_type)i) == strategy) {
+            refCount += mRefCount[i];
+        }
+    }
+    return refCount;
+}
+
+
+status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", device());
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Stream volume refCount muteCount\n");
+    result.append(buffer);
+    for (int i = 0; i < AudioSystem::NUM_STREAM_TYPES; i++) {
+        snprintf(buffer, SIZE, " %02d     %.03f     %02d       %02d\n", i, mCurVolume[i], mRefCount[i], mMuteCount[i]);
+        result.append(buffer);
+    }
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+// --- AudioInputDescriptor class implementation
+
+AudioPolicyManagerBase::AudioInputDescriptor::AudioInputDescriptor()
+    : mSamplingRate(0), mFormat(0), mChannels(0),
+     mAcoustics((AudioSystem::audio_in_acoustics)0), mDevice(0), mRefCount(0)
+{
+}
+
+status_t AudioPolicyManagerBase::AudioInputDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Format: %d\n", mFormat);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Channels: %08x\n", mChannels);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Acoustics %08x\n", mAcoustics);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Ref Count %d\n", mRefCount);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+// --- StreamDescriptor class implementation
+
+void AudioPolicyManagerBase::StreamDescriptor::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "      %02d         %02d         %02d         %d\n",
+            mIndexMin,
+            mIndexMax,
+            mIndexCur,
+            mCanBeMuted);
+}
+
+// --- EffectDescriptor class implementation
+
+status_t AudioPolicyManagerBase::EffectDescriptor::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, " Output: %d\n", mOutput);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Strategy: %d\n", mStrategy);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Session: %d\n", mSession);
+    result.append(buffer);
+    snprintf(buffer, SIZE, " Name: %s\n",  mDesc.name);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    return NO_ERROR;
+}
+
+
+
+}; // namespace android
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
new file mode 100644
index 0000000..f24e08e
--- /dev/null
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -0,0 +1,1005 @@
+/*
+ * Copyright (C) 2009 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_TAG "AudioPolicyService"
+//#define LOG_NDEBUG 0
+
+#undef __STRICT_ANSI__
+#define __STDINT_LIMITS
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include <sys/time.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <cutils/properties.h>
+#include <binder/IPCThreadState.h>
+#include <utils/String16.h>
+#include <utils/threads.h>
+#include "AudioPolicyService.h"
+#include <hardware_legacy/AudioPolicyManagerBase.h>
+#include <cutils/properties.h>
+#include <dlfcn.h>
+#include <hardware_legacy/power.h>
+
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+namespace android {
+
+
+static const char *kDeadlockedString = "AudioPolicyService may be deadlocked\n";
+static const char *kCmdDeadlockedString = "AudioPolicyService command thread may be deadlocked\n";
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 20000;
+
+static bool checkPermission() {
+#ifndef HAVE_ANDROID_OS
+    return true;
+#endif
+    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
+    bool ok = checkCallingPermission(String16("android.permission.MODIFY_AUDIO_SETTINGS"));
+    if (!ok) LOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS");
+    return ok;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioPolicyService::AudioPolicyService()
+    : BnAudioPolicyService() , mpPolicyManager(NULL)
+{
+    char value[PROPERTY_VALUE_MAX];
+
+    // start tone playback thread
+    mTonePlaybackThread = new AudioCommandThread(String8(""));
+    // start audio commands thread
+    mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread"));
+
+#if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST)
+    mpPolicyManager = new AudioPolicyManagerBase(this);
+    LOGV("build for GENERIC_AUDIO - using generic audio policy");
+#else
+    // if running in emulation - use the emulator driver
+    if (property_get("ro.kernel.qemu", value, 0)) {
+        LOGV("Running in emulation - using generic audio policy");
+        mpPolicyManager = new AudioPolicyManagerBase(this);
+    }
+    else {
+        LOGV("Using hardware specific audio policy");
+        mpPolicyManager = createAudioPolicyManager(this);
+    }
+#endif
+
+    // load properties
+    property_get("ro.camera.sound.forced", value, "0");
+    mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value);
+}
+
+AudioPolicyService::~AudioPolicyService()
+{
+    mTonePlaybackThread->exit();
+    mTonePlaybackThread.clear();
+    mAudioCommandThread->exit();
+    mAudioCommandThread.clear();
+
+    if (mpPolicyManager) {
+        delete mpPolicyManager;
+    }
+}
+
+
+status_t AudioPolicyService::setDeviceConnectionState(AudioSystem::audio_devices device,
+                                                  AudioSystem::device_connection_state state,
+                                                  const char *device_address)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (!AudioSystem::isOutputDevice(device) && !AudioSystem::isInputDevice(device)) {
+        return BAD_VALUE;
+    }
+    if (state != AudioSystem::DEVICE_STATE_AVAILABLE &&
+            state != AudioSystem::DEVICE_STATE_UNAVAILABLE) {
+        return BAD_VALUE;
+    }
+
+    LOGV("setDeviceConnectionState() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->setDeviceConnectionState(device, state, device_address);
+}
+
+AudioSystem::device_connection_state AudioPolicyService::getDeviceConnectionState(
+                                                              AudioSystem::audio_devices device,
+                                                              const char *device_address)
+{
+    if (mpPolicyManager == NULL) {
+        return AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    }
+    if (!checkPermission()) {
+        return AudioSystem::DEVICE_STATE_UNAVAILABLE;
+    }
+    return mpPolicyManager->getDeviceConnectionState(device, device_address);
+}
+
+status_t AudioPolicyService::setPhoneState(int state)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (state < 0 || state >= AudioSystem::NUM_MODES) {
+        return BAD_VALUE;
+    }
+
+    LOGV("setPhoneState() tid %d", gettid());
+
+    // TODO: check if it is more appropriate to do it in platform specific policy manager
+    AudioSystem::setMode(state);
+
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->setPhoneState(state);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setRingerMode(uint32_t mode, uint32_t mask)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+
+    mpPolicyManager->setRingerMode(mode, mask);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setForceUse(AudioSystem::force_use usage,
+                                         AudioSystem::forced_config config)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
+        return BAD_VALUE;
+    }
+    if (config < 0 || config >= AudioSystem::NUM_FORCE_CONFIG) {
+        return BAD_VALUE;
+    }
+    LOGV("setForceUse() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->setForceUse(usage, config);
+    return NO_ERROR;
+}
+
+AudioSystem::forced_config AudioPolicyService::getForceUse(AudioSystem::force_use usage)
+{
+    if (mpPolicyManager == NULL) {
+        return AudioSystem::FORCE_NONE;
+    }
+    if (!checkPermission()) {
+        return AudioSystem::FORCE_NONE;
+    }
+    if (usage < 0 || usage >= AudioSystem::NUM_FORCE_USE) {
+        return AudioSystem::FORCE_NONE;
+    }
+    return mpPolicyManager->getForceUse(usage);
+}
+
+audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::output_flags flags)
+{
+    if (mpPolicyManager == NULL) {
+        return 0;
+    }
+    LOGV("getOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags);
+}
+
+status_t AudioPolicyService::startOutput(audio_io_handle_t output,
+                                         AudioSystem::stream_type stream,
+                                         int session)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    LOGV("startOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->startOutput(output, stream, session);
+}
+
+status_t AudioPolicyService::stopOutput(audio_io_handle_t output,
+                                        AudioSystem::stream_type stream,
+                                        int session)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    LOGV("stopOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->stopOutput(output, stream, session);
+}
+
+void AudioPolicyService::releaseOutput(audio_io_handle_t output)
+{
+    if (mpPolicyManager == NULL) {
+        return;
+    }
+    LOGV("releaseOutput() tid %d", gettid());
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->releaseOutput(output);
+}
+
+audio_io_handle_t AudioPolicyService::getInput(int inputSource,
+                                    uint32_t samplingRate,
+                                    uint32_t format,
+                                    uint32_t channels,
+                                    AudioSystem::audio_in_acoustics acoustics)
+{
+    if (mpPolicyManager == NULL) {
+        return 0;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->getInput(inputSource, samplingRate, format, channels, acoustics);
+}
+
+status_t AudioPolicyService::startInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->startInput(input);
+}
+
+status_t AudioPolicyService::stopInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->stopInput(input);
+}
+
+void AudioPolicyService::releaseInput(audio_io_handle_t input)
+{
+    if (mpPolicyManager == NULL) {
+        return;
+    }
+    Mutex::Autolock _l(mLock);
+    mpPolicyManager->releaseInput(input);
+}
+
+status_t AudioPolicyService::initStreamVolume(AudioSystem::stream_type stream,
+                                            int indexMin,
+                                            int indexMax)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+    mpPolicyManager->initStreamVolume(stream, indexMin, indexMax);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setStreamVolumeIndex(AudioSystem::stream_type stream, int index)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+
+    return mpPolicyManager->setStreamVolumeIndex(stream, index);
+}
+
+status_t AudioPolicyService::getStreamVolumeIndex(AudioSystem::stream_type stream, int *index)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    if (!checkPermission()) {
+        return PERMISSION_DENIED;
+    }
+    if (stream < 0 || stream >= AudioSystem::NUM_STREAM_TYPES) {
+        return BAD_VALUE;
+    }
+    return mpPolicyManager->getStreamVolumeIndex(stream, index);
+}
+
+uint32_t AudioPolicyService::getStrategyForStream(AudioSystem::stream_type stream)
+{
+    if (mpPolicyManager == NULL) {
+        return 0;
+    }
+    return mpPolicyManager->getStrategyForStream(stream);
+}
+
+audio_io_handle_t AudioPolicyService::getOutputForEffect(effect_descriptor_t *desc)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    Mutex::Autolock _l(mLock);
+    return mpPolicyManager->getOutputForEffect(desc);
+}
+
+status_t AudioPolicyService::registerEffect(effect_descriptor_t *desc,
+                                audio_io_handle_t output,
+                                uint32_t strategy,
+                                int session,
+                                int id)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    return mpPolicyManager->registerEffect(desc, output, strategy, session, id);
+}
+
+status_t AudioPolicyService::unregisterEffect(int id)
+{
+    if (mpPolicyManager == NULL) {
+        return NO_INIT;
+    }
+    return mpPolicyManager->unregisterEffect(id);
+}
+
+void AudioPolicyService::binderDied(const wp<IBinder>& who) {
+    LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
+            IPCThreadState::self()->getCallingPid());
+}
+
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
+status_t AudioPolicyService::dumpInternals(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "PolicyManager Interface: %p\n", mpPolicyManager);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Command Thread: %p\n", mAudioCommandThread.get());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "Tones Thread: %p\n", mTonePlaybackThread.get());
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::dump(int fd, const Vector<String16>& args)
+{
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        dumpPermissionDenial(fd);
+    } else {
+        bool locked = tryLock(mLock);
+        if (!locked) {
+            String8 result(kDeadlockedString);
+            write(fd, result.string(), result.size());
+        }
+
+        dumpInternals(fd);
+        if (mAudioCommandThread != NULL) {
+            mAudioCommandThread->dump(fd);
+        }
+        if (mTonePlaybackThread != NULL) {
+            mTonePlaybackThread->dump(fd);
+        }
+
+        if (mpPolicyManager) {
+            mpPolicyManager->dump(fd);
+        }
+
+        if (locked) mLock.unlock();
+    }
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::dumpPermissionDenial(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, SIZE, "Permission Denial: "
+            "can't dump AudioPolicyService from pid=%d, uid=%d\n",
+            IPCThreadState::self()->getCallingPid(),
+            IPCThreadState::self()->getCallingUid());
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    return BnAudioPolicyService::onTransact(code, data, reply, flags);
+}
+
+
+// ----------------------------------------------------------------------------
+void AudioPolicyService::instantiate() {
+    defaultServiceManager()->addService(
+            String16("media.audio_policy"), new AudioPolicyService());
+}
+
+
+// ----------------------------------------------------------------------------
+// AudioPolicyClientInterface implementation
+// ----------------------------------------------------------------------------
+
+
+audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t *pLatencyMs,
+                                AudioSystem::output_flags flags)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openOutput() could not get AudioFlinger");
+        return 0;
+    }
+
+    return af->openOutput(pDevices,
+                          pSamplingRate,
+                          (uint32_t *)pFormat,
+                          pChannels,
+                          pLatencyMs,
+                          flags);
+}
+
+audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1,
+                                                          audio_io_handle_t output2)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openDuplicateOutput() could not get AudioFlinger");
+        return 0;
+    }
+    return af->openDuplicateOutput(output1, output2);
+}
+
+status_t AudioPolicyService::closeOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->closeOutput(output);
+}
+
+
+status_t AudioPolicyService::suspendOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("suspendOutput() could not get AudioFlinger");
+        return PERMISSION_DENIED;
+    }
+
+    return af->suspendOutput(output);
+}
+
+status_t AudioPolicyService::restoreOutput(audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("restoreOutput() could not get AudioFlinger");
+        return PERMISSION_DENIED;
+    }
+
+    return af->restoreOutput(output);
+}
+
+audio_io_handle_t AudioPolicyService::openInput(uint32_t *pDevices,
+                                uint32_t *pSamplingRate,
+                                uint32_t *pFormat,
+                                uint32_t *pChannels,
+                                uint32_t acoustics)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        LOGW("openInput() could not get AudioFlinger");
+        return 0;
+    }
+
+    return af->openInput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, acoustics);
+}
+
+status_t AudioPolicyService::closeInput(audio_io_handle_t input)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->closeInput(input);
+}
+
+status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream,
+                                             float volume,
+                                             audio_io_handle_t output,
+                                             int delayMs)
+{
+    return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs);
+}
+
+status_t AudioPolicyService::setStreamOutput(AudioSystem::stream_type stream,
+                                             audio_io_handle_t output)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->setStreamOutput(stream, output);
+}
+
+status_t AudioPolicyService::moveEffects(int session, audio_io_handle_t srcOutput,
+                                               audio_io_handle_t dstOutput)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) return PERMISSION_DENIED;
+
+    return af->moveEffects(session, (int)srcOutput, (int)dstOutput);
+}
+
+void AudioPolicyService::setParameters(audio_io_handle_t ioHandle,
+                                       const String8& keyValuePairs,
+                                       int delayMs)
+{
+    mAudioCommandThread->parametersCommand((int)ioHandle, keyValuePairs, delayMs);
+}
+
+String8 AudioPolicyService::getParameters(audio_io_handle_t ioHandle, const String8& keys)
+{
+    String8 result = AudioSystem::getParameters(ioHandle, keys);
+    return result;
+}
+
+status_t AudioPolicyService::startTone(ToneGenerator::tone_type tone,
+                                       AudioSystem::stream_type stream)
+{
+    mTonePlaybackThread->startToneCommand(tone, stream);
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::stopTone()
+{
+    mTonePlaybackThread->stopToneCommand();
+    return NO_ERROR;
+}
+
+status_t AudioPolicyService::setVoiceVolume(float volume, int delayMs)
+{
+    return mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
+}
+
+// -----------  AudioPolicyService::AudioCommandThread implementation ----------
+
+AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name)
+    : Thread(false), mName(name)
+{
+    mpToneGenerator = NULL;
+}
+
+
+AudioPolicyService::AudioCommandThread::~AudioCommandThread()
+{
+    if (mName != "" && !mAudioCommands.isEmpty()) {
+        release_wake_lock(mName.string());
+    }
+    mAudioCommands.clear();
+    if (mpToneGenerator != NULL) delete mpToneGenerator;
+}
+
+void AudioPolicyService::AudioCommandThread::onFirstRef()
+{
+    if (mName != "") {
+        run(mName.string(), ANDROID_PRIORITY_AUDIO);
+    } else {
+        run("AudioCommandThread", ANDROID_PRIORITY_AUDIO);
+    }
+}
+
+bool AudioPolicyService::AudioCommandThread::threadLoop()
+{
+    nsecs_t waitTime = INT64_MAX;
+
+    mLock.lock();
+    while (!exitPending())
+    {
+        while(!mAudioCommands.isEmpty()) {
+            nsecs_t curTime = systemTime();
+            // commands are sorted by increasing time stamp: execute them from index 0 and up
+            if (mAudioCommands[0]->mTime <= curTime) {
+                AudioCommand *command = mAudioCommands[0];
+                mAudioCommands.removeAt(0);
+                mLastCommand = *command;
+
+                switch (command->mCommand) {
+                case START_TONE: {
+                    mLock.unlock();
+                    ToneData *data = (ToneData *)command->mParam;
+                    LOGV("AudioCommandThread() processing start tone %d on stream %d",
+                            data->mType, data->mStream);
+                    if (mpToneGenerator != NULL)
+                        delete mpToneGenerator;
+                    mpToneGenerator = new ToneGenerator(data->mStream, 1.0);
+                    mpToneGenerator->startTone(data->mType);
+                    delete data;
+                    mLock.lock();
+                    }break;
+                case STOP_TONE: {
+                    mLock.unlock();
+                    LOGV("AudioCommandThread() processing stop tone");
+                    if (mpToneGenerator != NULL) {
+                        mpToneGenerator->stopTone();
+                        delete mpToneGenerator;
+                        mpToneGenerator = NULL;
+                    }
+                    mLock.lock();
+                    }break;
+                case SET_VOLUME: {
+                    VolumeData *data = (VolumeData *)command->mParam;
+                    LOGV("AudioCommandThread() processing set volume stream %d, \
+                            volume %f, output %d", data->mStream, data->mVolume, data->mIO);
+                    command->mStatus = AudioSystem::setStreamVolume(data->mStream,
+                                                                    data->mVolume,
+                                                                    data->mIO);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
+                case SET_PARAMETERS: {
+                     ParametersData *data = (ParametersData *)command->mParam;
+                     LOGV("AudioCommandThread() processing set parameters string %s, io %d",
+                             data->mKeyValuePairs.string(), data->mIO);
+                     command->mStatus = AudioSystem::setParameters(data->mIO, data->mKeyValuePairs);
+                     if (command->mWaitStatus) {
+                         command->mCond.signal();
+                         mWaitWorkCV.wait(mLock);
+                     }
+                     delete data;
+                     }break;
+                case SET_VOICE_VOLUME: {
+                    VoiceVolumeData *data = (VoiceVolumeData *)command->mParam;
+                    LOGV("AudioCommandThread() processing set voice volume volume %f",
+                            data->mVolume);
+                    command->mStatus = AudioSystem::setVoiceVolume(data->mVolume);
+                    if (command->mWaitStatus) {
+                        command->mCond.signal();
+                        mWaitWorkCV.wait(mLock);
+                    }
+                    delete data;
+                    }break;
+                default:
+                    LOGW("AudioCommandThread() unknown command %d", command->mCommand);
+                }
+                delete command;
+                waitTime = INT64_MAX;
+            } else {
+                waitTime = mAudioCommands[0]->mTime - curTime;
+                break;
+            }
+        }
+        // release delayed commands wake lock
+        if (mName != "" && mAudioCommands.isEmpty()) {
+            release_wake_lock(mName.string());
+        }
+        LOGV("AudioCommandThread() going to sleep");
+        mWaitWorkCV.waitRelative(mLock, waitTime);
+        LOGV("AudioCommandThread() waking up");
+    }
+    mLock.unlock();
+    return false;
+}
+
+status_t AudioPolicyService::AudioCommandThread::dump(int fd)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "AudioCommandThread %p Dump\n", this);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+
+    bool locked = tryLock(mLock);
+    if (!locked) {
+        String8 result2(kCmdDeadlockedString);
+        write(fd, result2.string(), result2.size());
+    }
+
+    snprintf(buffer, SIZE, "- Commands:\n");
+    result = String8(buffer);
+    result.append("   Command Time        Wait pParam\n");
+    for (int i = 0; i < (int)mAudioCommands.size(); i++) {
+        mAudioCommands[i]->dump(buffer, SIZE);
+        result.append(buffer);
+    }
+    result.append("  Last Command\n");
+    mLastCommand.dump(buffer, SIZE);
+    result.append(buffer);
+
+    write(fd, result.string(), result.size());
+
+    if (locked) mLock.unlock();
+
+    return NO_ERROR;
+}
+
+void AudioPolicyService::AudioCommandThread::startToneCommand(int type, int stream)
+{
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = START_TONE;
+    ToneData *data = new ToneData();
+    data->mType = type;
+    data->mStream = stream;
+    command->mParam = (void *)data;
+    command->mWaitStatus = false;
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command);
+    LOGV("AudioCommandThread() adding tone start type %d, stream %d", type, stream);
+    mWaitWorkCV.signal();
+}
+
+void AudioPolicyService::AudioCommandThread::stopToneCommand()
+{
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = STOP_TONE;
+    command->mParam = NULL;
+    command->mWaitStatus = false;
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command);
+    LOGV("AudioCommandThread() adding tone stop");
+    mWaitWorkCV.signal();
+}
+
+status_t AudioPolicyService::AudioCommandThread::volumeCommand(int stream,
+                                                               float volume,
+                                                               int output,
+                                                               int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_VOLUME;
+    VolumeData *data = new VolumeData();
+    data->mStream = stream;
+    data->mVolume = volume;
+    data->mIO = output;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set volume stream %d, volume %f, output %d",
+            stream, volume, output);
+    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
+    return status;
+}
+
+status_t AudioPolicyService::AudioCommandThread::parametersCommand(int ioHandle,
+                                                                   const String8& keyValuePairs,
+                                                                   int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_PARAMETERS;
+    ParametersData *data = new ParametersData();
+    data->mIO = ioHandle;
+    data->mKeyValuePairs = keyValuePairs;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set parameter string %s, io %d ,delay %d",
+            keyValuePairs.string(), ioHandle, delayMs);
+    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
+    return status;
+}
+
+status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume, int delayMs)
+{
+    status_t status = NO_ERROR;
+
+    AudioCommand *command = new AudioCommand();
+    command->mCommand = SET_VOICE_VOLUME;
+    VoiceVolumeData *data = new VoiceVolumeData();
+    data->mVolume = volume;
+    command->mParam = data;
+    if (delayMs == 0) {
+        command->mWaitStatus = true;
+    } else {
+        command->mWaitStatus = false;
+    }
+    Mutex::Autolock _l(mLock);
+    insertCommand_l(command, delayMs);
+    LOGV("AudioCommandThread() adding set voice volume volume %f", volume);
+    mWaitWorkCV.signal();
+    if (command->mWaitStatus) {
+        command->mCond.wait(mLock);
+        status =  command->mStatus;
+        mWaitWorkCV.signal();
+    }
+    return status;
+}
+
+// insertCommand_l() must be called with mLock held
+void AudioPolicyService::AudioCommandThread::insertCommand_l(AudioCommand *command, int delayMs)
+{
+    ssize_t i;
+    Vector <AudioCommand *> removedCommands;
+
+    command->mTime = systemTime() + milliseconds(delayMs);
+
+    // acquire wake lock to make sure delayed commands are processed
+    if (mName != "" && mAudioCommands.isEmpty()) {
+        acquire_wake_lock(PARTIAL_WAKE_LOCK, mName.string());
+    }
+
+    // check same pending commands with later time stamps and eliminate them
+    for (i = mAudioCommands.size()-1; i >= 0; i--) {
+        AudioCommand *command2 = mAudioCommands[i];
+        // commands are sorted by increasing time stamp: no need to scan the rest of mAudioCommands
+        if (command2->mTime <= command->mTime) break;
+        if (command2->mCommand != command->mCommand) continue;
+
+        switch (command->mCommand) {
+        case SET_PARAMETERS: {
+            ParametersData *data = (ParametersData *)command->mParam;
+            ParametersData *data2 = (ParametersData *)command2->mParam;
+            if (data->mIO != data2->mIO) break;
+            LOGV("Comparing parameter command %s to new command %s",
+                    data2->mKeyValuePairs.string(), data->mKeyValuePairs.string());
+            AudioParameter param = AudioParameter(data->mKeyValuePairs);
+            AudioParameter param2 = AudioParameter(data2->mKeyValuePairs);
+            for (size_t j = 0; j < param.size(); j++) {
+               String8 key;
+               String8 value;
+               param.getAt(j, key, value);
+               for (size_t k = 0; k < param2.size(); k++) {
+                  String8 key2;
+                  String8 value2;
+                  param2.getAt(k, key2, value2);
+                  if (key2 == key) {
+                      param2.remove(key2);
+                      LOGV("Filtering out parameter %s", key2.string());
+                      break;
+                  }
+               }
+            }
+            // if all keys have been filtered out, remove the command.
+            // otherwise, update the key value pairs
+            if (param2.size() == 0) {
+                removedCommands.add(command2);
+            } else {
+                data2->mKeyValuePairs = param2.toString();
+            }
+        } break;
+
+        case SET_VOLUME: {
+            VolumeData *data = (VolumeData *)command->mParam;
+            VolumeData *data2 = (VolumeData *)command2->mParam;
+            if (data->mIO != data2->mIO) break;
+            if (data->mStream != data2->mStream) break;
+            LOGV("Filtering out volume command on output %d for stream %d",
+                    data->mIO, data->mStream);
+            removedCommands.add(command2);
+        } break;
+        case START_TONE:
+        case STOP_TONE:
+        default:
+            break;
+        }
+    }
+
+    // remove filtered commands
+    for (size_t j = 0; j < removedCommands.size(); j++) {
+        // removed commands always have time stamps greater than current command
+        for (size_t k = i + 1; k < mAudioCommands.size(); k++) {
+            if (mAudioCommands[k] == removedCommands[j]) {
+                LOGV("suppressing command: %d", mAudioCommands[k]->mCommand);
+                mAudioCommands.removeAt(k);
+                break;
+            }
+        }
+    }
+    removedCommands.clear();
+
+    // insert command at the right place according to its time stamp
+    LOGV("inserting command: %d at index %d, num commands %d",
+            command->mCommand, (int)i+1, mAudioCommands.size());
+    mAudioCommands.insertAt(command, i + 1);
+}
+
+void AudioPolicyService::AudioCommandThread::exit()
+{
+    LOGV("AudioCommandThread::exit");
+    {
+        AutoMutex _l(mLock);
+        requestExit();
+        mWaitWorkCV.signal();
+    }
+    requestExitAndWait();
+}
+
+void AudioPolicyService::AudioCommandThread::AudioCommand::dump(char* buffer, size_t size)
+{
+    snprintf(buffer, size, "   %02d      %06d.%03d  %01u    %p\n",
+            mCommand,
+            (int)ns2s(mTime),
+            (int)ns2ms(mTime)%1000,
+            mWaitStatus,
+            mParam);
+}
+
+}; // namespace android
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
new file mode 100644
index 0000000..558f455
--- /dev/null
+++ b/services/audioflinger/AudioPolicyService.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2009 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 ANDROID_AUDIOPOLICYSERVICE_H
+#define ANDROID_AUDIOPOLICYSERVICE_H
+
+#include <media/IAudioPolicyService.h>
+#include <hardware_legacy/AudioPolicyInterface.h>
+#include <media/ToneGenerator.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class String8;
+
+// ----------------------------------------------------------------------------
+
+class AudioPolicyService: public BnAudioPolicyService, public AudioPolicyClientInterface,
+    public IBinder::DeathRecipient
+{
+
+public:
+    static  void        instantiate();
+
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+
+    //
+    // BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
+    //
+
+    virtual status_t setDeviceConnectionState(AudioSystem::audio_devices device,
+                                              AudioSystem::device_connection_state state,
+                                              const char *device_address);
+    virtual AudioSystem::device_connection_state getDeviceConnectionState(
+                                                                AudioSystem::audio_devices device,
+                                                                const char *device_address);
+    virtual status_t setPhoneState(int state);
+    virtual status_t setRingerMode(uint32_t mode, uint32_t mask);
+    virtual status_t setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config);
+    virtual AudioSystem::forced_config getForceUse(AudioSystem::force_use usage);
+    virtual audio_io_handle_t getOutput(AudioSystem::stream_type stream,
+                                        uint32_t samplingRate = 0,
+                                        uint32_t format = AudioSystem::FORMAT_DEFAULT,
+                                        uint32_t channels = 0,
+                                        AudioSystem::output_flags flags =
+                                                AudioSystem::OUTPUT_FLAG_INDIRECT);
+    virtual status_t startOutput(audio_io_handle_t output,
+                                 AudioSystem::stream_type stream,
+                                 int session = 0);
+    virtual status_t stopOutput(audio_io_handle_t output,
+                                AudioSystem::stream_type stream,
+                                int session = 0);
+    virtual void releaseOutput(audio_io_handle_t output);
+    virtual audio_io_handle_t getInput(int inputSource,
+                                    uint32_t samplingRate = 0,
+                                    uint32_t format = AudioSystem::FORMAT_DEFAULT,
+                                    uint32_t channels = 0,
+                                    AudioSystem::audio_in_acoustics acoustics =
+                                            (AudioSystem::audio_in_acoustics)0);
+    virtual status_t startInput(audio_io_handle_t input);
+    virtual status_t stopInput(audio_io_handle_t input);
+    virtual void releaseInput(audio_io_handle_t input);
+    virtual status_t initStreamVolume(AudioSystem::stream_type stream,
+                                      int indexMin,
+                                      int indexMax);
+    virtual status_t setStreamVolumeIndex(AudioSystem::stream_type stream, int index);
+    virtual status_t getStreamVolumeIndex(AudioSystem::stream_type stream, int *index);
+
+    virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream);
+
+    virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
+    virtual status_t registerEffect(effect_descriptor_t *desc,
+                                    audio_io_handle_t output,
+                                    uint32_t strategy,
+                                    int session,
+                                    int id);
+    virtual status_t unregisterEffect(int id);
+
+    virtual     status_t    onTransact(
+                                uint32_t code,
+                                const Parcel& data,
+                                Parcel* reply,
+                                uint32_t flags);
+
+    // IBinder::DeathRecipient
+    virtual     void        binderDied(const wp<IBinder>& who);
+
+    //
+    // AudioPolicyClientInterface
+    //
+    virtual audio_io_handle_t openOutput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t *pLatencyMs,
+                                    AudioSystem::output_flags flags);
+    virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+                                                  audio_io_handle_t output2);
+    virtual status_t closeOutput(audio_io_handle_t output);
+    virtual status_t suspendOutput(audio_io_handle_t output);
+    virtual status_t restoreOutput(audio_io_handle_t output);
+    virtual audio_io_handle_t openInput(uint32_t *pDevices,
+                                    uint32_t *pSamplingRate,
+                                    uint32_t *pFormat,
+                                    uint32_t *pChannels,
+                                    uint32_t acoustics);
+    virtual status_t closeInput(audio_io_handle_t input);
+    virtual status_t setStreamVolume(AudioSystem::stream_type stream,
+                                     float volume,
+                                     audio_io_handle_t output,
+                                     int delayMs = 0);
+    virtual status_t setStreamOutput(AudioSystem::stream_type stream, audio_io_handle_t output);
+    virtual void setParameters(audio_io_handle_t ioHandle,
+                               const String8& keyValuePairs,
+                               int delayMs = 0);
+    virtual String8 getParameters(audio_io_handle_t ioHandle, const String8& keys);
+    virtual status_t startTone(ToneGenerator::tone_type tone, AudioSystem::stream_type stream);
+    virtual status_t stopTone();
+    virtual status_t setVoiceVolume(float volume, int delayMs = 0);
+    virtual status_t moveEffects(int session,
+                                     audio_io_handle_t srcOutput,
+                                     audio_io_handle_t dstOutput);
+
+private:
+                        AudioPolicyService();
+    virtual             ~AudioPolicyService();
+
+            status_t dumpInternals(int fd);
+
+    // Thread used for tone playback and to send audio config commands to audio flinger
+    // For tone playback, using a separate thread is necessary to avoid deadlock with mLock because startTone()
+    // and stopTone() are normally called with mLock locked and requesting a tone start or stop will cause
+    // calls to AudioPolicyService and an attempt to lock mLock.
+    // For audio config commands, it is necessary because audio flinger requires that the calling process (user)
+    // has permission to modify audio settings.
+    class AudioCommandThread : public Thread {
+        class AudioCommand;
+    public:
+
+        // commands for tone AudioCommand
+        enum {
+            START_TONE,
+            STOP_TONE,
+            SET_VOLUME,
+            SET_PARAMETERS,
+            SET_VOICE_VOLUME
+        };
+
+        AudioCommandThread (String8 name);
+        virtual             ~AudioCommandThread();
+
+                    status_t    dump(int fd);
+
+        // Thread virtuals
+        virtual     void        onFirstRef();
+        virtual     bool        threadLoop();
+
+                    void        exit();
+                    void        startToneCommand(int type = 0, int stream = 0);
+                    void        stopToneCommand();
+                    status_t    volumeCommand(int stream, float volume, int output, int delayMs = 0);
+                    status_t    parametersCommand(int ioHandle, const String8& keyValuePairs, int delayMs = 0);
+                    status_t    voiceVolumeCommand(float volume, int delayMs = 0);
+                    void        insertCommand_l(AudioCommand *command, int delayMs = 0);
+
+    private:
+        // descriptor for requested tone playback event
+        class AudioCommand {
+
+        public:
+            AudioCommand()
+            : mCommand(-1) {}
+
+            void dump(char* buffer, size_t size);
+
+            int mCommand;   // START_TONE, STOP_TONE ...
+            nsecs_t mTime;  // time stamp
+            Condition mCond; // condition for status return
+            status_t mStatus; // command status
+            bool mWaitStatus; // true if caller is waiting for status
+            void *mParam;     // command parameter (ToneData, VolumeData, ParametersData)
+        };
+
+        class ToneData {
+        public:
+            int mType;      // tone type (START_TONE only)
+            int mStream;    // stream type (START_TONE only)
+        };
+
+        class VolumeData {
+        public:
+            int mStream;
+            float mVolume;
+            int mIO;
+        };
+
+        class ParametersData {
+        public:
+            int mIO;
+            String8 mKeyValuePairs;
+        };
+
+        class VoiceVolumeData {
+        public:
+            float mVolume;
+        };
+
+        Mutex   mLock;
+        Condition mWaitWorkCV;
+        Vector <AudioCommand *> mAudioCommands; // list of pending commands
+        ToneGenerator *mpToneGenerator;     // the tone generator
+        AudioCommand mLastCommand;          // last processed command (used by dump)
+        String8 mName;                      // string used by wake lock fo delayed commands
+    };
+
+    // Internal dump utilities.
+    status_t dumpPermissionDenial(int fd);
+
+
+    Mutex   mLock;      // prevents concurrent access to AudioPolicy manager functions changing device
+                        // connection stated our routing
+    AudioPolicyInterface* mpPolicyManager;          // the platform specific policy manager
+    sp <AudioCommandThread> mAudioCommandThread;    // audio commands thread
+    sp <AudioCommandThread> mTonePlaybackThread;     // tone playback thread
+};
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOPOLICYSERVICE_H
+
+
+
+
+
+
+
+
diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
new file mode 100644
index 0000000..5dabacb
--- /dev/null
+++ b/services/audioflinger/AudioResampler.cpp
@@ -0,0 +1,595 @@
+/*
+ * Copyright (C) 2007 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_TAG "AudioResampler"
+//#define LOG_NDEBUG 0
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include "AudioResampler.h"
+#include "AudioResamplerSinc.h"
+#include "AudioResamplerCubic.h"
+
+namespace android {
+
+#ifdef __ARM_ARCH_5E__  // optimized asm option
+    #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
+#endif // __ARM_ARCH_5E__
+// ----------------------------------------------------------------------------
+
+class AudioResamplerOrder1 : public AudioResampler {
+public:
+    AudioResamplerOrder1(int bitDepth, int inChannelCount, int32_t sampleRate) :
+        AudioResampler(bitDepth, inChannelCount, sampleRate), mX0L(0), mX0R(0) {
+    }
+    virtual void resample(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider);
+private:
+    // number of bits used in interpolation multiply - 15 bits avoids overflow
+    static const int kNumInterpBits = 15;
+
+    // bits to shift the phase fraction down to avoid overflow
+    static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
+
+    void init() {}
+    void resampleMono16(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider);
+    void resampleStereo16(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider);
+#ifdef ASM_ARM_RESAMP1  // asm optimisation for ResamplerOrder1
+    void AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
+            size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
+            uint32_t &phaseFraction, uint32_t phaseIncrement);
+    void AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
+            size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
+            uint32_t &phaseFraction, uint32_t phaseIncrement);
+#endif  // ASM_ARM_RESAMP1
+
+    static inline int32_t Interp(int32_t x0, int32_t x1, uint32_t f) {
+        return x0 + (((x1 - x0) * (int32_t)(f >> kPreInterpShift)) >> kNumInterpBits);
+    }
+    static inline void Advance(size_t* index, uint32_t* frac, uint32_t inc) {
+        *frac += inc;
+        *index += (size_t)(*frac >> kNumPhaseBits);
+        *frac &= kPhaseMask;
+    }
+    int mX0L;
+    int mX0R;
+};
+
+// ----------------------------------------------------------------------------
+AudioResampler* AudioResampler::create(int bitDepth, int inChannelCount,
+        int32_t sampleRate, int quality) {
+
+    // can only create low quality resample now
+    AudioResampler* resampler;
+
+    char value[PROPERTY_VALUE_MAX];
+    if (property_get("af.resampler.quality", value, 0)) {
+        quality = atoi(value);
+        LOGD("forcing AudioResampler quality to %d", quality);
+    }
+
+    if (quality == DEFAULT)
+        quality = LOW_QUALITY;
+
+    switch (quality) {
+    default:
+    case LOW_QUALITY:
+        LOGV("Create linear Resampler");
+        resampler = new AudioResamplerOrder1(bitDepth, inChannelCount, sampleRate);
+        break;
+    case MED_QUALITY:
+        LOGV("Create cubic Resampler");
+        resampler = new AudioResamplerCubic(bitDepth, inChannelCount, sampleRate);
+        break;
+    case HIGH_QUALITY:
+        LOGV("Create sinc Resampler");
+        resampler = new AudioResamplerSinc(bitDepth, inChannelCount, sampleRate);
+        break;
+    }
+
+    // initialize resampler
+    resampler->init();
+    return resampler;
+}
+
+AudioResampler::AudioResampler(int bitDepth, int inChannelCount,
+        int32_t sampleRate) :
+    mBitDepth(bitDepth), mChannelCount(inChannelCount),
+            mSampleRate(sampleRate), mInSampleRate(sampleRate), mInputIndex(0),
+            mPhaseFraction(0) {
+    // sanity check on format
+    if ((bitDepth != 16) ||(inChannelCount < 1) || (inChannelCount > 2)) {
+        LOGE("Unsupported sample format, %d bits, %d channels", bitDepth,
+                inChannelCount);
+        // LOG_ASSERT(0);
+    }
+
+    // initialize common members
+    mVolume[0] = mVolume[1] = 0;
+    mBuffer.frameCount = 0;
+
+    // save format for quick lookup
+    if (inChannelCount == 1) {
+        mFormat = MONO_16_BIT;
+    } else {
+        mFormat = STEREO_16_BIT;
+    }
+}
+
+AudioResampler::~AudioResampler() {
+}
+
+void AudioResampler::setSampleRate(int32_t inSampleRate) {
+    mInSampleRate = inSampleRate;
+    mPhaseIncrement = (uint32_t)((kPhaseMultiplier * inSampleRate) / mSampleRate);
+}
+
+void AudioResampler::setVolume(int16_t left, int16_t right) {
+    // TODO: Implement anti-zipper filter
+    mVolume[0] = left;
+    mVolume[1] = right;
+}
+
+// ----------------------------------------------------------------------------
+
+void AudioResamplerOrder1::resample(int32_t* out, size_t outFrameCount,
+        AudioBufferProvider* provider) {
+
+    // should never happen, but we overflow if it does
+    // LOG_ASSERT(outFrameCount < 32767);
+
+    // select the appropriate resampler
+    switch (mChannelCount) {
+    case 1:
+        resampleMono16(out, outFrameCount, provider);
+        break;
+    case 2:
+        resampleStereo16(out, outFrameCount, provider);
+        break;
+    }
+}
+
+void AudioResamplerOrder1::resampleStereo16(int32_t* out, size_t outFrameCount,
+        AudioBufferProvider* provider) {
+
+    int32_t vl = mVolume[0];
+    int32_t vr = mVolume[1];
+
+    size_t inputIndex = mInputIndex;
+    uint32_t phaseFraction = mPhaseFraction;
+    uint32_t phaseIncrement = mPhaseIncrement;
+    size_t outputIndex = 0;
+    size_t outputSampleCount = outFrameCount * 2;
+    size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+    // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n",
+    //      outFrameCount, inputIndex, phaseFraction, phaseIncrement);
+
+    while (outputIndex < outputSampleCount) {
+
+        // buffer is empty, fetch a new one
+        while (mBuffer.frameCount == 0) {
+            mBuffer.frameCount = inFrameCount;
+            provider->getNextBuffer(&mBuffer);
+            if (mBuffer.raw == NULL) {
+                goto resampleStereo16_exit;
+            }
+
+            // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount);
+            if (mBuffer.frameCount > inputIndex) break;
+
+            inputIndex -= mBuffer.frameCount;
+            mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
+            mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
+            provider->releaseBuffer(&mBuffer);
+             // mBuffer.frameCount == 0 now so we reload a new buffer
+        }
+
+        int16_t *in = mBuffer.i16;
+
+        // handle boundary case
+        while (inputIndex == 0) {
+            // LOGE("boundary case\n");
+            out[outputIndex++] += vl * Interp(mX0L, in[0], phaseFraction);
+            out[outputIndex++] += vr * Interp(mX0R, in[1], phaseFraction);
+            Advance(&inputIndex, &phaseFraction, phaseIncrement);
+            if (outputIndex == outputSampleCount)
+                break;
+        }
+
+        // process input samples
+        // LOGE("general case\n");
+
+#ifdef ASM_ARM_RESAMP1  // asm optimisation for ResamplerOrder1
+        if (inputIndex + 2 < mBuffer.frameCount) {
+            int32_t* maxOutPt;
+            int32_t maxInIdx;
+
+            maxOutPt = out + (outputSampleCount - 2);   // 2 because 2 frames per loop
+            maxInIdx = mBuffer.frameCount - 2;
+            AsmStereo16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
+                    phaseFraction, phaseIncrement);
+        }
+#endif  // ASM_ARM_RESAMP1
+
+        while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
+            out[outputIndex++] += vl * Interp(in[inputIndex*2-2],
+                    in[inputIndex*2], phaseFraction);
+            out[outputIndex++] += vr * Interp(in[inputIndex*2-1],
+                    in[inputIndex*2+1], phaseFraction);
+            Advance(&inputIndex, &phaseFraction, phaseIncrement);
+        }
+
+        // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
+
+        // if done with buffer, save samples
+        if (inputIndex >= mBuffer.frameCount) {
+            inputIndex -= mBuffer.frameCount;
+
+            // LOGE("buffer done, new input index %d", inputIndex);
+
+            mX0L = mBuffer.i16[mBuffer.frameCount*2-2];
+            mX0R = mBuffer.i16[mBuffer.frameCount*2-1];
+            provider->releaseBuffer(&mBuffer);
+
+            // verify that the releaseBuffer resets the buffer frameCount
+            // LOG_ASSERT(mBuffer.frameCount == 0);
+        }
+    }
+
+    // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
+
+resampleStereo16_exit:
+    // save state
+    mInputIndex = inputIndex;
+    mPhaseFraction = phaseFraction;
+}
+
+void AudioResamplerOrder1::resampleMono16(int32_t* out, size_t outFrameCount,
+        AudioBufferProvider* provider) {
+
+    int32_t vl = mVolume[0];
+    int32_t vr = mVolume[1];
+
+    size_t inputIndex = mInputIndex;
+    uint32_t phaseFraction = mPhaseFraction;
+    uint32_t phaseIncrement = mPhaseIncrement;
+    size_t outputIndex = 0;
+    size_t outputSampleCount = outFrameCount * 2;
+    size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+    // LOGE("starting resample %d frames, inputIndex=%d, phaseFraction=%d, phaseIncrement=%d\n",
+    //      outFrameCount, inputIndex, phaseFraction, phaseIncrement);
+    while (outputIndex < outputSampleCount) {
+        // buffer is empty, fetch a new one
+        while (mBuffer.frameCount == 0) {
+            mBuffer.frameCount = inFrameCount;
+            provider->getNextBuffer(&mBuffer);
+            if (mBuffer.raw == NULL) {
+                mInputIndex = inputIndex;
+                mPhaseFraction = phaseFraction;
+                goto resampleMono16_exit;
+            }
+            // LOGE("New buffer fetched: %d frames\n", mBuffer.frameCount);
+            if (mBuffer.frameCount >  inputIndex) break;
+
+            inputIndex -= mBuffer.frameCount;
+            mX0L = mBuffer.i16[mBuffer.frameCount-1];
+            provider->releaseBuffer(&mBuffer);
+            // mBuffer.frameCount == 0 now so we reload a new buffer
+        }
+        int16_t *in = mBuffer.i16;
+
+        // handle boundary case
+        while (inputIndex == 0) {
+            // LOGE("boundary case\n");
+            int32_t sample = Interp(mX0L, in[0], phaseFraction);
+            out[outputIndex++] += vl * sample;
+            out[outputIndex++] += vr * sample;
+            Advance(&inputIndex, &phaseFraction, phaseIncrement);
+            if (outputIndex == outputSampleCount)
+                break;
+        }
+
+        // process input samples
+        // LOGE("general case\n");
+
+#ifdef ASM_ARM_RESAMP1  // asm optimisation for ResamplerOrder1
+        if (inputIndex + 2 < mBuffer.frameCount) {
+            int32_t* maxOutPt;
+            int32_t maxInIdx;
+
+            maxOutPt = out + (outputSampleCount - 2);
+            maxInIdx = (int32_t)mBuffer.frameCount - 2;
+                AsmMono16Loop(in, maxOutPt, maxInIdx, outputIndex, out, inputIndex, vl, vr,
+                        phaseFraction, phaseIncrement);
+        }
+#endif  // ASM_ARM_RESAMP1
+
+        while (outputIndex < outputSampleCount && inputIndex < mBuffer.frameCount) {
+            int32_t sample = Interp(in[inputIndex-1], in[inputIndex],
+                    phaseFraction);
+            out[outputIndex++] += vl * sample;
+            out[outputIndex++] += vr * sample;
+            Advance(&inputIndex, &phaseFraction, phaseIncrement);
+        }
+
+
+        // LOGE("loop done - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
+
+        // if done with buffer, save samples
+        if (inputIndex >= mBuffer.frameCount) {
+            inputIndex -= mBuffer.frameCount;
+
+            // LOGE("buffer done, new input index %d", inputIndex);
+
+            mX0L = mBuffer.i16[mBuffer.frameCount-1];
+            provider->releaseBuffer(&mBuffer);
+
+            // verify that the releaseBuffer resets the buffer frameCount
+            // LOG_ASSERT(mBuffer.frameCount == 0);
+        }
+    }
+
+    // LOGE("output buffer full - outputIndex=%d, inputIndex=%d\n", outputIndex, inputIndex);
+
+resampleMono16_exit:
+    // save state
+    mInputIndex = inputIndex;
+    mPhaseFraction = phaseFraction;
+}
+
+#ifdef ASM_ARM_RESAMP1  // asm optimisation for ResamplerOrder1
+
+/*******************************************************************
+*
+*   AsmMono16Loop
+*   asm optimized monotonic loop version; one loop is 2 frames
+*   Input:
+*       in : pointer on input samples
+*       maxOutPt : pointer on first not filled
+*       maxInIdx : index on first not used
+*       outputIndex : pointer on current output index
+*       out : pointer on output buffer
+*       inputIndex : pointer on current input index
+*       vl, vr : left and right gain
+*       phaseFraction : pointer on current phase fraction
+*       phaseIncrement
+*   Ouput:
+*       outputIndex :
+*       out : updated buffer
+*       inputIndex : index of next to use
+*       phaseFraction : phase fraction for next interpolation
+*
+*******************************************************************/
+void AudioResamplerOrder1::AsmMono16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
+            size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
+            uint32_t &phaseFraction, uint32_t phaseIncrement)
+{
+#define MO_PARAM5   "36"        // offset of parameter 5 (outputIndex)
+
+    asm(
+        "stmfd  sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
+        // get parameters
+        "   ldr r6, [sp, #" MO_PARAM5 " + 20]\n"    // &phaseFraction
+        "   ldr r6, [r6]\n"                         // phaseFraction
+        "   ldr r7, [sp, #" MO_PARAM5 " + 8]\n"     // &inputIndex
+        "   ldr r7, [r7]\n"                         // inputIndex
+        "   ldr r8, [sp, #" MO_PARAM5 " + 4]\n"     // out
+        "   ldr r0, [sp, #" MO_PARAM5 " + 0]\n"     // &outputIndex
+        "   ldr r0, [r0]\n"                         // outputIndex
+        "   add r8, r0, asl #2\n"                   // curOut
+        "   ldr r9, [sp, #" MO_PARAM5 " + 24]\n"    // phaseIncrement
+        "   ldr r10, [sp, #" MO_PARAM5 " + 12]\n"   // vl
+        "   ldr r11, [sp, #" MO_PARAM5 " + 16]\n"   // vr
+
+        // r0 pin, x0, Samp
+
+        // r1 in
+        // r2 maxOutPt
+        // r3 maxInIdx
+
+        // r4 x1, i1, i3, Out1
+        // r5 out0
+
+        // r6 frac
+        // r7 inputIndex
+        // r8 curOut
+
+        // r9 inc
+        // r10 vl
+        // r11 vr
+
+        // r12
+        // r13 sp
+        // r14
+
+        // the following loop works on 2 frames
+
+        ".Y4L01:\n"
+        "   cmp r8, r2\n"                   // curOut - maxCurOut
+        "   bcs .Y4L02\n"
+
+#define MO_ONE_FRAME \
+    "   add r0, r1, r7, asl #1\n"       /* in + inputIndex */\
+    "   ldrsh r4, [r0]\n"               /* in[inputIndex] */\
+    "   ldr r5, [r8]\n"                 /* out[outputIndex] */\
+    "   ldrsh r0, [r0, #-2]\n"          /* in[inputIndex-1] */\
+    "   bic r6, r6, #0xC0000000\n"      /* phaseFraction & ... */\
+    "   sub r4, r4, r0\n"               /* in[inputIndex] - in[inputIndex-1] */\
+    "   mov r4, r4, lsl #2\n"           /* <<2 */\
+    "   smulwt r4, r4, r6\n"            /* (x1-x0)*.. */\
+    "   add r6, r6, r9\n"               /* phaseFraction + phaseIncrement */\
+    "   add r0, r0, r4\n"               /* x0 - (..) */\
+    "   mla r5, r0, r10, r5\n"          /* vl*interp + out[] */\
+    "   ldr r4, [r8, #4]\n"             /* out[outputIndex+1] */\
+    "   str r5, [r8], #4\n"             /* out[outputIndex++] = ... */\
+    "   mla r4, r0, r11, r4\n"          /* vr*interp + out[] */\
+    "   add r7, r7, r6, lsr #30\n"      /* inputIndex + phaseFraction>>30 */\
+    "   str r4, [r8], #4\n"             /* out[outputIndex++] = ... */
+
+        MO_ONE_FRAME    // frame 1
+        MO_ONE_FRAME    // frame 2
+
+        "   cmp r7, r3\n"                   // inputIndex - maxInIdx
+        "   bcc .Y4L01\n"
+        ".Y4L02:\n"
+
+        "   bic r6, r6, #0xC0000000\n"             // phaseFraction & ...
+        // save modified values
+        "   ldr r0, [sp, #" MO_PARAM5 " + 20]\n"    // &phaseFraction
+        "   str r6, [r0]\n"                         // phaseFraction
+        "   ldr r0, [sp, #" MO_PARAM5 " + 8]\n"     // &inputIndex
+        "   str r7, [r0]\n"                         // inputIndex
+        "   ldr r0, [sp, #" MO_PARAM5 " + 4]\n"     // out
+        "   sub r8, r0\n"                           // curOut - out
+        "   asr r8, #2\n"                           // new outputIndex
+        "   ldr r0, [sp, #" MO_PARAM5 " + 0]\n"     // &outputIndex
+        "   str r8, [r0]\n"                         // save outputIndex
+
+        "   ldmfd   sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}\n"
+    );
+}
+
+/*******************************************************************
+*
+*   AsmStereo16Loop
+*   asm optimized stereo loop version; one loop is 2 frames
+*   Input:
+*       in : pointer on input samples
+*       maxOutPt : pointer on first not filled
+*       maxInIdx : index on first not used
+*       outputIndex : pointer on current output index
+*       out : pointer on output buffer
+*       inputIndex : pointer on current input index
+*       vl, vr : left and right gain
+*       phaseFraction : pointer on current phase fraction
+*       phaseIncrement
+*   Ouput:
+*       outputIndex :
+*       out : updated buffer
+*       inputIndex : index of next to use
+*       phaseFraction : phase fraction for next interpolation
+*
+*******************************************************************/
+void AudioResamplerOrder1::AsmStereo16Loop(int16_t *in, int32_t* maxOutPt, int32_t maxInIdx,
+            size_t &outputIndex, int32_t* out, size_t &inputIndex, int32_t vl, int32_t vr,
+            uint32_t &phaseFraction, uint32_t phaseIncrement)
+{
+#define ST_PARAM5    "40"     // offset of parameter 5 (outputIndex)
+    asm(
+        "stmfd  sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}\n"
+        // get parameters
+        "   ldr r6, [sp, #" ST_PARAM5 " + 20]\n"    // &phaseFraction
+        "   ldr r6, [r6]\n"                         // phaseFraction
+        "   ldr r7, [sp, #" ST_PARAM5 " + 8]\n"     // &inputIndex
+        "   ldr r7, [r7]\n"                         // inputIndex
+        "   ldr r8, [sp, #" ST_PARAM5 " + 4]\n"     // out
+        "   ldr r0, [sp, #" ST_PARAM5 " + 0]\n"     // &outputIndex
+        "   ldr r0, [r0]\n"                         // outputIndex
+        "   add r8, r0, asl #2\n"                   // curOut
+        "   ldr r9, [sp, #" ST_PARAM5 " + 24]\n"    // phaseIncrement
+        "   ldr r10, [sp, #" ST_PARAM5 " + 12]\n"   // vl
+        "   ldr r11, [sp, #" ST_PARAM5 " + 16]\n"   // vr
+
+        // r0 pin, x0, Samp
+
+        // r1 in
+        // r2 maxOutPt
+        // r3 maxInIdx
+
+        // r4 x1, i1, i3, out1
+        // r5 out0
+
+        // r6 frac
+        // r7 inputIndex
+        // r8 curOut
+
+        // r9 inc
+        // r10 vl
+        // r11 vr
+
+        // r12 temporary
+        // r13 sp
+        // r14
+
+        ".Y5L01:\n"
+        "   cmp r8, r2\n"                   // curOut - maxCurOut
+        "   bcs .Y5L02\n"
+
+#define ST_ONE_FRAME \
+    "   bic r6, r6, #0xC0000000\n"      /* phaseFraction & ... */\
+\
+    "   add r0, r1, r7, asl #2\n"       /* in + 2*inputIndex */\
+\
+    "   ldrsh r4, [r0]\n"               /* in[2*inputIndex] */\
+    "   ldr r5, [r8]\n"                 /* out[outputIndex] */\
+    "   ldrsh r12, [r0, #-4]\n"         /* in[2*inputIndex-2] */\
+    "   sub r4, r4, r12\n"              /* in[2*InputIndex] - in[2*InputIndex-2] */\
+    "   mov r4, r4, lsl #2\n"           /* <<2 */\
+    "   smulwt r4, r4, r6\n"            /* (x1-x0)*.. */\
+    "   add r12, r12, r4\n"             /* x0 - (..) */\
+    "   mla r5, r12, r10, r5\n"         /* vl*interp + out[] */\
+    "   ldr r4, [r8, #4]\n"             /* out[outputIndex+1] */\
+    "   str r5, [r8], #4\n"             /* out[outputIndex++] = ... */\
+\
+    "   ldrsh r12, [r0, #+2]\n"         /* in[2*inputIndex+1] */\
+    "   ldrsh r0, [r0, #-2]\n"          /* in[2*inputIndex-1] */\
+    "   sub r12, r12, r0\n"             /* in[2*InputIndex] - in[2*InputIndex-2] */\
+    "   mov r12, r12, lsl #2\n"         /* <<2 */\
+    "   smulwt r12, r12, r6\n"          /* (x1-x0)*.. */\
+    "   add r12, r0, r12\n"             /* x0 - (..) */\
+    "   mla r4, r12, r11, r4\n"         /* vr*interp + out[] */\
+    "   str r4, [r8], #4\n"             /* out[outputIndex++] = ... */\
+\
+    "   add r6, r6, r9\n"               /* phaseFraction + phaseIncrement */\
+    "   add r7, r7, r6, lsr #30\n"      /* inputIndex + phaseFraction>>30 */
+
+    ST_ONE_FRAME    // frame 1
+    ST_ONE_FRAME    // frame 1
+
+        "   cmp r7, r3\n"                       // inputIndex - maxInIdx
+        "   bcc .Y5L01\n"
+        ".Y5L02:\n"
+
+        "   bic r6, r6, #0xC0000000\n"              // phaseFraction & ...
+        // save modified values
+        "   ldr r0, [sp, #" ST_PARAM5 " + 20]\n"    // &phaseFraction
+        "   str r6, [r0]\n"                         // phaseFraction
+        "   ldr r0, [sp, #" ST_PARAM5 " + 8]\n"     // &inputIndex
+        "   str r7, [r0]\n"                         // inputIndex
+        "   ldr r0, [sp, #" ST_PARAM5 " + 4]\n"     // out
+        "   sub r8, r0\n"                           // curOut - out
+        "   asr r8, #2\n"                           // new outputIndex
+        "   ldr r0, [sp, #" ST_PARAM5 " + 0]\n"     // &outputIndex
+        "   str r8, [r0]\n"                         // save outputIndex
+
+        "   ldmfd   sp!, {r4, r5, r6, r7, r8, r9, r10, r11, r12, pc}\n"
+    );
+}
+
+#endif  // ASM_ARM_RESAMP1
+
+
+// ----------------------------------------------------------------------------
+}
+; // namespace android
+
diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
new file mode 100644
index 0000000..2dfac76
--- /dev/null
+++ b/services/audioflinger/AudioResampler.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2007 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 ANDROID_AUDIO_RESAMPLER_H
+#define ANDROID_AUDIO_RESAMPLER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "AudioBufferProvider.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioResampler {
+public:
+    // Determines quality of SRC.
+    //  LOW_QUALITY: linear interpolator (1st order)
+    //  MED_QUALITY: cubic interpolator (3rd order)
+    //  HIGH_QUALITY: fixed multi-tap FIR (e.g. 48KHz->44.1KHz)
+    // NOTE: high quality SRC will only be supported for
+    // certain fixed rate conversions. Sample rate cannot be
+    // changed dynamically. 
+    enum src_quality {
+        DEFAULT=0,
+        LOW_QUALITY=1,
+        MED_QUALITY=2,
+        HIGH_QUALITY=3
+    };
+
+    static AudioResampler* create(int bitDepth, int inChannelCount,
+            int32_t sampleRate, int quality=DEFAULT);
+
+    virtual ~AudioResampler();
+
+    virtual void init() = 0;
+    virtual void setSampleRate(int32_t inSampleRate);
+    virtual void setVolume(int16_t left, int16_t right);
+
+    virtual void resample(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider) = 0;
+
+protected:
+    // number of bits for phase fraction - 30 bits allows nearly 2x downsampling
+    static const int kNumPhaseBits = 30;
+
+    // phase mask for fraction
+    static const uint32_t kPhaseMask = (1LU<<kNumPhaseBits)-1;
+
+    // multiplier to calculate fixed point phase increment
+    static const double kPhaseMultiplier = 1L << kNumPhaseBits;
+
+    enum format {MONO_16_BIT, STEREO_16_BIT};
+    AudioResampler(int bitDepth, int inChannelCount, int32_t sampleRate);
+
+    // prevent copying
+    AudioResampler(const AudioResampler&);
+    AudioResampler& operator=(const AudioResampler&);
+
+    int32_t mBitDepth;
+    int32_t mChannelCount;
+    int32_t mSampleRate;
+    int32_t mInSampleRate;
+    AudioBufferProvider::Buffer mBuffer;
+    union {
+        int16_t mVolume[2];
+        uint32_t mVolumeRL;
+    };
+    int16_t mTargetVolume[2];
+    format mFormat;
+    size_t mInputIndex;
+    int32_t mPhaseIncrement;
+    uint32_t mPhaseFraction;
+};
+
+// ----------------------------------------------------------------------------
+}
+; // namespace android
+
+#endif // ANDROID_AUDIO_RESAMPLER_H
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
new file mode 100644
index 0000000..1d247bd
--- /dev/null
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+
+#include "AudioResampler.h"
+#include "AudioResamplerCubic.h"
+
+#define LOG_TAG "AudioSRC"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+void AudioResamplerCubic::init() {
+    memset(&left, 0, sizeof(state));
+    memset(&right, 0, sizeof(state));
+}
+
+void AudioResamplerCubic::resample(int32_t* out, size_t outFrameCount,
+        AudioBufferProvider* provider) {
+
+    // should never happen, but we overflow if it does
+    // LOG_ASSERT(outFrameCount < 32767);
+
+    // select the appropriate resampler
+    switch (mChannelCount) {
+    case 1:
+        resampleMono16(out, outFrameCount, provider);
+        break;
+    case 2:
+        resampleStereo16(out, outFrameCount, provider);
+        break;
+    }
+}
+
+void AudioResamplerCubic::resampleStereo16(int32_t* out, size_t outFrameCount,
+        AudioBufferProvider* provider) {
+
+    int32_t vl = mVolume[0];
+    int32_t vr = mVolume[1];
+
+    size_t inputIndex = mInputIndex;
+    uint32_t phaseFraction = mPhaseFraction;
+    uint32_t phaseIncrement = mPhaseIncrement;
+    size_t outputIndex = 0;
+    size_t outputSampleCount = outFrameCount * 2;
+    size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+    // fetch first buffer
+    if (mBuffer.frameCount == 0) {
+        mBuffer.frameCount = inFrameCount;
+        provider->getNextBuffer(&mBuffer);
+        if (mBuffer.raw == NULL)
+            return;
+        // LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
+    }
+    int16_t *in = mBuffer.i16;
+
+    while (outputIndex < outputSampleCount) {
+        int32_t sample;
+        int32_t x;
+
+        // calculate output sample
+        x = phaseFraction >> kPreInterpShift;
+        out[outputIndex++] += vl * interp(&left, x);
+        out[outputIndex++] += vr * interp(&right, x);
+        // out[outputIndex++] += vr * in[inputIndex*2];
+
+        // increment phase
+        phaseFraction += phaseIncrement;
+        uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
+        phaseFraction &= kPhaseMask;
+
+        // time to fetch another sample
+        while (indexIncrement--) {
+
+            inputIndex++;
+            if (inputIndex == mBuffer.frameCount) {
+                inputIndex = 0;
+                provider->releaseBuffer(&mBuffer);
+                mBuffer.frameCount = inFrameCount;
+                provider->getNextBuffer(&mBuffer);
+                if (mBuffer.raw == NULL)
+                    goto save_state;  // ugly, but efficient
+                in = mBuffer.i16;
+                // LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount);
+            }
+
+            // advance sample state
+            advance(&left, in[inputIndex*2]);
+            advance(&right, in[inputIndex*2+1]);
+        }
+    }
+
+save_state:
+    // LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
+    mInputIndex = inputIndex;
+    mPhaseFraction = phaseFraction;
+}
+
+void AudioResamplerCubic::resampleMono16(int32_t* out, size_t outFrameCount,
+        AudioBufferProvider* provider) {
+
+    int32_t vl = mVolume[0];
+    int32_t vr = mVolume[1];
+
+    size_t inputIndex = mInputIndex;
+    uint32_t phaseFraction = mPhaseFraction;
+    uint32_t phaseIncrement = mPhaseIncrement;
+    size_t outputIndex = 0;
+    size_t outputSampleCount = outFrameCount * 2;
+    size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+    // fetch first buffer
+    if (mBuffer.frameCount == 0) {
+        mBuffer.frameCount = inFrameCount;
+        provider->getNextBuffer(&mBuffer);
+        if (mBuffer.raw == NULL)
+            return;
+        // LOGW("New buffer: offset=%p, frames=%d\n", mBuffer.raw, mBuffer.frameCount);
+    }
+    int16_t *in = mBuffer.i16;
+
+    while (outputIndex < outputSampleCount) {
+        int32_t sample;
+        int32_t x;
+
+        // calculate output sample
+        x = phaseFraction >> kPreInterpShift;
+        sample = interp(&left, x);
+        out[outputIndex++] += vl * sample;
+        out[outputIndex++] += vr * sample;
+
+        // increment phase
+        phaseFraction += phaseIncrement;
+        uint32_t indexIncrement = (phaseFraction >> kNumPhaseBits);
+        phaseFraction &= kPhaseMask;
+
+        // time to fetch another sample
+        while (indexIncrement--) {
+
+            inputIndex++;
+            if (inputIndex == mBuffer.frameCount) {
+                inputIndex = 0;
+                provider->releaseBuffer(&mBuffer);
+                mBuffer.frameCount = inFrameCount;
+                provider->getNextBuffer(&mBuffer);
+                if (mBuffer.raw == NULL)
+                    goto save_state;  // ugly, but efficient
+                // LOGW("New buffer: offset=%p, frames=%dn", mBuffer.raw, mBuffer.frameCount);
+                in = mBuffer.i16;
+            }
+
+            // advance sample state
+            advance(&left, in[inputIndex]);
+        }
+    }
+
+save_state:
+    // LOGW("Done: index=%d, fraction=%u", inputIndex, phaseFraction);
+    mInputIndex = inputIndex;
+    mPhaseFraction = phaseFraction;
+}
+
+// ----------------------------------------------------------------------------
+}
+; // namespace android
+
diff --git a/services/audioflinger/AudioResamplerCubic.h b/services/audioflinger/AudioResamplerCubic.h
new file mode 100644
index 0000000..b72b62a
--- /dev/null
+++ b/services/audioflinger/AudioResamplerCubic.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2007 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 ANDROID_AUDIO_RESAMPLER_CUBIC_H
+#define ANDROID_AUDIO_RESAMPLER_CUBIC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+
+#include "AudioResampler.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+class AudioResamplerCubic : public AudioResampler {
+public:
+    AudioResamplerCubic(int bitDepth, int inChannelCount, int32_t sampleRate) :
+        AudioResampler(bitDepth, inChannelCount, sampleRate) {
+    }
+    virtual void resample(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider);
+private:
+    // number of bits used in interpolation multiply - 14 bits avoids overflow
+    static const int kNumInterpBits = 14;
+
+    // bits to shift the phase fraction down to avoid overflow
+    static const int kPreInterpShift = kNumPhaseBits - kNumInterpBits;
+    typedef struct {
+        int32_t a, b, c, y0, y1, y2, y3;
+    } state;
+    void init();
+    void resampleMono16(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider);
+    void resampleStereo16(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider);
+    static inline int32_t interp(state* p, int32_t x) {
+        return (((((p->a * x >> 14) + p->b) * x >> 14) + p->c) * x >> 14) + p->y1;
+    }
+    static inline void advance(state* p, int16_t in) {
+        p->y0 = p->y1;
+        p->y1 = p->y2;
+        p->y2 = p->y3;
+        p->y3 = in;
+        p->a = (3 * (p->y1 - p->y2) - p->y0 + p->y3) >> 1;            
+        p->b = (p->y2 << 1) + p->y0 - (((5 * p->y1 + p->y3)) >> 1);
+        p->c = (p->y2 - p->y0) >> 1;
+    }
+    state left, right;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif /*ANDROID_AUDIO_RESAMPLER_CUBIC_H*/
diff --git a/services/audioflinger/AudioResamplerSinc.cpp b/services/audioflinger/AudioResamplerSinc.cpp
new file mode 100644
index 0000000..9e5e254
--- /dev/null
+++ b/services/audioflinger/AudioResamplerSinc.cpp
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#include <string.h>
+#include "AudioResamplerSinc.h"
+
+namespace android {
+// ----------------------------------------------------------------------------
+
+
+/*
+ * These coeficients are computed with the "fir" utility found in
+ * tools/resampler_tools
+ * TODO: A good optimization would be to transpose this matrix, to take
+ * better advantage of the data-cache.
+ */
+const int32_t AudioResamplerSinc::mFirCoefsUp[] = {
+        0x7fffffff, 0x7f15d078, 0x7c5e0da6, 0x77ecd867, 0x71e2e251, 0x6a6c304a, 0x61be7269, 0x58170412, 0x4db8ab05, 0x42e92ea6, 0x37eee214, 0x2d0e3bb1, 0x22879366, 0x18951e95, 0x0f693d0d, 0x072d2621,
+        0x00000000, 0xf9f66655, 0xf51a5fd7, 0xf16bbd84, 0xeee0d9ac, 0xed67a922, 0xece70de6, 0xed405897, 0xee50e505, 0xeff3be30, 0xf203370f, 0xf45a6741, 0xf6d67d53, 0xf957db66, 0xfbc2f647, 0xfe00f2b9,
+        0x00000000, 0x01b37218, 0x0313a0c6, 0x041d930d, 0x04d28057, 0x053731b0, 0x05534dff, 0x05309bfd, 0x04da440d, 0x045c1aee, 0x03c1fcdd, 0x03173ef5, 0x02663ae8, 0x01b7f736, 0x0113ec79, 0x007fe6a9,
+        0x00000000, 0xff96b229, 0xff44f99f, 0xff0a86be, 0xfee5f803, 0xfed518fd, 0xfed521fd, 0xfee2f4fd, 0xfefb54f8, 0xff1b159b, 0xff3f4203, 0xff6539e0, 0xff8ac502, 0xffae1ddd, 0xffcdf3f9, 0xffe96798,
+        0x00000000, 0x00119de6, 0x001e6b7e, 0x0026cb7a, 0x002b4830, 0x002c83d6, 0x002b2a82, 0x0027e67a, 0x002356f9, 0x001e098e, 0x001875e4, 0x0012fbbe, 0x000de2d1, 0x00095c10, 0x00058414, 0x00026636,
+        0x00000000, 0xfffe44a9, 0xfffd206d, 0xfffc7b7f, 0xfffc3c8f, 0xfffc4ac2, 0xfffc8f2b, 0xfffcf5c4, 0xfffd6df3, 0xfffdeab2, 0xfffe6275, 0xfffececf, 0xffff2c07, 0xffff788c, 0xffffb471, 0xffffe0f2,
+        0x00000000, 0x000013e6, 0x00001f03, 0x00002396, 0x00002399, 0x000020b6, 0x00001c3c, 0x00001722, 0x00001216, 0x00000d81, 0x0000099c, 0x0000067c, 0x00000419, 0x0000025f, 0x00000131, 0x00000070,
+        0x00000000, 0xffffffc7, 0xffffffb3, 0xffffffb3, 0xffffffbe, 0xffffffcd, 0xffffffdb, 0xffffffe7, 0xfffffff0, 0xfffffff7, 0xfffffffb, 0xfffffffe, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
+        0x00000000 // this one is needed for lerping the last coefficient
+};
+
+/*
+ * These coefficients are optimized for 48KHz -> 44.1KHz (stop-band at 22.050KHz)
+ * It's possible to use the above coefficient for any down-sampling
+ * at the expense of a slower processing loop (we can interpolate
+ * these coefficient from the above by "Stretching" them in time).
+ */
+const int32_t AudioResamplerSinc::mFirCoefsDown[] = {
+        0x7fffffff, 0x7f55e46d, 0x7d5b4c60, 0x7a1b4b98, 0x75a7fb14, 0x7019f0bd, 0x698f875a, 0x622bfd59, 0x5a167256, 0x5178cc54, 0x487e8e6c, 0x3f53aae8, 0x36235ad4, 0x2d17047b, 0x245539ab, 0x1c00d540,
+        0x14383e57, 0x0d14d5ca, 0x06aa910b, 0x0107c38b, 0xfc351654, 0xf835abae, 0xf5076b45, 0xf2a37202, 0xf0fe9faa, 0xf00a3bbd, 0xefb4aa81, 0xefea2b05, 0xf0959716, 0xf1a11e83, 0xf2f6f7a0, 0xf481fff4,
+        0xf62e48ce, 0xf7e98ca5, 0xf9a38b4c, 0xfb4e4bfa, 0xfcde456f, 0xfe4a6d30, 0xff8c2fdf, 0x009f5555, 0x0181d393, 0x0233940f, 0x02b62f06, 0x030ca07d, 0x033afa62, 0x03461725, 0x03334f83, 0x030835fa,
+        0x02ca59cc, 0x027f12d1, 0x022b570d, 0x01d39a49, 0x017bb78f, 0x0126e414, 0x00d7aaaf, 0x008feec7, 0x0050f584, 0x001b73e3, 0xffefa063, 0xffcd46ed, 0xffb3ddcd, 0xffa29aaa, 0xff988691, 0xff949066,
+        0xff959d24, 0xff9a959e, 0xffa27195, 0xffac4011, 0xffb72d2b, 0xffc28569, 0xffcdb706, 0xffd85171, 0xffe20364, 0xffea97e9, 0xfff1f2b2, 0xfff80c06, 0xfffcec92, 0x0000a955, 0x00035fd8, 0x000532cf,
+        0x00064735, 0x0006c1f9, 0x0006c62d, 0x000673ba, 0x0005e68f, 0x00053630, 0x000475a3, 0x0003b397, 0x0002fac1, 0x00025257, 0x0001be9e, 0x0001417a, 0x0000dafd, 0x000089eb, 0x00004c28, 0x00001f1d,
+        0x00000000, 0xffffec10, 0xffffe0be, 0xffffdbc5, 0xffffdb39, 0xffffdd8b, 0xffffe182, 0xffffe638, 0xffffeb0a, 0xffffef8f, 0xfffff38b, 0xfffff6e3, 0xfffff993, 0xfffffba6, 0xfffffd30, 0xfffffe4a,
+        0xffffff09, 0xffffff85, 0xffffffd1, 0xfffffffb, 0x0000000f, 0x00000016, 0x00000015, 0x00000012, 0x0000000d, 0x00000009, 0x00000006, 0x00000003, 0x00000002, 0x00000001, 0x00000000, 0x00000000,
+        0x00000000 // this one is needed for lerping the last coefficient
+};
+
+// ----------------------------------------------------------------------------
+
+static inline
+int32_t mulRL(int left, int32_t in, uint32_t vRL)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    if (left) {
+        asm( "smultb %[out], %[in], %[vRL] \n"
+             : [out]"=r"(out)
+             : [in]"%r"(in), [vRL]"r"(vRL)
+             : );
+    } else {
+        asm( "smultt %[out], %[in], %[vRL] \n"
+             : [out]"=r"(out)
+             : [in]"%r"(in), [vRL]"r"(vRL)
+             : );
+    }
+    return out;
+#else
+    if (left) {
+        return int16_t(in>>16) * int16_t(vRL&0xFFFF);
+    } else {
+        return int16_t(in>>16) * int16_t(vRL>>16);
+    }
+#endif
+}
+
+static inline
+int32_t mulAdd(int16_t in, int32_t v, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    asm( "smlawb %[out], %[v], %[in], %[a] \n"
+         : [out]"=r"(out)
+         : [in]"%r"(in), [v]"r"(v), [a]"r"(a)
+         : );
+    return out;
+#else
+    return a + in * (v>>16);
+    // improved precision
+    // return a + in * (v>>16) + ((in * (v & 0xffff)) >> 16);
+#endif
+}
+
+static inline
+int32_t mulAddRL(int left, uint32_t inRL, int32_t v, int32_t a)
+{
+#if defined(__arm__) && !defined(__thumb__)
+    int32_t out;
+    if (left) {
+        asm( "smlawb %[out], %[v], %[inRL], %[a] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
+             : );
+    } else {
+        asm( "smlawt %[out], %[v], %[inRL], %[a] \n"
+             : [out]"=r"(out)
+             : [inRL]"%r"(inRL), [v]"r"(v), [a]"r"(a)
+             : );
+    }
+    return out;
+#else
+    if (left) {
+        return a + (int16_t(inRL&0xFFFF) * (v>>16));
+        //improved precision
+        // return a + (int16_t(inRL&0xFFFF) * (v>>16)) + ((int16_t(inRL&0xFFFF) * (v & 0xffff)) >> 16);
+    } else {
+        return a + (int16_t(inRL>>16) * (v>>16));
+    }
+#endif
+}
+
+// ----------------------------------------------------------------------------
+
+AudioResamplerSinc::AudioResamplerSinc(int bitDepth,
+        int inChannelCount, int32_t sampleRate)
+    : AudioResampler(bitDepth, inChannelCount, sampleRate),
+    mState(0)
+{
+    /*
+     * Layout of the state buffer for 32 tap:
+     *
+     * "present" sample            beginning of 2nd buffer
+     *                 v                v
+     *  0              01               2              23              3
+     *  0              F0               0              F0              F
+     * [pppppppppppppppInnnnnnnnnnnnnnnnpppppppppppppppInnnnnnnnnnnnnnnn]
+     *                 ^               ^ head
+     *
+     * p = past samples, convoluted with the (p)ositive side of sinc()
+     * n = future samples, convoluted with the (n)egative side of sinc()
+     * r = extra space for implementing the ring buffer
+     *
+     */
+
+    const size_t numCoefs = 2*halfNumCoefs;
+    const size_t stateSize = numCoefs * inChannelCount * 2;
+    mState = new int16_t[stateSize];
+    memset(mState, 0, sizeof(int16_t)*stateSize);
+    mImpulse = mState + (halfNumCoefs-1)*inChannelCount;
+    mRingFull = mImpulse + (numCoefs+1)*inChannelCount;
+}
+
+AudioResamplerSinc::~AudioResamplerSinc()
+{
+    delete [] mState;
+}
+
+void AudioResamplerSinc::init() {
+}
+
+void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider)
+{
+    mFirCoefs = (mInSampleRate <= mSampleRate) ? mFirCoefsUp : mFirCoefsDown;
+
+    // select the appropriate resampler
+    switch (mChannelCount) {
+    case 1:
+        resample<1>(out, outFrameCount, provider);
+        break;
+    case 2:
+        resample<2>(out, outFrameCount, provider);
+        break;
+    }
+}
+
+
+template<int CHANNELS>
+void AudioResamplerSinc::resample(int32_t* out, size_t outFrameCount,
+        AudioBufferProvider* provider)
+{
+    int16_t* impulse = mImpulse;
+    uint32_t vRL = mVolumeRL;
+    size_t inputIndex = mInputIndex;
+    uint32_t phaseFraction = mPhaseFraction;
+    uint32_t phaseIncrement = mPhaseIncrement;
+    size_t outputIndex = 0;
+    size_t outputSampleCount = outFrameCount * 2;
+    size_t inFrameCount = (outFrameCount*mInSampleRate)/mSampleRate;
+
+    AudioBufferProvider::Buffer& buffer(mBuffer);
+    while (outputIndex < outputSampleCount) {
+        // buffer is empty, fetch a new one
+        while (buffer.frameCount == 0) {
+            buffer.frameCount = inFrameCount;
+            provider->getNextBuffer(&buffer);
+            if (buffer.raw == NULL) {
+                goto resample_exit;
+            }
+            const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
+            if (phaseIndex == 1) {
+                // read one frame
+                read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
+            } else if (phaseIndex == 2) {
+                // read 2 frames
+                read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
+                inputIndex++;
+                if (inputIndex >= mBuffer.frameCount) {
+                    inputIndex -= mBuffer.frameCount;
+                    provider->releaseBuffer(&buffer);
+                } else {
+                    read<CHANNELS>(impulse, phaseFraction, buffer.i16, inputIndex);
+                }
+           }
+        }
+        int16_t *in = buffer.i16;
+        const size_t frameCount = buffer.frameCount;
+
+        // Always read-in the first samples from the input buffer
+        int16_t* head = impulse + halfNumCoefs*CHANNELS;
+        head[0] = in[inputIndex*CHANNELS + 0];
+        if (CHANNELS == 2)
+            head[1] = in[inputIndex*CHANNELS + 1];
+
+        // handle boundary case
+        int32_t l, r;
+        while (outputIndex < outputSampleCount) {
+            filterCoefficient<CHANNELS>(l, r, phaseFraction, impulse);
+            out[outputIndex++] += 2 * mulRL(1, l, vRL);
+            out[outputIndex++] += 2 * mulRL(0, r, vRL);
+
+            phaseFraction += phaseIncrement;
+            const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
+            if (phaseIndex == 1) {
+                inputIndex++;
+                if (inputIndex >= frameCount)
+                    break;  // need a new buffer
+                read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
+            } else if(phaseIndex == 2) {    // maximum value
+                inputIndex++;
+                if (inputIndex >= frameCount)
+                    break;  // 0 frame available, 2 frames needed
+                // read first frame
+                read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
+                inputIndex++;
+                if (inputIndex >= frameCount)
+                    break;  // 0 frame available, 1 frame needed
+                // read second frame
+                read<CHANNELS>(impulse, phaseFraction, in, inputIndex);
+            }
+        }
+
+        // if done with buffer, save samples
+        if (inputIndex >= frameCount) {
+            inputIndex -= frameCount;
+            provider->releaseBuffer(&buffer);
+        }
+    }
+
+resample_exit:
+    mImpulse = impulse;
+    mInputIndex = inputIndex;
+    mPhaseFraction = phaseFraction;
+}
+
+template<int CHANNELS>
+/***
+* read()
+*
+* This function reads only one frame from input buffer and writes it in
+* state buffer
+*
+**/
+void AudioResamplerSinc::read(
+        int16_t*& impulse, uint32_t& phaseFraction,
+        int16_t const* in, size_t inputIndex)
+{
+    const uint32_t phaseIndex = phaseFraction >> kNumPhaseBits;
+    impulse += CHANNELS;
+    phaseFraction -= 1LU<<kNumPhaseBits;
+    if (impulse >= mRingFull) {
+        const size_t stateSize = (halfNumCoefs*2)*CHANNELS;
+        memcpy(mState, mState+stateSize, sizeof(int16_t)*stateSize);
+        impulse -= stateSize;
+    }
+    int16_t* head = impulse + halfNumCoefs*CHANNELS;
+    head[0] = in[inputIndex*CHANNELS + 0];
+    if (CHANNELS == 2)
+        head[1] = in[inputIndex*CHANNELS + 1];
+}
+
+template<int CHANNELS>
+void AudioResamplerSinc::filterCoefficient(
+        int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples)
+{
+    // compute the index of the coefficient on the positive side and
+    // negative side
+    uint32_t indexP = (phase & cMask) >> cShift;
+    uint16_t lerpP  = (phase & pMask) >> pShift;
+    uint32_t indexN = (-phase & cMask) >> cShift;
+    uint16_t lerpN  = (-phase & pMask) >> pShift;
+    if ((indexP == 0) && (lerpP == 0)) {
+        indexN = cMask >> cShift;
+        lerpN = pMask >> pShift;
+    }
+
+    l = 0;
+    r = 0;
+    int32_t const* coefs = mFirCoefs;
+    int16_t const *sP = samples;
+    int16_t const *sN = samples+CHANNELS;
+    for (unsigned int i=0 ; i<halfNumCoefs/4 ; i++) {
+        interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
+        interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
+        sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
+        interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
+        interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
+        sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
+        interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
+        interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
+        sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
+        interpolate<CHANNELS>(l, r, coefs+indexP, lerpP, sP);
+        interpolate<CHANNELS>(l, r, coefs+indexN, lerpN, sN);
+        sP -= CHANNELS; sN += CHANNELS; coefs += 1<<coefsBits;
+    }
+}
+
+template<int CHANNELS>
+void AudioResamplerSinc::interpolate(
+        int32_t& l, int32_t& r,
+        int32_t const* coefs, int16_t lerp, int16_t const* samples)
+{
+    int32_t c0 = coefs[0];
+    int32_t c1 = coefs[1];
+    int32_t sinc = mulAdd(lerp, (c1-c0)<<1, c0);
+    if (CHANNELS == 2) {
+        uint32_t rl = *reinterpret_cast<uint32_t const*>(samples);
+        l = mulAddRL(1, rl, sinc, l);
+        r = mulAddRL(0, rl, sinc, r);
+    } else {
+        r = l = mulAdd(samples[0], sinc, l);
+    }
+}
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/services/audioflinger/AudioResamplerSinc.h b/services/audioflinger/AudioResamplerSinc.h
new file mode 100644
index 0000000..e6cb90b
--- /dev/null
+++ b/services/audioflinger/AudioResamplerSinc.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2007 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 ANDROID_AUDIO_RESAMPLER_SINC_H
+#define ANDROID_AUDIO_RESAMPLER_SINC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <cutils/log.h>
+
+#include "AudioResampler.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class AudioResamplerSinc : public AudioResampler {
+public:
+    AudioResamplerSinc(int bitDepth, int inChannelCount, int32_t sampleRate);
+
+    ~AudioResamplerSinc();
+
+    virtual void resample(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider);
+private:
+    void init();
+
+    template<int CHANNELS>
+    void resample(int32_t* out, size_t outFrameCount,
+            AudioBufferProvider* provider);
+
+    template<int CHANNELS>
+    inline void filterCoefficient(
+            int32_t& l, int32_t& r, uint32_t phase, int16_t const *samples);
+
+    template<int CHANNELS>
+    inline void interpolate(
+            int32_t& l, int32_t& r,
+            int32_t const* coefs, int16_t lerp, int16_t const* samples);
+
+    template<int CHANNELS>
+    inline void read(int16_t*& impulse, uint32_t& phaseFraction,
+            int16_t const* in, size_t inputIndex);
+
+    int16_t *mState;
+    int16_t *mImpulse;
+    int16_t *mRingFull;
+
+    int32_t const * mFirCoefs;
+    static const int32_t mFirCoefsDown[];
+    static const int32_t mFirCoefsUp[];
+
+    // ----------------------------------------------------------------------------
+    static const int32_t RESAMPLE_FIR_NUM_COEF       = 8;
+    static const int32_t RESAMPLE_FIR_LERP_INT_BITS  = 4;
+
+    // we have 16 coefs samples per zero-crossing
+    static const int coefsBits = RESAMPLE_FIR_LERP_INT_BITS;        // 4
+    static const int cShift = kNumPhaseBits - coefsBits;            // 26
+    static const uint32_t cMask  = ((1<<coefsBits)-1) << cShift;    // 0xf<<26 = 3c00 0000
+
+    // and we use 15 bits to interpolate between these samples
+    // this cannot change because the mul below rely on it.
+    static const int pLerpBits = 15;
+    static const int pShift = kNumPhaseBits - coefsBits - pLerpBits;    // 11
+    static const uint32_t pMask  = ((1<<pLerpBits)-1) << pShift;    // 0x7fff << 11
+
+    // number of zero-crossing on each side
+    static const unsigned int halfNumCoefs = RESAMPLE_FIR_NUM_COEF;
+};
+
+// ----------------------------------------------------------------------------
+}; // namespace android
+
+#endif /*ANDROID_AUDIO_RESAMPLER_SINC_H*/
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
new file mode 100644
index 0000000..87975af
--- /dev/null
+++ b/services/camera/libcameraservice/Android.mk
@@ -0,0 +1,66 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Set USE_CAMERA_STUB if you don't want to use the hardware camera.
+
+# force these builds to use camera stub only
+ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
+  USE_CAMERA_STUB:=true
+endif
+
+ifeq ($(USE_CAMERA_STUB),)
+  USE_CAMERA_STUB:=false
+endif
+
+ifeq ($(USE_CAMERA_STUB),true)
+#
+# libcamerastub
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    CameraHardwareStub.cpp      \
+    FakeCamera.cpp
+
+LOCAL_MODULE:= libcamerastub
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_CFLAGS += -DSINGLE_PROCESS
+endif
+
+LOCAL_SHARED_LIBRARIES:= libui
+
+include $(BUILD_STATIC_LIBRARY)
+endif # USE_CAMERA_STUB
+
+#
+# libcameraservice
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    CameraService.cpp
+
+LOCAL_SHARED_LIBRARIES:= \
+    libui \
+    libutils \
+    libbinder \
+    libcutils \
+    libmedia \
+    libcamera_client \
+    libsurfaceflinger_client
+
+LOCAL_MODULE:= libcameraservice
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_CFLAGS += -DSINGLE_PROCESS
+endif
+
+ifeq ($(USE_CAMERA_STUB), true)
+LOCAL_STATIC_LIBRARIES += libcamerastub
+else
+LOCAL_SHARED_LIBRARIES += libcamera 
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
new file mode 100644
index 0000000..b3e0ee6
--- /dev/null
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
@@ -0,0 +1,410 @@
+/*
+**
+** Copyright 2008, 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_TAG "CameraHardwareStub"
+#include <utils/Log.h>
+
+#include "CameraHardwareStub.h"
+#include <utils/threads.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "CannedJpeg.h"
+
+namespace android {
+
+CameraHardwareStub::CameraHardwareStub()
+                  : mParameters(),
+                    mPreviewHeap(0),
+                    mRawHeap(0),
+                    mFakeCamera(0),
+                    mPreviewFrameSize(0),
+                    mNotifyCb(0),
+                    mDataCb(0),
+                    mDataCbTimestamp(0),
+                    mCallbackCookie(0),
+                    mMsgEnabled(0),
+                    mCurrentPreviewFrame(0)
+{
+    initDefaultParameters();
+}
+
+void CameraHardwareStub::initDefaultParameters()
+{
+    CameraParameters p;
+
+    p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
+    p.setPreviewSize(320, 240);
+    p.setPreviewFrameRate(15);
+    p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
+
+    p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
+    p.setPictureSize(320, 240);
+    p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
+
+    if (setParameters(p) != NO_ERROR) {
+        LOGE("Failed to set default parameters?!");
+    }
+}
+
+void CameraHardwareStub::initHeapLocked()
+{
+    // Create raw heap.
+    int picture_width, picture_height;
+    mParameters.getPictureSize(&picture_width, &picture_height);
+    mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);
+
+    int preview_width, preview_height;
+    mParameters.getPreviewSize(&preview_width, &preview_height);
+    LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
+
+    // Note that we enforce yuv420sp in setParameters().
+    int how_big = preview_width * preview_height * 3 / 2;
+
+    // If we are being reinitialized to the same size as before, no
+    // work needs to be done.
+    if (how_big == mPreviewFrameSize)
+        return;
+
+    mPreviewFrameSize = how_big;
+
+    // Make a new mmap'ed heap that can be shared across processes.
+    // use code below to test with pmem
+    mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
+    // Make an IMemory for each frame so that we can reuse them in callbacks.
+    for (int i = 0; i < kBufferCount; i++) {
+        mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
+    }
+
+    // Recreate the fake camera to reflect the current size.
+    delete mFakeCamera;
+    mFakeCamera = new FakeCamera(preview_width, preview_height);
+}
+
+CameraHardwareStub::~CameraHardwareStub()
+{
+    delete mFakeCamera;
+    mFakeCamera = 0; // paranoia
+}
+
+sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
+{
+    return mPreviewHeap;
+}
+
+sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
+{
+    return mRawHeap;
+}
+
+void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
+                                      data_callback data_cb,
+                                      data_callback_timestamp data_cb_timestamp,
+                                      void* user)
+{
+    Mutex::Autolock lock(mLock);
+    mNotifyCb = notify_cb;
+    mDataCb = data_cb;
+    mDataCbTimestamp = data_cb_timestamp;
+    mCallbackCookie = user;
+}
+
+void CameraHardwareStub::enableMsgType(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    mMsgEnabled |= msgType;
+}
+
+void CameraHardwareStub::disableMsgType(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    mMsgEnabled &= ~msgType;
+}
+
+bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    return (mMsgEnabled & msgType);
+}
+
+// ---------------------------------------------------------------------------
+
+int CameraHardwareStub::previewThread()
+{
+    mLock.lock();
+        // the attributes below can change under our feet...
+
+        int previewFrameRate = mParameters.getPreviewFrameRate();
+
+        // Find the offset within the heap of the current buffer.
+        ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
+
+        sp<MemoryHeapBase> heap = mPreviewHeap;
+
+        // this assumes the internal state of fake camera doesn't change
+        // (or is thread safe)
+        FakeCamera* fakeCamera = mFakeCamera;
+
+        sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
+
+    mLock.unlock();
+
+    // TODO: here check all the conditions that could go wrong
+    if (buffer != 0) {
+        // Calculate how long to wait between frames.
+        int delay = (int)(1000000.0f / float(previewFrameRate));
+
+        // This is always valid, even if the client died -- the memory
+        // is still mapped in our process.
+        void *base = heap->base();
+
+        // Fill the current frame with the fake camera.
+        uint8_t *frame = ((uint8_t *)base) + offset;
+        fakeCamera->getNextFrameAsYuv420(frame);
+
+        //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
+
+        // Notify the client of a new frame.
+        if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+            mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
+
+        // Advance the buffer pointer.
+        mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
+
+        // Wait for it...
+        usleep(delay);
+    }
+
+    return NO_ERROR;
+}
+
+status_t CameraHardwareStub::startPreview()
+{
+    Mutex::Autolock lock(mLock);
+    if (mPreviewThread != 0) {
+        // already running
+        return INVALID_OPERATION;
+    }
+    mPreviewThread = new PreviewThread(this);
+    return NO_ERROR;
+}
+
+void CameraHardwareStub::stopPreview()
+{
+    sp<PreviewThread> previewThread;
+
+    { // scope for the lock
+        Mutex::Autolock lock(mLock);
+        previewThread = mPreviewThread;
+    }
+
+    // don't hold the lock while waiting for the thread to quit
+    if (previewThread != 0) {
+        previewThread->requestExitAndWait();
+    }
+
+    Mutex::Autolock lock(mLock);
+    mPreviewThread.clear();
+}
+
+bool CameraHardwareStub::previewEnabled() {
+    return mPreviewThread != 0;
+}
+
+status_t CameraHardwareStub::startRecording()
+{
+    return UNKNOWN_ERROR;
+}
+
+void CameraHardwareStub::stopRecording()
+{
+}
+
+bool CameraHardwareStub::recordingEnabled()
+{
+    return false;
+}
+
+void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+}
+
+// ---------------------------------------------------------------------------
+
+int CameraHardwareStub::beginAutoFocusThread(void *cookie)
+{
+    CameraHardwareStub *c = (CameraHardwareStub *)cookie;
+    return c->autoFocusThread();
+}
+
+int CameraHardwareStub::autoFocusThread()
+{
+    if (mMsgEnabled & CAMERA_MSG_FOCUS)
+        mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+    return NO_ERROR;
+}
+
+status_t CameraHardwareStub::autoFocus()
+{
+    Mutex::Autolock lock(mLock);
+    if (createThread(beginAutoFocusThread, this) == false)
+        return UNKNOWN_ERROR;
+    return NO_ERROR;
+}
+
+status_t CameraHardwareStub::cancelAutoFocus()
+{
+    return NO_ERROR;
+}
+
+/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
+{
+    CameraHardwareStub *c = (CameraHardwareStub *)cookie;
+    return c->pictureThread();
+}
+
+int CameraHardwareStub::pictureThread()
+{
+    if (mMsgEnabled & CAMERA_MSG_SHUTTER)
+        mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
+
+    if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
+        //FIXME: use a canned YUV image!
+        // In the meantime just make another fake camera picture.
+        int w, h;
+        mParameters.getPictureSize(&w, &h);
+        sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
+        FakeCamera cam(w, h);
+        cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
+        mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
+    }
+
+    if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
+        sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
+        sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
+        memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
+        mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
+    }
+    return NO_ERROR;
+}
+
+status_t CameraHardwareStub::takePicture()
+{
+    stopPreview();
+    if (createThread(beginPictureThread, this) == false)
+        return UNKNOWN_ERROR;
+    return NO_ERROR;
+}
+
+status_t CameraHardwareStub::cancelPicture()
+{
+    return NO_ERROR;
+}
+
+status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    AutoMutex lock(&mLock);
+    if (mFakeCamera != 0) {
+        mFakeCamera->dump(fd);
+        mParameters.dump(fd, args);
+        snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
+        result.append(buffer);
+    } else {
+        result.append("No camera client yet.\n");
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t CameraHardwareStub::setParameters(const CameraParameters& params)
+{
+    Mutex::Autolock lock(mLock);
+    // XXX verify params
+
+    if (strcmp(params.getPreviewFormat(),
+        CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
+        LOGE("Only yuv420sp preview is supported");
+        return -1;
+    }
+
+    if (strcmp(params.getPictureFormat(),
+        CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
+        LOGE("Only jpeg still pictures are supported");
+        return -1;
+    }
+
+    int w, h;
+    params.getPictureSize(&w, &h);
+    if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
+        LOGE("Still picture size must be size of canned JPEG (%dx%d)",
+             kCannedJpegWidth, kCannedJpegHeight);
+        return -1;
+    }
+
+    mParameters = params;
+    initHeapLocked();
+
+    return NO_ERROR;
+}
+
+CameraParameters CameraHardwareStub::getParameters() const
+{
+    Mutex::Autolock lock(mLock);
+    return mParameters;
+}
+
+status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
+                                         int32_t arg2)
+{
+    return BAD_VALUE;
+}
+
+void CameraHardwareStub::release()
+{
+}
+
+sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
+{
+    return new CameraHardwareStub();
+}
+
+static CameraInfo sCameraInfo[] = {
+    {
+        CAMERA_FACING_BACK,
+        90,  /* orientation */
+    }
+};
+
+extern "C" int HAL_getNumberOfCameras()
+{
+    return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
+}
+
+extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
+{
+    memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
+}
+
+extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
+{
+    return CameraHardwareStub::createInstance();
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
new file mode 100644
index 0000000..d3427ba
--- /dev/null
+++ b/services/camera/libcameraservice/CameraHardwareStub.h
@@ -0,0 +1,133 @@
+/*
+**
+** Copyright 2008, 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 ANDROID_HARDWARE_CAMERA_HARDWARE_STUB_H
+#define ANDROID_HARDWARE_CAMERA_HARDWARE_STUB_H
+
+#include "FakeCamera.h"
+#include <utils/threads.h>
+#include <camera/CameraHardwareInterface.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class CameraHardwareStub : public CameraHardwareInterface {
+public:
+    virtual sp<IMemoryHeap> getPreviewHeap() const;
+    virtual sp<IMemoryHeap> getRawHeap() const;
+
+    virtual void        setCallbacks(notify_callback notify_cb,
+                                     data_callback data_cb,
+                                     data_callback_timestamp data_cb_timestamp,
+                                     void* user);
+
+    virtual void        enableMsgType(int32_t msgType);
+    virtual void        disableMsgType(int32_t msgType);
+    virtual bool        msgTypeEnabled(int32_t msgType);
+
+    virtual status_t    startPreview();
+    virtual void        stopPreview();
+    virtual bool        previewEnabled();
+
+    virtual status_t    startRecording();
+    virtual void        stopRecording();
+    virtual bool        recordingEnabled();
+    virtual void        releaseRecordingFrame(const sp<IMemory>& mem);
+
+    virtual status_t    autoFocus();
+    virtual status_t    cancelAutoFocus();
+    virtual status_t    takePicture();
+    virtual status_t    cancelPicture();
+    virtual status_t    dump(int fd, const Vector<String16>& args) const;
+    virtual status_t    setParameters(const CameraParameters& params);
+    virtual CameraParameters  getParameters() const;
+    virtual status_t    sendCommand(int32_t command, int32_t arg1,
+                                    int32_t arg2);
+    virtual void release();
+
+    static sp<CameraHardwareInterface> createInstance();
+
+private:
+                        CameraHardwareStub();
+    virtual             ~CameraHardwareStub();
+
+    static const int kBufferCount = 4;
+
+    class PreviewThread : public Thread {
+        CameraHardwareStub* mHardware;
+    public:
+        PreviewThread(CameraHardwareStub* hw) :
+#ifdef SINGLE_PROCESS
+            // In single process mode this thread needs to be a java thread,
+            // since we won't be calling through the binder.
+            Thread(true),
+#else
+            Thread(false),
+#endif
+              mHardware(hw) { }
+        virtual void onFirstRef() {
+            run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
+        }
+        virtual bool threadLoop() {
+            mHardware->previewThread();
+            // loop until we need to quit
+            return true;
+        }
+    };
+
+    void initDefaultParameters();
+    void initHeapLocked();
+
+    int previewThread();
+
+    static int beginAutoFocusThread(void *cookie);
+    int autoFocusThread();
+
+    static int beginPictureThread(void *cookie);
+    int pictureThread();
+
+    mutable Mutex       mLock;
+
+    CameraParameters    mParameters;
+
+    sp<MemoryHeapBase>  mPreviewHeap;
+    sp<MemoryHeapBase>  mRawHeap;
+    sp<MemoryBase>      mBuffers[kBufferCount];
+
+    FakeCamera          *mFakeCamera;
+    bool                mPreviewRunning;
+    int                 mPreviewFrameSize;
+
+    // protected by mLock
+    sp<PreviewThread>   mPreviewThread;
+
+    notify_callback    mNotifyCb;
+    data_callback      mDataCb;
+    data_callback_timestamp mDataCbTimestamp;
+    void               *mCallbackCookie;
+
+    int32_t             mMsgEnabled;
+
+    // only used from PreviewThread
+    int                 mCurrentPreviewFrame;
+};
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
new file mode 100644
index 0000000..3b3904a
--- /dev/null
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -0,0 +1,1267 @@
+/*
+**
+** Copyright (C) 2008, 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_TAG "CameraService"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <cutils/atomic.h>
+#include <hardware/hardware.h>
+#include <media/AudioSystem.h>
+#include <media/mediaplayer.h>
+#include <surfaceflinger/ISurface.h>
+#include <ui/Overlay.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/String16.h>
+
+#include "CameraService.h"
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+// Logging support -- this is for debugging only
+// Use "adb shell dumpsys media.camera -v 1" to change it.
+static volatile int32_t gLogLevel = 0;
+
+#define LOG1(...) LOGD_IF(gLogLevel >= 1, __VA_ARGS__);
+#define LOG2(...) LOGD_IF(gLogLevel >= 2, __VA_ARGS__);
+
+static void setLogLevel(int level) {
+    android_atomic_write(level, &gLogLevel);
+}
+
+// ----------------------------------------------------------------------------
+
+static int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
+static int getCallingUid() {
+    return IPCThreadState::self()->getCallingUid();
+}
+
+// ----------------------------------------------------------------------------
+
+// This is ugly and only safe if we never re-create the CameraService, but
+// should be ok for now.
+static CameraService *gCameraService;
+
+CameraService::CameraService()
+:mSoundRef(0)
+{
+    LOGI("CameraService started (pid=%d)", getpid());
+
+    mNumberOfCameras = HAL_getNumberOfCameras();
+    if (mNumberOfCameras > MAX_CAMERAS) {
+        LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
+             mNumberOfCameras, MAX_CAMERAS);
+        mNumberOfCameras = MAX_CAMERAS;
+    }
+
+    for (int i = 0; i < mNumberOfCameras; i++) {
+        setCameraFree(i);
+    }
+
+    gCameraService = this;
+}
+
+CameraService::~CameraService() {
+    for (int i = 0; i < mNumberOfCameras; i++) {
+        if (mBusy[i]) {
+            LOGE("camera %d is still in use in destructor!", i);
+        }
+    }
+
+    gCameraService = NULL;
+}
+
+int32_t CameraService::getNumberOfCameras() {
+    return mNumberOfCameras;
+}
+
+status_t CameraService::getCameraInfo(int cameraId,
+                                      struct CameraInfo* cameraInfo) {
+    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
+        return BAD_VALUE;
+    }
+
+    HAL_getCameraInfo(cameraId, cameraInfo);
+    return OK;
+}
+
+sp<ICamera> CameraService::connect(
+        const sp<ICameraClient>& cameraClient, int cameraId) {
+    int callingPid = getCallingPid();
+    LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
+
+    sp<Client> client;
+    if (cameraId < 0 || cameraId >= mNumberOfCameras) {
+        LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
+            callingPid, cameraId);
+        return NULL;
+    }
+
+    Mutex::Autolock lock(mServiceLock);
+    if (mClient[cameraId] != 0) {
+        client = mClient[cameraId].promote();
+        if (client != 0) {
+            if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
+                LOG1("CameraService::connect X (pid %d) (the same client)",
+                    callingPid);
+                return client;
+            } else {
+                LOGW("CameraService::connect X (pid %d) rejected (existing client).",
+                    callingPid);
+                return NULL;
+            }
+        }
+        mClient[cameraId].clear();
+    }
+
+    if (mBusy[cameraId]) {
+        LOGW("CameraService::connect X (pid %d) rejected"
+             " (camera %d is still busy).", callingPid, cameraId);
+        return NULL;
+    }
+
+    client = new Client(this, cameraClient, cameraId, callingPid);
+    mClient[cameraId] = client;
+    LOG1("CameraService::connect X");
+    return client;
+}
+
+void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
+    int callingPid = getCallingPid();
+    LOG1("CameraService::removeClient E (pid %d)", callingPid);
+
+    for (int i = 0; i < mNumberOfCameras; i++) {
+        // Declare this before the lock to make absolutely sure the
+        // destructor won't be called with the lock held.
+        sp<Client> client;
+
+        Mutex::Autolock lock(mServiceLock);
+
+        // This happens when we have already disconnected (or this is
+        // just another unused camera).
+        if (mClient[i] == 0) continue;
+
+        // Promote mClient. It can fail if we are called from this path:
+        // Client::~Client() -> disconnect() -> removeClient().
+        client = mClient[i].promote();
+
+        if (client == 0) {
+            mClient[i].clear();
+            continue;
+        }
+
+        if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
+            // Found our camera, clear and leave.
+            LOG1("removeClient: clear camera %d", i);
+            mClient[i].clear();
+            break;
+        }
+    }
+
+    LOG1("CameraService::removeClient X (pid %d)", callingPid);
+}
+
+sp<CameraService::Client> CameraService::getClientById(int cameraId) {
+    if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
+    return mClient[cameraId].promote();
+}
+
+status_t CameraService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    // Permission checks
+    switch (code) {
+        case BnCameraService::CONNECT:
+            const int pid = getCallingPid();
+            const int self_pid = getpid();
+            if (pid != self_pid) {
+                // we're called from a different process, do the real check
+                if (!checkCallingPermission(
+                        String16("android.permission.CAMERA"))) {
+                    const int uid = getCallingUid();
+                    LOGE("Permission Denial: "
+                         "can't use the camera pid=%d, uid=%d", pid, uid);
+                    return PERMISSION_DENIED;
+                }
+            }
+            break;
+    }
+
+    return BnCameraService::onTransact(code, data, reply, flags);
+}
+
+// The reason we need this busy bit is a new CameraService::connect() request
+// may come in while the previous Client's destructor has not been run or is
+// still running. If the last strong reference of the previous Client is gone
+// but the destructor has not been finished, we should not allow the new Client
+// to be created because we need to wait for the previous Client to tear down
+// the hardware first.
+void CameraService::setCameraBusy(int cameraId) {
+    android_atomic_write(1, &mBusy[cameraId]);
+}
+
+void CameraService::setCameraFree(int cameraId) {
+    android_atomic_write(0, &mBusy[cameraId]);
+}
+
+// We share the media players for shutter and recording sound for all clients.
+// A reference count is kept to determine when we will actually release the
+// media players.
+
+static MediaPlayer* newMediaPlayer(const char *file) {
+    MediaPlayer* mp = new MediaPlayer();
+    if (mp->setDataSource(file, NULL) == NO_ERROR) {
+        mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
+        mp->prepare();
+    } else {
+        LOGE("Failed to load CameraService sounds: %s", file);
+        return NULL;
+    }
+    return mp;
+}
+
+void CameraService::loadSound() {
+    Mutex::Autolock lock(mSoundLock);
+    LOG1("CameraService::loadSound ref=%d", mSoundRef);
+    if (mSoundRef++) return;
+
+    mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
+    mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+}
+
+void CameraService::releaseSound() {
+    Mutex::Autolock lock(mSoundLock);
+    LOG1("CameraService::releaseSound ref=%d", mSoundRef);
+    if (--mSoundRef) return;
+
+    for (int i = 0; i < NUM_SOUNDS; i++) {
+        if (mSoundPlayer[i] != 0) {
+            mSoundPlayer[i]->disconnect();
+            mSoundPlayer[i].clear();
+        }
+    }
+}
+
+void CameraService::playSound(sound_kind kind) {
+    LOG1("playSound(%d)", kind);
+    Mutex::Autolock lock(mSoundLock);
+    sp<MediaPlayer> player = mSoundPlayer[kind];
+    if (player != 0) {
+        // do not play the sound if stream volume is 0
+        // (typically because ringer mode is silent).
+        int index;
+        AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+        if (index != 0) {
+            player->seekTo(0);
+            player->start();
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+CameraService::Client::Client(const sp<CameraService>& cameraService,
+        const sp<ICameraClient>& cameraClient, int cameraId, int clientPid) {
+    int callingPid = getCallingPid();
+    LOG1("Client::Client E (pid %d)", callingPid);
+
+    mCameraService = cameraService;
+    mCameraClient = cameraClient;
+    mCameraId = cameraId;
+    mClientPid = clientPid;
+
+    mHardware = HAL_openCameraHardware(cameraId);
+    mUseOverlay = mHardware->useOverlay();
+    mMsgEnabled = 0;
+
+    mHardware->setCallbacks(notifyCallback,
+                            dataCallback,
+                            dataCallbackTimestamp,
+                            (void *)cameraId);
+
+    // Enable zoom, error, and focus messages by default
+    enableMsgType(CAMERA_MSG_ERROR |
+                  CAMERA_MSG_ZOOM |
+                  CAMERA_MSG_FOCUS);
+    mOverlayW = 0;
+    mOverlayH = 0;
+
+    // Callback is disabled by default
+    mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+    mOrientation = 0;
+    cameraService->setCameraBusy(cameraId);
+    cameraService->loadSound();
+    LOG1("Client::Client X (pid %d)", callingPid);
+}
+
+static void *unregister_surface(void *arg) {
+    ISurface *surface = (ISurface *)arg;
+    surface->unregisterBuffers();
+    IPCThreadState::self()->flushCommands();
+    return NULL;
+}
+
+// tear down the client
+CameraService::Client::~Client() {
+    int callingPid = getCallingPid();
+    LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
+
+    if (mSurface != 0 && !mUseOverlay) {
+        pthread_t thr;
+        // We unregister the buffers in a different thread because binder does
+        // not let us make sychronous transactions in a binder destructor (that
+        // is, upon our reaching a refcount of zero.)
+        pthread_create(&thr,
+                       NULL,  // attr
+                       unregister_surface,
+                       mSurface.get());
+        pthread_join(thr, NULL);
+    }
+
+    // set mClientPid to let disconnet() tear down the hardware
+    mClientPid = callingPid;
+    disconnect();
+    mCameraService->releaseSound();
+    LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
+}
+
+// ----------------------------------------------------------------------------
+
+status_t CameraService::Client::checkPid() const {
+    int callingPid = getCallingPid();
+    if (callingPid == mClientPid) return NO_ERROR;
+
+    LOGW("attempt to use a locked camera from a different process"
+         " (old pid %d, new pid %d)", mClientPid, callingPid);
+    return EBUSY;
+}
+
+status_t CameraService::Client::checkPidAndHardware() const {
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+    if (mHardware == 0) {
+        LOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
+}
+
+status_t CameraService::Client::lock() {
+    int callingPid = getCallingPid();
+    LOG1("lock (pid %d)", callingPid);
+    Mutex::Autolock lock(mLock);
+
+    // lock camera to this client if the the camera is unlocked
+    if (mClientPid == 0) {
+        mClientPid = callingPid;
+        return NO_ERROR;
+    }
+
+    // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
+    return checkPid();
+}
+
+status_t CameraService::Client::unlock() {
+    int callingPid = getCallingPid();
+    LOG1("unlock (pid %d)", callingPid);
+    Mutex::Autolock lock(mLock);
+
+    // allow anyone to use camera (after they lock the camera)
+    status_t result = checkPid();
+    if (result == NO_ERROR) {
+        mClientPid = 0;
+        LOG1("clear mCameraClient (pid %d)", callingPid);
+        // we need to remove the reference to ICameraClient so that when the app
+        // goes away, the reference count goes to 0.
+        mCameraClient.clear();
+    }
+    return result;
+}
+
+// connect a new client to the camera
+status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
+    int callingPid = getCallingPid();
+    LOG1("connect E (pid %d)", callingPid);
+    Mutex::Autolock lock(mLock);
+
+    if (mClientPid != 0 && checkPid() != NO_ERROR) {
+        LOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
+                mClientPid, callingPid);
+        return EBUSY;
+    }
+
+    if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
+        LOG1("Connect to the same client");
+        return NO_ERROR;
+    }
+
+    mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+    mClientPid = callingPid;
+    mCameraClient = client;
+
+    LOG1("connect X (pid %d)", callingPid);
+    return NO_ERROR;
+}
+
+void CameraService::Client::disconnect() {
+    int callingPid = getCallingPid();
+    LOG1("disconnect E (pid %d)", callingPid);
+    Mutex::Autolock lock(mLock);
+
+    if (checkPid() != NO_ERROR) {
+        LOGW("different client - don't disconnect");
+        return;
+    }
+
+    if (mClientPid <= 0) {
+        LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
+        return;
+    }
+
+    // Make sure disconnect() is done once and once only, whether it is called
+    // from the user directly, or called by the destructor.
+    if (mHardware == 0) return;
+
+    LOG1("hardware teardown");
+    // Before destroying mHardware, we must make sure it's in the
+    // idle state.
+    // Turn off all messages.
+    disableMsgType(CAMERA_MSG_ALL_MSGS);
+    mHardware->stopPreview();
+    mHardware->cancelPicture();
+    // Release the hardware resources.
+    mHardware->release();
+    // Release the held overlay resources.
+    if (mUseOverlay) {
+        mOverlayRef = 0;
+    }
+    mHardware.clear();
+
+    mCameraService->removeClient(mCameraClient);
+    mCameraService->setCameraFree(mCameraId);
+
+    LOG1("disconnect X (pid %d)", callingPid);
+}
+
+// ----------------------------------------------------------------------------
+
+// set the ISurface that the preview will use
+status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
+    LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    result = NO_ERROR;
+
+    // return if no change in surface.
+    // asBinder() is safe on NULL (returns NULL)
+    if (surface->asBinder() == mSurface->asBinder()) {
+        return result;
+    }
+
+    if (mSurface != 0) {
+        LOG1("clearing old preview surface %p", mSurface.get());
+        if (mUseOverlay) {
+            // Force the destruction of any previous overlay
+            sp<Overlay> dummy;
+            mHardware->setOverlay(dummy);
+        } else {
+            mSurface->unregisterBuffers();
+        }
+    }
+    mSurface = surface;
+    mOverlayRef = 0;
+    // If preview has been already started, set overlay or register preview
+    // buffers now.
+    if (mHardware->previewEnabled()) {
+        if (mUseOverlay) {
+            result = setOverlay();
+        } else if (mSurface != 0) {
+            result = registerPreviewBuffers();
+        }
+    }
+
+    return result;
+}
+
+status_t CameraService::Client::registerPreviewBuffers() {
+    int w, h;
+    CameraParameters params(mHardware->getParameters());
+    params.getPreviewSize(&w, &h);
+
+    // FIXME: don't use a hardcoded format here.
+    ISurface::BufferHeap buffers(w, h, w, h,
+                                 HAL_PIXEL_FORMAT_YCrCb_420_SP,
+                                 mOrientation,
+                                 0,
+                                 mHardware->getPreviewHeap());
+
+    status_t result = mSurface->registerBuffers(buffers);
+    if (result != NO_ERROR) {
+        LOGE("registerBuffers failed with status %d", result);
+    }
+    return result;
+}
+
+status_t CameraService::Client::setOverlay() {
+    int w, h;
+    CameraParameters params(mHardware->getParameters());
+    params.getPreviewSize(&w, &h);
+
+    if (w != mOverlayW || h != mOverlayH) {
+        // Force the destruction of any previous overlay
+        sp<Overlay> dummy;
+        mHardware->setOverlay(dummy);
+        mOverlayRef = 0;
+    }
+
+    status_t result = NO_ERROR;
+    if (mSurface == 0) {
+        result = mHardware->setOverlay(NULL);
+    } else {
+        if (mOverlayRef == 0) {
+            // FIXME:
+            // Surfaceflinger may hold onto the previous overlay reference for some
+            // time after we try to destroy it. retry a few times. In the future, we
+            // should make the destroy call block, or possibly specify that we can
+            // wait in the createOverlay call if the previous overlay is in the
+            // process of being destroyed.
+            for (int retry = 0; retry < 50; ++retry) {
+                mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
+                                                      mOrientation);
+                if (mOverlayRef != 0) break;
+                LOGW("Overlay create failed - retrying");
+                usleep(20000);
+            }
+            if (mOverlayRef == 0) {
+                LOGE("Overlay Creation Failed!");
+                return -EINVAL;
+            }
+            result = mHardware->setOverlay(new Overlay(mOverlayRef));
+        }
+    }
+    if (result != NO_ERROR) {
+        LOGE("mHardware->setOverlay() failed with status %d\n", result);
+        return result;
+    }
+
+    mOverlayW = w;
+    mOverlayH = h;
+
+    return result;
+}
+
+// set the preview callback flag to affect how the received frames from
+// preview are handled.
+void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
+    LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return;
+
+    mPreviewCallbackFlag = callback_flag;
+
+    // If we don't use overlay, we always need the preview frame for display.
+    // If we do use overlay, we only need the preview frame if the user
+    // wants the data.
+    if (mUseOverlay) {
+        if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
+            enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        } else {
+            disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        }
+    }
+}
+
+// start preview mode
+status_t CameraService::Client::startPreview() {
+    LOG1("startPreview (pid %d)", getCallingPid());
+    return startCameraMode(CAMERA_PREVIEW_MODE);
+}
+
+// start recording mode
+status_t CameraService::Client::startRecording() {
+    LOG1("startRecording (pid %d)", getCallingPid());
+    return startCameraMode(CAMERA_RECORDING_MODE);
+}
+
+// start preview or recording
+status_t CameraService::Client::startCameraMode(camera_mode mode) {
+    LOG1("startCameraMode(%d)", mode);
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    switch(mode) {
+        case CAMERA_PREVIEW_MODE:
+            if (mSurface == 0) {
+                LOG1("mSurface is not set yet.");
+                // still able to start preview in this case.
+            }
+            return startPreviewMode();
+        case CAMERA_RECORDING_MODE:
+            if (mSurface == 0) {
+                LOGE("mSurface must be set before startRecordingMode.");
+                return INVALID_OPERATION;
+            }
+            return startRecordingMode();
+        default:
+            return UNKNOWN_ERROR;
+    }
+}
+
+status_t CameraService::Client::startPreviewMode() {
+    LOG1("startPreviewMode");
+    status_t result = NO_ERROR;
+
+    // if preview has been enabled, nothing needs to be done
+    if (mHardware->previewEnabled()) {
+        return NO_ERROR;
+    }
+
+    if (mUseOverlay) {
+        // If preview display has been set, set overlay now.
+        if (mSurface != 0) {
+            result = setOverlay();
+        }
+        if (result != NO_ERROR) return result;
+        result = mHardware->startPreview();
+    } else {
+        enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        result = mHardware->startPreview();
+        if (result != NO_ERROR) return result;
+        // If preview display has been set, register preview buffers now.
+        if (mSurface != 0) {
+           // Unregister here because the surface may be previously registered
+           // with the raw (snapshot) heap.
+           mSurface->unregisterBuffers();
+           result = registerPreviewBuffers();
+        }
+    }
+    return result;
+}
+
+status_t CameraService::Client::startRecordingMode() {
+    LOG1("startRecordingMode");
+    status_t result = NO_ERROR;
+
+    // if recording has been enabled, nothing needs to be done
+    if (mHardware->recordingEnabled()) {
+        return NO_ERROR;
+    }
+
+    // if preview has not been started, start preview first
+    if (!mHardware->previewEnabled()) {
+        result = startPreviewMode();
+        if (result != NO_ERROR) {
+            return result;
+        }
+    }
+
+    // start recording mode
+    enableMsgType(CAMERA_MSG_VIDEO_FRAME);
+    mCameraService->playSound(SOUND_RECORDING);
+    result = mHardware->startRecording();
+    if (result != NO_ERROR) {
+        LOGE("mHardware->startRecording() failed with status %d", result);
+    }
+    return result;
+}
+
+// stop preview mode
+void CameraService::Client::stopPreview() {
+    LOG1("stopPreview (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return;
+
+    disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    mHardware->stopPreview();
+
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->unregisterBuffers();
+    }
+
+    mPreviewBuffer.clear();
+}
+
+// stop recording mode
+void CameraService::Client::stopRecording() {
+    LOG1("stopRecording (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return;
+
+    mCameraService->playSound(SOUND_RECORDING);
+    disableMsgType(CAMERA_MSG_VIDEO_FRAME);
+    mHardware->stopRecording();
+
+    mPreviewBuffer.clear();
+}
+
+// release a recording frame
+void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return;
+    mHardware->releaseRecordingFrame(mem);
+}
+
+bool CameraService::Client::previewEnabled() {
+    LOG1("previewEnabled (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return false;
+    return mHardware->previewEnabled();
+}
+
+bool CameraService::Client::recordingEnabled() {
+    LOG1("recordingEnabled (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return false;
+    return mHardware->recordingEnabled();
+}
+
+status_t CameraService::Client::autoFocus() {
+    LOG1("autoFocus (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    return mHardware->autoFocus();
+}
+
+status_t CameraService::Client::cancelAutoFocus() {
+    LOG1("cancelAutoFocus (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    return mHardware->cancelAutoFocus();
+}
+
+// take a picture - image is returned in callback
+status_t CameraService::Client::takePicture() {
+    LOG1("takePicture (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    enableMsgType(CAMERA_MSG_SHUTTER |
+                  CAMERA_MSG_POSTVIEW_FRAME |
+                  CAMERA_MSG_RAW_IMAGE |
+                  CAMERA_MSG_COMPRESSED_IMAGE);
+
+    return mHardware->takePicture();
+}
+
+// set preview/capture parameters - key/value pairs
+status_t CameraService::Client::setParameters(const String8& params) {
+    LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    CameraParameters p(params);
+    return mHardware->setParameters(p);
+}
+
+// get preview/capture parameters - key/value pairs
+String8 CameraService::Client::getParameters() const {
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return String8();
+
+    String8 params(mHardware->getParameters().flatten());
+    LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
+    return params;
+}
+
+status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
+    LOG1("sendCommand (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
+        // The orientation cannot be set during preview.
+        if (mHardware->previewEnabled()) {
+            return INVALID_OPERATION;
+        }
+        switch (arg1) {
+            case 0:
+                mOrientation = ISurface::BufferHeap::ROT_0;
+                break;
+            case 90:
+                mOrientation = ISurface::BufferHeap::ROT_90;
+                break;
+            case 180:
+                mOrientation = ISurface::BufferHeap::ROT_180;
+                break;
+            case 270:
+                mOrientation = ISurface::BufferHeap::ROT_270;
+                break;
+            default:
+                return BAD_VALUE;
+        }
+        return OK;
+    }
+
+    return mHardware->sendCommand(cmd, arg1, arg2);
+}
+
+// ----------------------------------------------------------------------------
+
+void CameraService::Client::enableMsgType(int32_t msgType) {
+    android_atomic_or(msgType, &mMsgEnabled);
+    mHardware->enableMsgType(msgType);
+}
+
+void CameraService::Client::disableMsgType(int32_t msgType) {
+    android_atomic_and(~msgType, &mMsgEnabled);
+    mHardware->disableMsgType(msgType);
+}
+
+#define CHECK_MESSAGE_INTERVAL 10 // 10ms
+bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
+    int sleepCount = 0;
+    while (mMsgEnabled & msgType) {
+        if (mLock.tryLock() == NO_ERROR) {
+            if (sleepCount > 0) {
+                LOG1("lockIfMessageWanted(%d): waited for %d ms",
+                    msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
+            }
+            return true;
+        }
+        if (sleepCount++ == 0) {
+            LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
+        }
+        usleep(CHECK_MESSAGE_INTERVAL * 1000);
+    }
+    LOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
+    return false;
+}
+
+// ----------------------------------------------------------------------------
+
+// Converts from a raw pointer to the client to a strong pointer during a
+// hardware callback. This requires the callbacks only happen when the client
+// is still alive.
+sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
+    sp<Client> client = gCameraService->getClientById((int) user);
+
+    // This could happen if the Client is in the process of shutting down (the
+    // last strong reference is gone, but the destructor hasn't finished
+    // stopping the hardware).
+    if (client == 0) return NULL;
+
+    // The checks below are not necessary and are for debugging only.
+    if (client->mCameraService.get() != gCameraService) {
+        LOGE("mismatch service!");
+        return NULL;
+    }
+
+    if (client->mHardware == 0) {
+        LOGE("mHardware == 0: callback after disconnect()?");
+        return NULL;
+    }
+
+    return client;
+}
+
+// Callback messages can be dispatched to internal handlers or pass to our
+// client's callback functions, depending on the message type.
+//
+// notifyCallback:
+//      CAMERA_MSG_SHUTTER              handleShutter
+//      (others)                        c->notifyCallback
+// dataCallback:
+//      CAMERA_MSG_PREVIEW_FRAME        handlePreviewData
+//      CAMERA_MSG_POSTVIEW_FRAME       handlePostview
+//      CAMERA_MSG_RAW_IMAGE            handleRawPicture
+//      CAMERA_MSG_COMPRESSED_IMAGE     handleCompressedPicture
+//      (others)                        c->dataCallback
+// dataCallbackTimestamp
+//      (others)                        c->dataCallbackTimestamp
+//
+// NOTE: the *Callback functions grab mLock of the client before passing
+// control to handle* functions. So the handle* functions must release the
+// lock before calling the ICameraClient's callbacks, so those callbacks can
+// invoke methods in the Client class again (For example, the preview frame
+// callback may want to releaseRecordingFrame). The handle* functions must
+// release the lock after all accesses to member variables, so it must be
+// handled very carefully.
+
+void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
+        int32_t ext2, void* user) {
+    LOG2("notifyCallback(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) return;
+    if (!client->lockIfMessageWanted(msgType)) return;
+
+    switch (msgType) {
+        case CAMERA_MSG_SHUTTER:
+            // ext1 is the dimension of the yuv picture.
+            client->handleShutter((image_rect_type *)ext1);
+            break;
+        default:
+            client->handleGenericNotify(msgType, ext1, ext2);
+            break;
+    }
+}
+
+void CameraService::Client::dataCallback(int32_t msgType,
+        const sp<IMemory>& dataPtr, void* user) {
+    LOG2("dataCallback(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) return;
+    if (!client->lockIfMessageWanted(msgType)) return;
+
+    if (dataPtr == 0) {
+        LOGE("Null data returned in data callback");
+        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+        return;
+    }
+
+    switch (msgType) {
+        case CAMERA_MSG_PREVIEW_FRAME:
+            client->handlePreviewData(dataPtr);
+            break;
+        case CAMERA_MSG_POSTVIEW_FRAME:
+            client->handlePostview(dataPtr);
+            break;
+        case CAMERA_MSG_RAW_IMAGE:
+            client->handleRawPicture(dataPtr);
+            break;
+        case CAMERA_MSG_COMPRESSED_IMAGE:
+            client->handleCompressedPicture(dataPtr);
+            break;
+        default:
+            client->handleGenericData(msgType, dataPtr);
+            break;
+    }
+}
+
+void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
+        int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
+    LOG2("dataCallbackTimestamp(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) return;
+    if (!client->lockIfMessageWanted(msgType)) return;
+
+    if (dataPtr == 0) {
+        LOGE("Null data returned in data with timestamp callback");
+        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+        return;
+    }
+
+    client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
+}
+
+// snapshot taken callback
+// "size" is the width and height of yuv picture for registerBuffer.
+// If it is NULL, use the picture size from parameters.
+void CameraService::Client::handleShutter(image_rect_type *size) {
+    mCameraService->playSound(SOUND_SHUTTER);
+
+    // Screen goes black after the buffer is unregistered.
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->unregisterBuffers();
+    }
+
+    sp<ICameraClient> c = mCameraClient;
+    if (c != 0) {
+        mLock.unlock();
+        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+        if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
+    }
+    disableMsgType(CAMERA_MSG_SHUTTER);
+
+    // It takes some time before yuvPicture callback to be called.
+    // Register the buffer for raw image here to reduce latency.
+    if (mSurface != 0 && !mUseOverlay) {
+        int w, h;
+        CameraParameters params(mHardware->getParameters());
+        if (size == NULL) {
+            params.getPictureSize(&w, &h);
+        } else {
+            w = size->width;
+            h = size->height;
+            w &= ~1;
+            h &= ~1;
+            LOG1("Snapshot image width=%d, height=%d", w, h);
+        }
+        // FIXME: don't use hardcoded format constants here
+        ISurface::BufferHeap buffers(w, h, w, h,
+            HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
+            mHardware->getRawHeap());
+
+        mSurface->registerBuffers(buffers);
+        IPCThreadState::self()->flushCommands();
+    }
+
+    mLock.unlock();
+}
+
+// preview callback - frame buffer update
+void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+    if (!mUseOverlay) {
+        if (mSurface != 0) {
+            mSurface->postBuffer(offset);
+        }
+    }
+
+    // local copy of the callback flags
+    int flags = mPreviewCallbackFlag;
+
+    // is callback enabled?
+    if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+        // If the enable bit is off, the copy-out and one-shot bits are ignored
+        LOG2("frame callback is disabled");
+        mLock.unlock();
+        return;
+    }
+
+    // hold a strong pointer to the client
+    sp<ICameraClient> c = mCameraClient;
+
+    // clear callback flags if no client or one-shot mode
+    if (c == 0 || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
+        LOG2("Disable preview callback");
+        mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+                                  FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+                                  FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        if (mUseOverlay) {
+            disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        }
+    }
+
+    if (c != 0) {
+        // Is the received frame copied out or not?
+        if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+            LOG2("frame is copied");
+            copyFrameAndPostCopiedFrame(c, heap, offset, size);
+        } else {
+            LOG2("frame is forwarded");
+            mLock.unlock();
+            c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
+        }
+    } else {
+        mLock.unlock();
+    }
+}
+
+// picture callback - postview image ready
+void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
+    disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+    }
+}
+
+// picture callback - raw image ready
+void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
+    disableMsgType(CAMERA_MSG_RAW_IMAGE);
+
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+    // Put the YUV version of the snapshot in the preview display.
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->postBuffer(offset);
+    }
+
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
+    }
+}
+
+// picture callback - compressed picture ready
+void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
+    disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
+    }
+}
+
+
+void CameraService::Client::handleGenericNotify(int32_t msgType,
+    int32_t ext1, int32_t ext2) {
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->notifyCallback(msgType, ext1, ext2);
+    }
+}
+
+void CameraService::Client::handleGenericData(int32_t msgType,
+    const sp<IMemory>& dataPtr) {
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(msgType, dataPtr);
+    }
+}
+
+void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
+    int32_t msgType, const sp<IMemory>& dataPtr) {
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+    }
+}
+
+void CameraService::Client::copyFrameAndPostCopiedFrame(
+        const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap,
+        size_t offset, size_t size) {
+    LOG2("copyFrameAndPostCopiedFrame");
+    // It is necessary to copy out of pmem before sending this to
+    // the callback. For efficiency, reuse the same MemoryHeapBase
+    // provided it's big enough. Don't allocate the memory or
+    // perform the copy if there's no callback.
+    // hold the preview lock while we grab a reference to the preview buffer
+    sp<MemoryHeapBase> previewBuffer;
+
+    if (mPreviewBuffer == 0) {
+        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+    } else if (size > mPreviewBuffer->virtualSize()) {
+        mPreviewBuffer.clear();
+        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+    }
+    if (mPreviewBuffer == 0) {
+        LOGE("failed to allocate space for preview buffer");
+        mLock.unlock();
+        return;
+    }
+    previewBuffer = mPreviewBuffer;
+
+    memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
+
+    sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
+    if (frame == 0) {
+        LOGE("failed to allocate space for frame callback");
+        mLock.unlock();
+        return;
+    }
+
+    mLock.unlock();
+    client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
+}
+
+// ----------------------------------------------------------------------------
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 60000;
+
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
+status_t CameraService::dump(int fd, const Vector<String16>& args) {
+    static const char* kDeadlockedString = "CameraService may be deadlocked\n";
+
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
+        snprintf(buffer, SIZE, "Permission Denial: "
+                "can't dump CameraService from pid=%d, uid=%d\n",
+                getCallingPid(),
+                getCallingUid());
+        result.append(buffer);
+        write(fd, result.string(), result.size());
+    } else {
+        bool locked = tryLock(mServiceLock);
+        // failed to lock - CameraService is probably deadlocked
+        if (!locked) {
+            String8 result(kDeadlockedString);
+            write(fd, result.string(), result.size());
+        }
+
+        bool hasClient = false;
+        for (int i = 0; i < mNumberOfCameras; i++) {
+            sp<Client> client = mClient[i].promote();
+            if (client == 0) continue;
+            hasClient = true;
+            sprintf(buffer, "Client[%d] (%p) PID: %d\n",
+                    i,
+                    client->getCameraClient()->asBinder().get(),
+                    client->mClientPid);
+            result.append(buffer);
+            write(fd, result.string(), result.size());
+            client->mHardware->dump(fd, args);
+        }
+        if (!hasClient) {
+            result.append("No camera client yet.\n");
+            write(fd, result.string(), result.size());
+        }
+
+        if (locked) mServiceLock.unlock();
+
+        // change logging level
+        int n = args.size();
+        for (int i = 0; i + 1 < n; i++) {
+            if (args[i] == String16("-v")) {
+                String8 levelStr(args[i+1]);
+                int level = atoi(levelStr.string());
+                sprintf(buffer, "Set Log Level to %d", level);
+                result.append(buffer);
+                setLogLevel(level);
+            }
+        }
+    }
+    return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
new file mode 100644
index 0000000..77ccf41
--- /dev/null
+++ b/services/camera/libcameraservice/CameraService.h
@@ -0,0 +1,198 @@
+/*
+**
+** Copyright (C) 2008, 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 ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+
+#include <binder/BinderService.h>
+
+#include <camera/ICameraService.h>
+#include <camera/CameraHardwareInterface.h>
+
+/* This needs to be increased if we can have more cameras */
+#define MAX_CAMERAS 2
+
+namespace android {
+
+class MemoryHeapBase;
+class MediaPlayer;
+
+class CameraService :
+    public BinderService<CameraService>,
+    public BnCameraService
+{
+    class Client;
+    friend class BinderService<CameraService>;
+public:
+    static char const* getServiceName() { return "media.camera"; }
+
+                        CameraService();
+    virtual             ~CameraService();
+
+    virtual int32_t     getNumberOfCameras();
+    virtual status_t    getCameraInfo(int cameraId,
+                                      struct CameraInfo* cameraInfo);
+    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId);
+    virtual void        removeClient(const sp<ICameraClient>& cameraClient);
+    virtual sp<Client>  getClientById(int cameraId);
+
+    virtual status_t    dump(int fd, const Vector<String16>& args);
+    virtual status_t    onTransact(uint32_t code, const Parcel& data,
+                                   Parcel* reply, uint32_t flags);
+
+    enum sound_kind {
+        SOUND_SHUTTER = 0,
+        SOUND_RECORDING = 1,
+        NUM_SOUNDS
+    };
+
+    void                loadSound();
+    void                playSound(sound_kind kind);
+    void                releaseSound();
+
+private:
+    Mutex               mServiceLock;
+    wp<Client>          mClient[MAX_CAMERAS];  // protected by mServiceLock
+    int                 mNumberOfCameras;
+
+    // atomics to record whether the hardware is allocated to some client.
+    volatile int32_t    mBusy[MAX_CAMERAS];
+    void                setCameraBusy(int cameraId);
+    void                setCameraFree(int cameraId);
+
+    // sounds
+    Mutex               mSoundLock;
+    sp<MediaPlayer>     mSoundPlayer[NUM_SOUNDS];
+    int                 mSoundRef;  // reference count (release all MediaPlayer when 0)
+
+    class Client : public BnCamera
+    {
+    public:
+        // ICamera interface (see ICamera for details)
+        virtual void            disconnect();
+        virtual status_t        connect(const sp<ICameraClient>& client);
+        virtual status_t        lock();
+        virtual status_t        unlock();
+        virtual status_t        setPreviewDisplay(const sp<ISurface>& surface);
+        virtual void            setPreviewCallbackFlag(int flag);
+        virtual status_t        startPreview();
+        virtual void            stopPreview();
+        virtual bool            previewEnabled();
+        virtual status_t        startRecording();
+        virtual void            stopRecording();
+        virtual bool            recordingEnabled();
+        virtual void            releaseRecordingFrame(const sp<IMemory>& mem);
+        virtual status_t        autoFocus();
+        virtual status_t        cancelAutoFocus();
+        virtual status_t        takePicture();
+        virtual status_t        setParameters(const String8& params);
+        virtual String8         getParameters() const;
+        virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+    private:
+        friend class CameraService;
+                                Client(const sp<CameraService>& cameraService,
+                                       const sp<ICameraClient>& cameraClient,
+                                       int cameraId,
+                                       int clientPid);
+                                ~Client();
+
+        // return our camera client
+        const sp<ICameraClient>&    getCameraClient() { return mCameraClient; }
+
+        // check whether the calling process matches mClientPid.
+        status_t                checkPid() const;
+        status_t                checkPidAndHardware() const;  // also check mHardware != 0
+
+        // these are internal functions used to set up preview buffers
+        status_t                registerPreviewBuffers();
+        status_t                setOverlay();
+
+        // camera operation mode
+        enum camera_mode {
+            CAMERA_PREVIEW_MODE   = 0,  // frame automatically released
+            CAMERA_RECORDING_MODE = 1,  // frame has to be explicitly released by releaseRecordingFrame()
+        };
+        // these are internal functions used for preview/recording
+        status_t                startCameraMode(camera_mode mode);
+        status_t                startPreviewMode();
+        status_t                startRecordingMode();
+
+        // these are static callback functions
+        static void             notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
+        static void             dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+        static void             dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+        // convert client from cookie
+        static sp<Client>       getClientFromCookie(void* user);
+        // handlers for messages
+        void                    handleShutter(image_rect_type *size);
+        void                    handlePreviewData(const sp<IMemory>& mem);
+        void                    handlePostview(const sp<IMemory>& mem);
+        void                    handleRawPicture(const sp<IMemory>& mem);
+        void                    handleCompressedPicture(const sp<IMemory>& mem);
+        void                    handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
+        void                    handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr);
+        void                    handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
+
+        void                    copyFrameAndPostCopiedFrame(
+                                    const sp<ICameraClient>& client,
+                                    const sp<IMemoryHeap>& heap,
+                                    size_t offset, size_t size);
+
+        // these are initialized in the constructor.
+        sp<CameraService>               mCameraService;  // immutable after constructor
+        sp<ICameraClient>               mCameraClient;
+        int                             mCameraId;       // immutable after constructor
+        pid_t                           mClientPid;
+        sp<CameraHardwareInterface>     mHardware;       // cleared after disconnect()
+        bool                            mUseOverlay;     // immutable after constructor
+        sp<OverlayRef>                  mOverlayRef;
+        int                             mOverlayW;
+        int                             mOverlayH;
+        int                             mPreviewCallbackFlag;
+        int                             mOrientation;
+
+        // Ensures atomicity among the public methods
+        mutable Mutex                   mLock;
+        sp<ISurface>                    mSurface;
+
+        // If the user want us to return a copy of the preview frame (instead
+        // of the original one), we allocate mPreviewBuffer and reuse it if possible.
+        sp<MemoryHeapBase>              mPreviewBuffer;
+
+        // We need to avoid the deadlock when the incoming command thread and
+        // the CameraHardwareInterface callback thread both want to grab mLock.
+        // An extra flag is used to tell the callback thread that it should stop
+        // trying to deliver the callback messages if the client is not
+        // interested in it anymore. For example, if the client is calling
+        // stopPreview(), the preview frame messages do not need to be delivered
+        // anymore.
+
+        // This function takes the same parameter as the enableMsgType() and
+        // disableMsgType() functions in CameraHardwareInterface.
+        void                    enableMsgType(int32_t msgType);
+        void                    disableMsgType(int32_t msgType);
+        volatile int32_t        mMsgEnabled;
+
+        // This function keeps trying to grab mLock, or give up if the message
+        // is found to be disabled. It returns true if mLock is grabbed.
+        bool                    lockIfMessageWanted(int32_t msgType);
+    };
+};
+
+} // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CannedJpeg.h b/services/camera/libcameraservice/CannedJpeg.h
new file mode 100644
index 0000000..b6266fb
--- /dev/null
+++ b/services/camera/libcameraservice/CannedJpeg.h
@@ -0,0 +1,734 @@
+const int kCannedJpegWidth = 320;
+const int kCannedJpegHeight = 240;
+const int kCannedJpegSize = 8733;
+
+const char kCannedJpeg[] = {
+  0xff,  0xd8,  0xff,  0xe0,  0x00,  0x10,  0x4a,  0x46,  0x49,  0x46,  0x00,  0x01,
+  0x01,  0x01,  0x00,  0x60,  0x00,  0x60,  0x00,  0x00,  0xff,  0xe1,  0x00,  0x66,
+  0x45,  0x78,  0x69,  0x66,  0x00,  0x00,  0x49,  0x49,  0x2a,  0x00,  0x08,  0x00,
+  0x00,  0x00,  0x04,  0x00,  0x1a,  0x01,  0x05,  0x00,  0x01,  0x00,  0x00,  0x00,
+  0x3e,  0x00,  0x00,  0x00,  0x1b,  0x01,  0x05,  0x00,  0x01,  0x00,  0x00,  0x00,
+  0x46,  0x00,  0x00,  0x00,  0x28,  0x01,  0x03,  0x00,  0x01,  0x00,  0x00,  0x00,
+  0x02,  0x00,  0x00,  0x00,  0x31,  0x01,  0x02,  0x00,  0x10,  0x00,  0x00,  0x00,
+  0x4e,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x60,  0x00,  0x00,  0x00,
+  0x01,  0x00,  0x00,  0x00,  0x60,  0x00,  0x00,  0x00,  0x01,  0x00,  0x00,  0x00,
+  0x50,  0x61,  0x69,  0x6e,  0x74,  0x2e,  0x4e,  0x45,  0x54,  0x20,  0x76,  0x33,
+  0x2e,  0x33,  0x36,  0x00,  0xff,  0xdb,  0x00,  0x43,  0x00,  0x03,  0x02,  0x02,
+  0x03,  0x02,  0x02,  0x03,  0x03,  0x03,  0x03,  0x04,  0x03,  0x03,  0x04,  0x05,
+  0x08,  0x05,  0x05,  0x04,  0x04,  0x05,  0x0a,  0x07,  0x07,  0x06,  0x08,  0x0c,
+  0x0a,  0x0c,  0x0c,  0x0b,  0x0a,  0x0b,  0x0b,  0x0d,  0x0e,  0x12,  0x10,  0x0d,
+  0x0e,  0x11,  0x0e,  0x0b,  0x0b,  0x10,  0x16,  0x10,  0x11,  0x13,  0x14,  0x15,
+  0x15,  0x15,  0x0c,  0x0f,  0x17,  0x18,  0x16,  0x14,  0x18,  0x12,  0x14,  0x15,
+  0x14,  0xff,  0xdb,  0x00,  0x43,  0x01,  0x03,  0x04,  0x04,  0x05,  0x04,  0x05,
+  0x09,  0x05,  0x05,  0x09,  0x14,  0x0d,  0x0b,  0x0d,  0x14,  0x14,  0x14,  0x14,
+  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,
+  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,
+  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,
+  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0xff,  0xc0,
+  0x00,  0x11,  0x08,  0x00,  0xf0,  0x01,  0x40,  0x03,  0x01,  0x22,  0x00,  0x02,
+  0x11,  0x01,  0x03,  0x11,  0x01,  0xff,  0xc4,  0x00,  0x1f,  0x00,  0x00,  0x01,
+  0x05,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x01,  0x02,  0x03,  0x04,  0x05,  0x06,  0x07,  0x08,  0x09,
+  0x0a,  0x0b,  0xff,  0xc4,  0x00,  0xb5,  0x10,  0x00,  0x02,  0x01,  0x03,  0x03,
+  0x02,  0x04,  0x03,  0x05,  0x05,  0x04,  0x04,  0x00,  0x00,  0x01,  0x7d,  0x01,
+  0x02,  0x03,  0x00,  0x04,  0x11,  0x05,  0x12,  0x21,  0x31,  0x41,  0x06,  0x13,
+  0x51,  0x61,  0x07,  0x22,  0x71,  0x14,  0x32,  0x81,  0x91,  0xa1,  0x08,  0x23,
+  0x42,  0xb1,  0xc1,  0x15,  0x52,  0xd1,  0xf0,  0x24,  0x33,  0x62,  0x72,  0x82,
+  0x09,  0x0a,  0x16,  0x17,  0x18,  0x19,  0x1a,  0x25,  0x26,  0x27,  0x28,  0x29,
+  0x2a,  0x34,  0x35,  0x36,  0x37,  0x38,  0x39,  0x3a,  0x43,  0x44,  0x45,  0x46,
+  0x47,  0x48,  0x49,  0x4a,  0x53,  0x54,  0x55,  0x56,  0x57,  0x58,  0x59,  0x5a,
+  0x63,  0x64,  0x65,  0x66,  0x67,  0x68,  0x69,  0x6a,  0x73,  0x74,  0x75,  0x76,
+  0x77,  0x78,  0x79,  0x7a,  0x83,  0x84,  0x85,  0x86,  0x87,  0x88,  0x89,  0x8a,
+  0x92,  0x93,  0x94,  0x95,  0x96,  0x97,  0x98,  0x99,  0x9a,  0xa2,  0xa3,  0xa4,
+  0xa5,  0xa6,  0xa7,  0xa8,  0xa9,  0xaa,  0xb2,  0xb3,  0xb4,  0xb5,  0xb6,  0xb7,
+  0xb8,  0xb9,  0xba,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,  0xc7,  0xc8,  0xc9,  0xca,
+  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,  0xd7,  0xd8,  0xd9,  0xda,  0xe1,  0xe2,  0xe3,
+  0xe4,  0xe5,  0xe6,  0xe7,  0xe8,  0xe9,  0xea,  0xf1,  0xf2,  0xf3,  0xf4,  0xf5,
+  0xf6,  0xf7,  0xf8,  0xf9,  0xfa,  0xff,  0xc4,  0x00,  0x1f,  0x01,  0x00,  0x03,
+  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x00,  0x00,  0x00,
+  0x00,  0x00,  0x00,  0x01,  0x02,  0x03,  0x04,  0x05,  0x06,  0x07,  0x08,  0x09,
+  0x0a,  0x0b,  0xff,  0xc4,  0x00,  0xb5,  0x11,  0x00,  0x02,  0x01,  0x02,  0x04,
+  0x04,  0x03,  0x04,  0x07,  0x05,  0x04,  0x04,  0x00,  0x01,  0x02,  0x77,  0x00,
+  0x01,  0x02,  0x03,  0x11,  0x04,  0x05,  0x21,  0x31,  0x06,  0x12,  0x41,  0x51,
+  0x07,  0x61,  0x71,  0x13,  0x22,  0x32,  0x81,  0x08,  0x14,  0x42,  0x91,  0xa1,
+  0xb1,  0xc1,  0x09,  0x23,  0x33,  0x52,  0xf0,  0x15,  0x62,  0x72,  0xd1,  0x0a,
+  0x16,  0x24,  0x34,  0xe1,  0x25,  0xf1,  0x17,  0x18,  0x19,  0x1a,  0x26,  0x27,
+  0x28,  0x29,  0x2a,  0x35,  0x36,  0x37,  0x38,  0x39,  0x3a,  0x43,  0x44,  0x45,
+  0x46,  0x47,  0x48,  0x49,  0x4a,  0x53,  0x54,  0x55,  0x56,  0x57,  0x58,  0x59,
+  0x5a,  0x63,  0x64,  0x65,  0x66,  0x67,  0x68,  0x69,  0x6a,  0x73,  0x74,  0x75,
+  0x76,  0x77,  0x78,  0x79,  0x7a,  0x82,  0x83,  0x84,  0x85,  0x86,  0x87,  0x88,
+  0x89,  0x8a,  0x92,  0x93,  0x94,  0x95,  0x96,  0x97,  0x98,  0x99,  0x9a,  0xa2,
+  0xa3,  0xa4,  0xa5,  0xa6,  0xa7,  0xa8,  0xa9,  0xaa,  0xb2,  0xb3,  0xb4,  0xb5,
+  0xb6,  0xb7,  0xb8,  0xb9,  0xba,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,  0xc7,  0xc8,
+  0xc9,  0xca,  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,  0xd7,  0xd8,  0xd9,  0xda,  0xe2,
+  0xe3,  0xe4,  0xe5,  0xe6,  0xe7,  0xe8,  0xe9,  0xea,  0xf2,  0xf3,  0xf4,  0xf5,
+  0xf6,  0xf7,  0xf8,  0xf9,  0xfa,  0xff,  0xda,  0x00,  0x0c,  0x03,  0x01,  0x00,
+  0x02,  0x11,  0x03,  0x11,  0x00,  0x3f,  0x00,  0xf9,  0xd2,  0xa3,  0x95,  0xbb,
+  0x54,  0x84,  0xe0,  0x66,  0xa0,  0x27,  0x27,  0x35,  0xed,  0x9e,  0x50,  0x95,
+  0x2c,  0x4b,  0xc6,  0x6a,  0x35,  0x1b,  0x8e,  0x2a,  0x70,  0x30,  0x28,  0x00,
+  0xa8,  0xe5,  0x6e,  0x71,  0x52,  0x31,  0xda,  0x33,  0x50,  0x13,  0x93,  0x40,
+  0x09,  0x52,  0xc6,  0xb8,  0x19,  0xf5,  0xa6,  0x2a,  0xee,  0x6c,  0x54,  0xd4,
+  0x00,  0x54,  0x52,  0x36,  0x5b,  0x1e,  0x95,  0x23,  0xb6,  0xd5,  0xcd,  0x41,
+  0x40,  0x05,  0x4c,  0x8b,  0xb5,  0x7d,  0xea,  0x34,  0x5d,  0xcd,  0xed,  0x53,
+  0x50,  0x01,  0x50,  0xbb,  0x6e,  0x6f,  0x6a,  0x91,  0xdb,  0x6a,  0xfb,  0xd4,
+  0x34,  0x00,  0x54,  0xe8,  0xbb,  0x57,  0x15,  0x1c,  0x6b,  0x96,  0xcf,  0xa5,
+  0x4b,  0x40,  0x05,  0x42,  0xcd,  0xb9,  0xb3,  0x4f,  0x91,  0xb0,  0x31,  0xeb,
+  0x51,  0x50,  0x02,  0x81,  0x93,  0x53,  0xa8,  0xda,  0x31,  0x51,  0xc4,  0xbc,
+  0xe6,  0xa4,  0xa0,  0x00,  0x9c,  0x0a,  0x81,  0x8e,  0xe3,  0x9a,  0x92,  0x56,
+  0xe3,  0x15,  0x15,  0x00,  0x28,  0x19,  0x38,  0xa9,  0xc0,  0xc0,  0xc5,  0x47,
+  0x12,  0xf7,  0xa9,  0x28,  0x00,  0x27,  0x00,  0x9a,  0x80,  0x9c,  0x9c,  0xd3,
+  0xe5,  0x6e,  0xd5,  0x1d,  0x00,  0x2a,  0x8d,  0xc7,  0x15,  0x3d,  0x32,  0x35,
+  0xc0,  0xcf,  0xad,  0x3e,  0x80,  0x11,  0x8e,  0xd1,  0x9a,  0x82,  0x9f,  0x23,
+  0x64,  0xe3,  0xd2,  0x99,  0x40,  0x0e,  0x45,  0xdc,  0xde,  0xd5,  0x35,  0x36,
+  0x35,  0xc2,  0xfb,  0x9a,  0x75,  0x00,  0x35,  0xdb,  0x6a,  0xfb,  0xd4,  0x34,
+  0xe9,  0x1b,  0x73,  0x7b,  0x0a,  0x6d,  0x00,  0x3e,  0x35,  0xcb,  0x7b,  0x0a,
+  0x96,  0x91,  0x17,  0x6a,  0xd2,  0xd0,  0x03,  0x64,  0x6c,  0x2f,  0xb9,  0xa8,
+  0x69,  0xce,  0xdb,  0x9a,  0x9b,  0xd6,  0x80,  0x1f,  0x12,  0xe4,  0xe7,  0xd2,
+  0xa5,  0xa4,  0x51,  0xb4,  0x62,  0x97,  0xa5,  0x00,  0x67,  0xc9,  0xad,  0xd8,
+  0x91,  0x81,  0x72,  0x9f,  0x9d,  0x47,  0xfd,  0xb3,  0x65,  0xff,  0x00,  0x3f,
+  0x29,  0x5f,  0xa0,  0x1f,  0xf0,  0xe9,  0x6f,  0x09,  0x7f,  0xd0,  0xfb,  0xad,
+  0x7f,  0xe0,  0x24,  0x34,  0x7f,  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,
+  0xee,  0xb5,  0xff,  0x00,  0x80,  0x90,  0xd7,  0x3f,  0xb7,  0x87,  0x73,  0x6f,
+  0x63,  0x33,  0xe0,  0x28,  0xf5,  0x9b,  0x11,  0xc9,  0xb9,  0x4c,  0xfd,  0x69,
+  0xff,  0x00,  0xdb,  0x96,  0x1f,  0xf3,  0xf5,  0x1f,  0xe7,  0x5f,  0x7d,  0x7f,
+  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,  0xff,  0x00,  0x80,
+  0x90,  0xd1,  0xff,  0x00,  0x0e,  0x96,  0xf0,  0x97,  0xfd,  0x0f,  0xba,  0xd7,
+  0xfe,  0x02,  0x43,  0x47,  0xb7,  0x87,  0x70,  0xf6,  0x33,  0x3e,  0x02,  0x93,
+  0x5b,  0xb1,  0x3c,  0x0b,  0x94,  0xc7,  0xd6,  0x99,  0xfd,  0xb3,  0x65,  0xff,
+  0x00,  0x3f,  0x29,  0xf9,  0xd7,  0xe8,  0x07,  0xfc,  0x3a,  0x5b,  0xc2,  0x5f,
+  0xf4,  0x3e,  0xeb,  0x5f,  0xf8,  0x09,  0x0d,  0x1f,  0xf0,  0xe9,  0x6f,  0x09,
+  0x7f,  0xd0,  0xfb,  0xad,  0x7f,  0xe0,  0x24,  0x34,  0xbd,  0xbc,  0x03,  0xd8,
+  0xcc,  0xf8,  0x0e,  0x3d,  0x6a,  0xc1,  0x47,  0x37,  0x29,  0x9f,  0xad,  0x3b,
+  0xfb,  0x72,  0xc3,  0xfe,  0x7e,  0xa3,  0xfc,  0xeb,  0xef,  0xaf,  0xf8,  0x74,
+  0xb7,  0x84,  0xbf,  0xe8,  0x7d,  0xd6,  0xbf,  0xf0,  0x12,  0x1a,  0x3f,  0xe1,
+  0xd2,  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,  0x00,  0xc0,  0x48,
+  0x69,  0xfb,  0x78,  0x77,  0x0f,  0x63,  0x33,  0xe0,  0x19,  0x35,  0xbb,  0x26,
+  0x3c,  0x5c,  0xa6,  0x3e,  0xb4,  0xdf,  0xed,  0x9b,  0x2f,  0xf9,  0xf9,  0x4a,
+  0xfd,  0x00,  0xff,  0x00,  0x87,  0x4b,  0x78,  0x4b,  0xfe,  0x87,  0xdd,  0x6b,
+  0xff,  0x00,  0x01,  0x21,  0xa3,  0xfe,  0x1d,  0x2d,  0xe1,  0x2f,  0xfa,  0x1f,
+  0x75,  0xaf,  0xfc,  0x04,  0x86,  0x97,  0xb7,  0x80,  0x7b,  0x19,  0x9f,  0x01,
+  0xa6,  0xb5,  0x60,  0xab,  0xff,  0x00,  0x1f,  0x51,  0xe7,  0xeb,  0x4e,  0xfe,
+  0xdc,  0xb0,  0xff,  0x00,  0x9f,  0xa8,  0xff,  0x00,  0x3a,  0xfb,  0xeb,  0xfe,
+  0x1d,  0x2d,  0xe1,  0x2f,  0xfa,  0x1f,  0x75,  0xaf,  0xfc,  0x04,  0x86,  0x8f,
+  0xf8,  0x74,  0xb7,  0x84,  0xbf,  0xe8,  0x7d,  0xd6,  0xbf,  0xf0,  0x12,  0x1a,
+  0x3d,  0xbc,  0x03,  0xd8,  0xcc,  0xf8,  0x05,  0xf5,  0xab,  0x26,  0x6f,  0xf8,
+  0xf9,  0x4c,  0x7d,  0x69,  0xbf,  0xdb,  0x36,  0x5f,  0xf3,  0xf2,  0x9f,  0x9d,
+  0x7e,  0x80,  0x7f,  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,
+  0xff,  0x00,  0x80,  0x90,  0xd1,  0xff,  0x00,  0x0e,  0x96,  0xf0,  0x97,  0xfd,
+  0x0f,  0xba,  0xd7,  0xfe,  0x02,  0x43,  0x47,  0xb7,  0x80,  0x7b,  0x19,  0x9f,
+  0x02,  0x26,  0xb5,  0x60,  0xab,  0x8f,  0xb5,  0x47,  0xf9,  0xd2,  0xff,  0x00,
+  0x6e,  0x58,  0x7f,  0xcf,  0xd4,  0x7f,  0x9d,  0x7d,  0xf5,  0xff,  0x00,  0x0e,
+  0x96,  0xf0,  0x97,  0xfd,  0x0f,  0xba,  0xd7,  0xfe,  0x02,  0x43,  0x47,  0xfc,
+  0x3a,  0x5b,  0xc2,  0x5f,  0xf4,  0x3e,  0xeb,  0x5f,  0xf8,  0x09,  0x0d,  0x1e,
+  0xde,  0x01,  0xec,  0x66,  0x7c,  0x00,  0xda,  0xd5,  0x93,  0x1c,  0xfd,  0xa5,
+  0x3f,  0x3a,  0x4f,  0xed,  0x8b,  0x2f,  0xf9,  0xf9,  0x4f,  0xce,  0xbf,  0x40,
+  0x3f,  0xe1,  0xd2,  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,  0x00,
+  0xc0,  0x48,  0x68,  0xff,  0x00,  0x87,  0x4b,  0x78,  0x4b,  0xfe,  0x87,  0xdd,
+  0x6b,  0xff,  0x00,  0x01,  0x21,  0xa7,  0xed,  0xe1,  0xdc,  0x3d,  0x8c,  0xcf,
+  0x81,  0x57,  0x5a,  0xb0,  0x51,  0x8f,  0xb5,  0x47,  0xf9,  0xd1,  0xfd,  0xb9,
+  0x61,  0xff,  0x00,  0x3f,  0x49,  0xf9,  0xd7,  0xdf,  0x5f,  0xf0,  0xe9,  0x6f,
+  0x09,  0x7f,  0xd0,  0xfb,  0xad,  0x7f,  0xe0,  0x24,  0x34,  0x7f,  0xc3,  0xa5,
+  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,  0xff,  0x00,  0x80,  0x90,  0xd2,
+  0xf6,  0xf0,  0x0f,  0x63,  0x33,  0xe0,  0x06,  0xd6,  0xac,  0x98,  0xe7,  0xed,
+  0x29,  0xf9,  0xd2,  0x0d,  0x62,  0xcb,  0xfe,  0x7e,  0x53,  0xf3,  0xaf,  0xd0,
+  0x0f,  0xf8,  0x74,  0xb7,  0x84,  0xbf,  0xe8,  0x7d,  0xd6,  0xbf,  0xf0,  0x12,
+  0x1a,  0x3f,  0xe1,  0xd2,  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,
+  0x00,  0xc0,  0x48,  0x69,  0xfb,  0x78,  0x77,  0x0f,  0x63,  0x33,  0xe0,  0x51,
+  0xad,  0xd8,  0x01,  0x8f,  0xb5,  0x47,  0xf9,  0xd0,  0x75,  0xcb,  0x0c,  0x7f,
+  0xc7,  0xca,  0x7e,  0x75,  0xf7,  0xd7,  0xfc,  0x3a,  0x5b,  0xc2,  0x5f,  0xf4,
+  0x3e,  0xeb,  0x5f,  0xf8,  0x09,  0x0d,  0x1f,  0xf0,  0xe9,  0x6f,  0x09,  0x7f,
+  0xd0,  0xfb,  0xad,  0x7f,  0xe0,  0x24,  0x34,  0x7b,  0x78,  0x77,  0x0f,  0x63,
+  0x33,  0xf3,  0xfc,  0xeb,  0x36,  0x44,  0xff,  0x00,  0xc7,  0xca,  0x7e,  0x74,
+  0xa3,  0x58,  0xb1,  0x24,  0x66,  0xe5,  0x31,  0xf5,  0xaf,  0xbf,  0xff,  0x00,
+  0xe1,  0xd2,  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,  0x00,  0xc0,
+  0x48,  0x68,  0xff,  0x00,  0x87,  0x4b,  0x78,  0x4b,  0xfe,  0x87,  0xdd,  0x6b,
+  0xff,  0x00,  0x01,  0x21,  0xa3,  0xdb,  0xc3,  0xb8,  0x7b,  0x19,  0x9f,  0x02,
+  0xff,  0x00,  0x6d,  0xd8,  0x7f,  0xcf,  0xd4,  0x7f,  0x9d,  0x07,  0x5c,  0xb1,
+  0x03,  0x8b,  0x94,  0xcf,  0xd6,  0xbe,  0xfa,  0xff,  0x00,  0x87,  0x4b,  0x78,
+  0x4b,  0xfe,  0x87,  0xdd,  0x6b,  0xff,  0x00,  0x01,  0x21,  0xa3,  0xfe,  0x1d,
+  0x2d,  0xe1,  0x2f,  0xfa,  0x1f,  0x75,  0xaf,  0xfc,  0x04,  0x86,  0x8f,  0x6f,
+  0x0e,  0xe1,  0xec,  0x66,  0x7e,  0x7f,  0xff,  0x00,  0x6c,  0xd9,  0x7f,  0xcf,
+  0xca,  0x7e,  0x74,  0xab,  0xac,  0x58,  0xe7,  0x9b,  0x94,  0xc7,  0xd6,  0xbe,
+  0xff,  0x00,  0xff,  0x00,  0x87,  0x4b,  0x78,  0x4b,  0xfe,  0x87,  0xdd,  0x6b,
+  0xff,  0x00,  0x01,  0x21,  0xa3,  0xfe,  0x1d,  0x2d,  0xe1,  0x2f,  0xfa,  0x1f,
+  0x75,  0xaf,  0xfc,  0x04,  0x86,  0x8f,  0x6f,  0x0e,  0xe1,  0xec,  0x66,  0x7c,
+  0x0b,  0xfd,  0xb9,  0x61,  0xff,  0x00,  0x3f,  0x51,  0xfe,  0x74,  0x8d,  0xae,
+  0x58,  0xed,  0x38,  0xb9,  0x4c,  0xfd,  0x6b,  0xef,  0xbf,  0xf8,  0x74,  0xb7,
+  0x84,  0xbf,  0xe8,  0x7d,  0xd6,  0xbf,  0xf0,  0x12,  0x1a,  0x3f,  0xe1,  0xd2,
+  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,  0x00,  0xc0,  0x48,  0x68,
+  0xf6,  0xf0,  0xee,  0x1e,  0xc6,  0x67,  0xe7,  0xff,  0x00,  0xf6,  0xc5,  0x97,
+  0xfc,  0xfc,  0xa7,  0xe7,  0x4e,  0x4d,  0x62,  0xc7,  0x77,  0x37,  0x29,  0xf9,
+  0xd7,  0xdf,  0xdf,  0xf0,  0xe9,  0x6f,  0x09,  0x7f,  0xd0,  0xfb,  0xad,  0x7f,
+  0xe0,  0x24,  0x34,  0x7f,  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,
+  0xb5,  0xff,  0x00,  0x80,  0x90,  0xd1,  0xed,  0xe1,  0xdc,  0x3d,  0x8c,  0xcf,
+  0x81,  0x7f,  0xb7,  0x2c,  0x3f,  0xe7,  0xea,  0x3f,  0xce,  0x91,  0xf5,  0xcb,
+  0x1c,  0x71,  0x72,  0x9f,  0x9d,  0x7d,  0xf7,  0xff,  0x00,  0x0e,  0x96,  0xf0,
+  0x97,  0xfd,  0x0f,  0xba,  0xd7,  0xfe,  0x02,  0x43,  0x47,  0xfc,  0x3a,  0x5b,
+  0xc2,  0x5f,  0xf4,  0x3e,  0xeb,  0x5f,  0xf8,  0x09,  0x0d,  0x1e,  0xde,  0x1d,
+  0xc3,  0xd8,  0xcc,  0xfc,  0xff,  0x00,  0xfe,  0xd9,  0xb2,  0xff,  0x00,  0x9f,
+  0x94,  0xfc,  0xe9,  0xd1,  0xeb,  0x36,  0x20,  0xe4,  0xdc,  0xa7,  0xe7,  0x5f,
+  0x7f,  0x7f,  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,  0xff,
+  0x00,  0x80,  0x90,  0xd1,  0xff,  0x00,  0x0e,  0x96,  0xf0,  0x97,  0xfd,  0x0f,
+  0xba,  0xd7,  0xfe,  0x02,  0x43,  0x47,  0xb7,  0x87,  0x70,  0xf6,  0x33,  0x3e,
+  0x05,  0xfe,  0xdc,  0xb0,  0xff,  0x00,  0x9f,  0xa8,  0xff,  0x00,  0x3a,  0x6c,
+  0x9a,  0xdd,  0x89,  0x18,  0x17,  0x29,  0xf9,  0xd7,  0xdf,  0x9f,  0xf0,  0xe9,
+  0x6f,  0x09,  0x7f,  0xd0,  0xfb,  0xad,  0x7f,  0xe0,  0x24,  0x34,  0x7f,  0xc3,
+  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,  0xff,  0x00,  0x80,  0x90,
+  0xd1,  0xed,  0xe1,  0xdc,  0x3d,  0x8c,  0xcf,  0xbc,  0xa8,  0xa2,  0x8a,  0xf3,
+  0x0e,  0xf0,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,
+  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,
+  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0xa0,  0xbb,  0xbd,  0xb7,  0xb0,
+  0x88,  0x49,  0x73,  0x3c,  0x56,  0xf1,  0x96,  0x0a,  0x1e,  0x57,  0x0a,  0x09,
+  0x3d,  0x06,  0x4f,  0x7a,  0x9e,  0x95,  0xd3,  0x76,  0xea,  0x01,  0x45,  0x14,
+  0x53,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,  0x82,  0xda,  0xf6,  0xde,
+  0xf0,  0xca,  0x2d,  0xe7,  0x8a,  0x73,  0x13,  0x98,  0xe4,  0xf2,  0xdc,  0x36,
+  0xc6,  0x1d,  0x54,  0xe3,  0xa1,  0xf6,  0xa4,  0xda,  0x4e,  0xcc,  0x09,  0xe8,
+  0xa2,  0x8a,  0x60,  0x14,  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,
+  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,
+  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x02,  0xb8,
+  0x51,  0x45,  0x14,  0x05,  0xc2,  0x8a,  0x28,  0xa0,  0x2e,  0x14,  0x51,  0x45,
+  0x01,  0x70,  0xa2,  0x8a,  0x28,  0x18,  0x51,  0x45,  0x14,  0x0a,  0xe1,  0x45,
+  0x14,  0x50,  0x17,  0x0a,  0x28,  0xa2,  0x80,  0xb9,  0xca,  0xfc,  0x4a,  0xf0,
+  0x52,  0x78,  0xef,  0xc2,  0xb7,  0x1a,  0x76,  0xef,  0x2e,  0xe5,  0x4f,  0x9d,
+  0x6c,  0xe4,  0xe0,  0x09,  0x00,  0x38,  0xcf,  0xb1,  0xc9,  0x1f,  0x8e,  0x7b,
+  0x57,  0x3d,  0xf0,  0x5b,  0xc7,  0x53,  0x6b,  0xba,  0x6c,  0xda,  0x16,  0xaa,
+  0x5a,  0x3d,  0x73,  0x4a,  0xfd,  0xd4,  0x8b,  0x2f,  0xdf,  0x91,  0x01,  0xc0,
+  0x27,  0xdc,  0x1e,  0x0f,  0xe0,  0x7b,  0xd7,  0xa3,  0x5c,  0xdc,  0xc5,  0x67,
+  0x04,  0x93,  0xcf,  0x2a,  0x43,  0x0c,  0x60,  0xb3,  0xc9,  0x23,  0x05,  0x55,
+  0x1e,  0xa4,  0x9e,  0x95,  0xf3,  0x47,  0xc4,  0x8f,  0x1f,  0xe9,  0x36,  0xdf,
+  0x10,  0xed,  0x3c,  0x41,  0xe1,  0x39,  0x99,  0xaf,  0xa1,  0xe2,  0xea,  0x42,
+  0x98,  0x82,  0x72,  0x38,  0xe3,  0x90,  0x4e,  0x46,  0x41,  0xe9,  0x9c,  0x0c,
+  0x7a,  0xd7,  0xc4,  0x67,  0x98,  0x9a,  0x59,  0x3e,  0x26,  0x9e,  0x64,  0xa6,
+  0x93,  0x7e,  0xec,  0xe3,  0x7d,  0x65,  0x1e,  0xe9,  0x77,  0x8b,  0xd7,  0xd3,
+  0x4b,  0x99,  0x4d,  0xa8,  0xbe,  0x63,  0xe9,  0xca,  0x2b,  0xe4,  0x3d,  0x73,
+  0xe3,  0x3f,  0x8b,  0xb5,  0xc6,  0x6d,  0xfa,  0xb4,  0x96,  0x71,  0x9e,  0x91,
+  0x59,  0x0f,  0x28,  0x0f,  0xc4,  0x7c,  0xdf,  0x99,  0xae,  0x56,  0xe7,  0x5a,
+  0xd4,  0x6f,  0x18,  0xb5,  0xc5,  0xfd,  0xd4,  0xec,  0x7b,  0xc9,  0x33,  0x31,
+  0xfd,  0x4d,  0x78,  0x75,  0xf8,  0xfb,  0x0b,  0x07,  0x6a,  0x14,  0x65,  0x25,
+  0xe6,  0xd2,  0xff,  0x00,  0x32,  0x1d,  0x75,  0xd1,  0x1f,  0x73,  0x51,  0x5f,
+  0x0b,  0xdb,  0xea,  0xf7,  0xf6,  0xad,  0xba,  0x0b,  0xdb,  0x88,  0x58,  0x77,
+  0x8e,  0x56,  0x53,  0xfa,  0x1a,  0xe9,  0xf4,  0x5f,  0x8b,  0xfe,  0x2e,  0xd0,
+  0xd9,  0x7c,  0xad,  0x66,  0x7b,  0x84,  0x1f,  0xf2,  0xce,  0xec,  0xf9,  0xc0,
+  0xff,  0x00,  0xdf,  0x59,  0x23,  0xf0,  0x34,  0xa8,  0x71,  0xf6,  0x1a,  0x4e,
+  0xd5,  0xa8,  0x4a,  0x2b,  0xc9,  0xa7,  0xfe,  0x40,  0xab,  0xae,  0xa8,  0xfa,
+  0x13,  0xe2,  0xff,  0x00,  0x8f,  0xcf,  0x82,  0xfc,  0x3e,  0x21,  0xb3,  0x6d,
+  0xda,  0xcd,  0xfe,  0x62,  0xb5,  0x45,  0xe5,  0x97,  0xb1,  0x7c,  0x7b,  0x67,
+  0x8f,  0x72,  0x3d,  0xea,  0x5f,  0x84,  0x7e,  0x05,  0x6f,  0x04,  0x78,  0x60,
+  0x2d,  0xd1,  0x2d,  0xa9,  0xde,  0xb0,  0x9e,  0xe8,  0x93,  0x9d,  0xad,  0x8e,
+  0x17,  0xf0,  0x1d,  0x4f,  0xa9,  0x35,  0xe2,  0x5e,  0x13,  0xf8,  0x89,  0x61,
+  0xac,  0xfc,  0x49,  0x8f,  0xc4,  0x3e,  0x30,  0x76,  0xcc,  0x68,  0x16,  0xd8,
+  0x43,  0x19,  0x68,  0x61,  0x61,  0xd0,  0x91,  0x92,  0x40,  0x1c,  0x9e,  0x33,
+  0xc9,  0xcd,  0x7d,  0x3b,  0x63,  0x7f,  0x6d,  0xaa,  0x5a,  0x45,  0x75,  0x69,
+  0x3c,  0x77,  0x36,  0xd2,  0x8d,  0xc9,  0x2c,  0x4c,  0x19,  0x58,  0x7b,  0x11,
+  0x5e,  0xde,  0x4d,  0x8b,  0xa3,  0x9d,  0xe3,  0x2a,  0x66,  0x1c,  0xe9,  0xf2,
+  0x5e,  0x30,  0x8f,  0x58,  0xae,  0xb2,  0x6b,  0xbc,  0xbf,  0x05,  0xa1,  0x50,
+  0x6a,  0x6f,  0x98,  0xb1,  0x45,  0x14,  0x57,  0xdc,  0x9b,  0x5c,  0x28,  0xa2,
+  0x8a,  0x02,  0xe1,  0x45,  0x14,  0x50,  0x17,  0x0a,  0x28,  0xa2,  0x80,  0xb8,
+  0x51,  0x45,  0x14,  0x05,  0xc2,  0x8a,  0x28,  0xa0,  0x2e,  0x14,  0x51,  0x45,
+  0x01,  0x70,  0xa2,  0x8a,  0x28,  0x0b,  0x8d,  0xcd,  0x19,  0xa6,  0xe4,  0x51,
+  0x91,  0x55,  0x62,  0x47,  0x66,  0x8c,  0xd3,  0x72,  0x28,  0xc8,  0xa2,  0xc0,
+  0x3b,  0x34,  0x66,  0x9b,  0x91,  0x46,  0x45,  0x16,  0x01,  0xd9,  0xa3,  0x34,
+  0xdc,  0x8a,  0x32,  0x28,  0xb0,  0x0e,  0xcd,  0x19,  0xa6,  0xe4,  0x52,  0xe4,
+  0x51,  0x60,  0xb8,  0xb9,  0xa3,  0x34,  0xdc,  0x8a,  0x32,  0x28,  0xb0,  0x0e,
+  0xdd,  0x46,  0x69,  0xb9,  0x14,  0x64,  0x51,  0x60,  0x1d,  0x9a,  0xa7,  0xac,
+  0x6b,  0x16,  0x9a,  0x0e,  0x9b,  0x71,  0xa8,  0x5f,  0x4c,  0x20,  0xb5,  0x81,
+  0x37,  0xbb,  0x9e,  0xc3,  0xd0,  0x7a,  0x93,  0xd0,  0x0a,  0xb5,  0x91,  0x5f,
+  0x39,  0xfe,  0xd1,  0x1e,  0x37,  0x7d,  0x4b,  0x5a,  0x4f,  0x0f,  0x5b,  0x48,
+  0x45,  0xa5,  0x96,  0x1e,  0x70,  0xa7,  0xef,  0xca,  0x46,  0x40,  0x3f,  0xee,
+  0x83,  0xf9,  0x93,  0xe9,  0x5e,  0x06,  0x79,  0x9a,  0xc3,  0x27,  0xc1,  0x4b,
+  0x12,  0xd5,  0xe5,  0xb4,  0x57,  0x76,  0xff,  0x00,  0xab,  0xbf,  0x24,  0x44,
+  0xe5,  0xca,  0xae,  0x72,  0xbf,  0x12,  0xbe,  0x2a,  0xea,  0x3e,  0x3e,  0xbd,
+  0x78,  0xd5,  0x9e,  0xd3,  0x48,  0x46,  0xfd,  0xd5,  0xa2,  0x9f,  0xbd,  0xe8,
+  0xcf,  0xea,  0x7f,  0x41,  0xdb,  0xd4,  0xc3,  0xe0,  0x5f,  0x85,  0x1a,  0xd7,
+  0x8f,  0xed,  0xe6,  0xb9,  0xb1,  0xf2,  0x2d,  0xed,  0x22,  0x6d,  0x86,  0x7b,
+  0x96,  0x21,  0x59,  0xb1,  0x9c,  0x0c,  0x02,  0x4f,  0x51,  0xf9,  0xd7,  0x19,
+  0x5e,  0xcd,  0xf0,  0x73,  0xe3,  0x16,  0x97,  0xe1,  0x0d,  0x06,  0x4d,  0x23,
+  0x57,  0x49,  0x63,  0x44,  0x95,  0xa5,  0x86,  0x78,  0x53,  0x78,  0x21,  0xba,
+  0xab,  0x0e,  0xb9,  0xcf,  0x7f,  0x7f,  0x6a,  0xfc,  0x1b,  0x2e,  0xa9,  0x87,
+  0xcd,  0xb3,  0x2f,  0x69,  0x9c,  0xd5,  0x6a,  0x2e,  0xfa,  0xde,  0xda,  0xf4,
+  0x57,  0xe8,  0xbf,  0xe1,  0x8e,  0x48,  0xda,  0x52,  0xf7,  0x8f,  0x30,  0xf1,
+  0x57,  0x85,  0x75,  0x0f,  0x06,  0xeb,  0x12,  0x69,  0xba,  0x94,  0x42,  0x3b,
+  0x84,  0x01,  0x83,  0x21,  0xca,  0xba,  0x9e,  0x8c,  0xa7,  0xb8,  0xac,  0x8a,
+  0xed,  0x3e,  0x2c,  0xf8,  0xee,  0x1f,  0x1f,  0xf8,  0x9c,  0x5e,  0xda,  0xc2,
+  0xf0,  0xda,  0x41,  0x08,  0x82,  0x2f,  0x33,  0x01,  0xd8,  0x02,  0x49,  0x63,
+  0xe9,  0xc9,  0x3c,  0x57,  0x17,  0x5e,  0x26,  0x3e,  0x9e,  0x1e,  0x96,  0x2a,
+  0xa4,  0x30,  0xb2,  0xe6,  0xa6,  0x9b,  0xb3,  0xee,  0x88,  0x76,  0xbe,  0x81,
+  0x5a,  0x1a,  0x06,  0x83,  0x7b,  0xe2,  0x7d,  0x5e,  0xdf,  0x4d,  0xd3,  0xe2,
+  0xf3,  0xae,  0xa7,  0x38,  0x55,  0xce,  0x00,  0x00,  0x64,  0x92,  0x7b,  0x00,
+  0x39,  0xac,  0xfa,  0xea,  0x3e,  0x1b,  0x78,  0xc1,  0x7c,  0x0d,  0xe2,  0xcb,
+  0x5d,  0x52,  0x58,  0x4c,  0xf6,  0xe1,  0x5a,  0x39,  0x51,  0x3e,  0xf6,  0xd6,
+  0x18,  0x24,  0x7b,  0x8e,  0x0d,  0x67,  0x83,  0x85,  0x1a,  0x98,  0x8a,  0x70,
+  0xc4,  0x4b,  0x96,  0x0d,  0xae,  0x67,  0xd9,  0x5f,  0x50,  0x56,  0xbe,  0xa6,
+  0x97,  0x8d,  0x7e,  0x0e,  0xeb,  0xde,  0x06,  0xd3,  0x17,  0x50,  0xbb,  0x36,
+  0xf7,  0x56,  0x99,  0x0b,  0x24,  0x96,  0xae,  0x4f,  0x96,  0x4f,  0x4d,  0xc0,
+  0x81,  0xc1,  0x3c,  0x66,  0xa9,  0xfc,  0x3e,  0xf8,  0x93,  0xaa,  0x78,  0x03,
+  0x50,  0x0f,  0x6c,  0xe6,  0x7b,  0x07,  0x6f,  0xdf,  0xd9,  0x3b,  0x7c,  0x8e,
+  0x3d,  0x47,  0xa3,  0x7b,  0xfe,  0x79,  0xaf,  0x45,  0xf8,  0xad,  0xf1,  0xb3,
+  0x47,  0xf1,  0x27,  0x85,  0x26,  0xd2,  0x34,  0x84,  0x9a,  0x67,  0xbb,  0x2b,
+  0xe6,  0xcb,  0x34,  0x7b,  0x04,  0x6a,  0x18,  0x36,  0x07,  0xa9,  0xc8,  0x1e,
+  0xd5,  0xe1,  0x95,  0xf4,  0x39,  0xab,  0xc2,  0x65,  0x79,  0x84,  0x67,  0x93,
+  0x55,  0x6d,  0x24,  0x9d,  0xd3,  0xbd,  0x9f,  0x55,  0x7e,  0xaa,  0xd6,  0xbe,
+  0xfb,  0xd8,  0xb9,  0x5a,  0x32,  0xf7,  0x59,  0xf6,  0xef,  0x86,  0xbc,  0x49,
+  0x63,  0xe2,  0xbd,  0x1a,  0xdf,  0x53,  0xd3,  0xe5,  0xf3,  0x2d,  0xe6,  0x1d,
+  0xfe,  0xf2,  0x1e,  0xea,  0xc3,  0xb1,  0x15,  0xa9,  0x9a,  0xf9,  0x7b,  0xe0,
+  0x27,  0x8d,  0xe4,  0xf0,  0xef,  0x8a,  0x53,  0x4a,  0x9e,  0x43,  0xfd,  0x9f,
+  0xa9,  0x30,  0x8f,  0x69,  0x3c,  0x24,  0xdf,  0xc0,  0xc3,  0xeb,  0xf7,  0x7f,
+  0x11,  0xe9,  0x5f,  0x4f,  0xe4,  0x57,  0xee,  0x3c,  0x3f,  0x9b,  0xc7,  0x39,
+  0xc1,  0x2a,  0xed,  0x5a,  0x6b,  0x49,  0x2f,  0x3f,  0xf2,  0x7b,  0xfe,  0x1d,
+  0x0e,  0xb8,  0x4f,  0x99,  0x5c,  0x76,  0x4d,  0x19,  0xa6,  0xe4,  0x51,  0x91,
+  0x5f,  0x4b,  0x62,  0xc7,  0x64,  0xd1,  0x9a,  0x6e,  0x45,  0x19,  0x14,  0x58,
+  0x2e,  0x3b,  0x34,  0x66,  0x9b,  0x91,  0x46,  0x45,  0x16,  0x0b,  0x8e,  0xcd,
+  0x19,  0xa6,  0xe4,  0x51,  0x91,  0x45,  0x80,  0x76,  0x68,  0xcd,  0x37,  0x34,
+  0x64,  0x51,  0x60,  0xb8,  0xec,  0xd1,  0x9a,  0x6e,  0x45,  0x19,  0x14,  0x58,
+  0x07,  0x64,  0xd1,  0x9a,  0x6e,  0x45,  0x19,  0x14,  0x58,  0x06,  0x6e,  0xa3,
+  0x75,  0x37,  0x34,  0x66,  0xae,  0xc4,  0x5c,  0x76,  0xea,  0x37,  0x53,  0x73,
+  0x46,  0x68,  0xb0,  0x5c,  0x76,  0xea,  0x37,  0x53,  0x73,  0x46,  0x68,  0xb0,
+  0x5c,  0x76,  0xea,  0x37,  0x53,  0x72,  0x28,  0xcd,  0x16,  0x0b,  0x8e,  0xdd,
+  0x46,  0xea,  0x6e,  0x68,  0xcd,  0x16,  0x0b,  0x8e,  0xdd,  0x46,  0xea,  0x6e,
+  0x68,  0xcd,  0x16,  0x0b,  0x8e,  0xdd,  0x46,  0xea,  0xc4,  0xf1,  0x57,  0x8c,
+  0x34,  0xaf,  0x06,  0x69,  0xff,  0x00,  0x6b,  0xd5,  0x2e,  0x44,  0x28,  0xc7,
+  0x08,  0x8a,  0x37,  0x3c,  0x87,  0xd1,  0x47,  0x7f,  0xe5,  0x5c,  0x0d,  0x9f,
+  0xed,  0x1f,  0xe1,  0xcb,  0x8b,  0xc1,  0x14,  0xd6,  0x97,  0xf6,  0xb0,  0x93,
+  0x81,  0x3b,  0xa2,  0xb0,  0x1e,  0xe4,  0x06,  0x27,  0xf2,  0xcd,  0x78,  0xf8,
+  0xac,  0xdf,  0x2f,  0xc0,  0xd4,  0x54,  0x71,  0x35,  0xa3,  0x19,  0x3e,  0x8d,
+  0xfe,  0x7d,  0xbe,  0x64,  0xb9,  0x25,  0xb9,  0xeb,  0x05,  0xf6,  0x82,  0x4f,
+  0x41,  0x5f,  0x10,  0xeb,  0x7a,  0x93,  0xeb,  0x3a,  0xcd,  0xf5,  0xfc,  0x84,
+  0x97,  0xb9,  0x9d,  0xe6,  0x39,  0xff,  0x00,  0x69,  0x89,  0xfe,  0xb5,  0xf6,
+  0xad,  0x8e,  0xa1,  0x6b,  0xab,  0x58,  0xc5,  0x75,  0x69,  0x34,  0x77,  0x36,
+  0xb3,  0x2e,  0xe4,  0x91,  0x0e,  0x55,  0x85,  0x78,  0x5f,  0xfc,  0x2d,  0x5f,
+  0x87,  0x3f,  0xf4,  0x25,  0x27,  0xfe,  0x00,  0xdb,  0xff,  0x00,  0x8d,  0x7c,
+  0x67,  0x18,  0xe1,  0xa8,  0x63,  0x61,  0x87,  0x55,  0x31,  0x31,  0xa7,  0x1f,
+  0x79,  0xab,  0xdd,  0xf3,  0x7c,  0x3a,  0xab,  0x76,  0xfd,  0x4c,  0xea,  0x59,
+  0xdb,  0x53,  0xc4,  0x68,  0xaf,  0x6e,  0xff,  0x00,  0x85,  0xab,  0xf0,  0xe7,
+  0xfe,  0x84,  0xa4,  0xff,  0x00,  0xc0,  0x1b,  0x7f,  0xf1,  0xa3,  0xfe,  0x16,
+  0xaf,  0xc3,  0x9f,  0xfa,  0x12,  0x93,  0xff,  0x00,  0x00,  0x6d,  0xff,  0x00,
+  0xc6,  0xbf,  0x33,  0xfe,  0xc5,  0xc0,  0xff,  0x00,  0xd0,  0x7c,  0x3e,  0xe9,
+  0x7f,  0x91,  0x8f,  0x2a,  0xee,  0x78,  0x8d,  0x15,  0xed,  0xdf,  0xf0,  0xb5,
+  0x7e,  0x1c,  0xff,  0x00,  0xd0,  0x94,  0x9f,  0xf8,  0x03,  0x6f,  0xfe,  0x34,
+  0x7f,  0xc2,  0xd5,  0xf8,  0x73,  0xff,  0x00,  0x42,  0x52,  0x7f,  0xe0,  0x0d,
+  0xbf,  0xf8,  0xd1,  0xfd,  0x8b,  0x81,  0xff,  0x00,  0xa0,  0xf8,  0x7d,  0xd2,
+  0xff,  0x00,  0x20,  0xe5,  0x5d,  0xcf,  0x11,  0xa2,  0xbd,  0xbb,  0xfe,  0x16,
+  0xaf,  0xc3,  0x9f,  0xfa,  0x12,  0x93,  0xff,  0x00,  0x00,  0x6d,  0xff,  0x00,
+  0xc6,  0x8f,  0xf8,  0x5a,  0xbf,  0x0e,  0x7f,  0xe8,  0x4a,  0x4f,  0xfc,  0x01,
+  0xb7,  0xff,  0x00,  0x1a,  0x3f,  0xb1,  0x70,  0x3f,  0xf4,  0x1f,  0x0f,  0xba,
+  0x5f,  0xe4,  0x1c,  0xab,  0xb9,  0xe2,  0x34,  0x57,  0xb7,  0x7f,  0xc2,  0xd5,
+  0xf8,  0x73,  0xff,  0x00,  0x42,  0x52,  0x7f,  0xe0,  0x0d,  0xbf,  0xf8,  0xd1,
+  0xff,  0x00,  0x0b,  0x57,  0xe1,  0xcf,  0xfd,  0x09,  0x49,  0xff,  0x00,  0x80,
+  0x36,  0xff,  0x00,  0xe3,  0x47,  0xf6,  0x2e,  0x07,  0xfe,  0x83,  0xe1,  0xf7,
+  0x4b,  0xfc,  0x83,  0x95,  0x77,  0x3c,  0x52,  0x09,  0xde,  0xda,  0x78,  0xe6,
+  0x89,  0x8a,  0x49,  0x1b,  0x07,  0x56,  0x1d,  0x41,  0x07,  0x20,  0xd7,  0xdb,
+  0xfa,  0x5d,  0xf0,  0xd4,  0x74,  0xdb,  0x4b,  0xb0,  0x30,  0x27,  0x85,  0x25,
+  0x03,  0xfd,  0xe5,  0x07,  0xfa,  0xd7,  0x85,  0xff,  0x00,  0xc2,  0xd5,  0xf8,
+  0x73,  0xff,  0x00,  0x42,  0x52,  0x7f,  0xe0,  0x0d,  0xbf,  0xf8,  0xd7,  0xb6,
+  0x69,  0x1a,  0x95,  0xa5,  0xc7,  0x87,  0xec,  0xaf,  0xe1,  0x55,  0xb3,  0xb1,
+  0x7b,  0x54,  0x99,  0x11,  0xf0,  0x82,  0x28,  0xca,  0x02,  0x01,  0xec,  0x30,
+  0x3f,  0x0e,  0x2b,  0xf4,  0x7e,  0x0e,  0xc2,  0xd0,  0xc1,  0xce,  0xbc,  0x69,
+  0x62,  0x63,  0x51,  0x34,  0x9b,  0x4a,  0xfa,  0x5a,  0xfa,  0xeb,  0xea,  0x6d,
+  0x4e,  0xca,  0xfa,  0x9a,  0x5b,  0xa8,  0xdd,  0x5e,  0x57,  0xab,  0xfe,  0xd1,
+  0x3e,  0x1b,  0xd3,  0xaf,  0x1a,  0x0b,  0x68,  0x6e,  0xf5,  0x15,  0x53,  0x83,
+  0x34,  0x28,  0xaa,  0x87,  0xe9,  0xb8,  0x82,  0x7f,  0x2a,  0xeb,  0xbc,  0x1b,
+  0xf1,  0x07,  0x45,  0xf1,  0xcd,  0xbb,  0xbe,  0x99,  0x70,  0x7c,  0xe8,  0xc6,
+  0x64,  0xb6,  0x98,  0x6d,  0x91,  0x07,  0xa9,  0x1d,  0xc7,  0xb8,  0xc8,  0xaf,
+  0xb7,  0xc3,  0xe7,  0x19,  0x76,  0x2a,  0xb7,  0xd5,  0xe8,  0x56,  0x8c,  0xa7,
+  0xd9,  0x3f,  0xcb,  0xbf,  0xc8,  0xd1,  0x49,  0x3d,  0x2e,  0x74,  0xdb,  0xa8,
+  0xcd,  0x37,  0x34,  0x64,  0x57,  0xb2,  0x55,  0xc7,  0x6e,  0xa3,  0x75,  0x37,
+  0x34,  0x66,  0x8b,  0x05,  0xc7,  0x6e,  0xa3,  0x75,  0x37,  0x34,  0x66,  0x8b,
+  0x05,  0xc7,  0x6e,  0xa3,  0x75,  0x37,  0x34,  0x66,  0x8b,  0x05,  0xc7,  0x6e,
+  0xa3,  0x75,  0x37,  0x34,  0x64,  0x51,  0x60,  0xb8,  0xed,  0xd4,  0x6e,  0xa6,
+  0xe4,  0x51,  0x9a,  0x2c,  0x17,  0x1b,  0x9a,  0x33,  0x51,  0xee,  0xa3,  0x75,
+  0x55,  0x88,  0xb9,  0x26,  0x68,  0xcd,  0x47,  0xba,  0x8d,  0xd4,  0x58,  0x2e,
+  0x49,  0x9a,  0x33,  0x51,  0xee,  0xa3,  0x75,  0x16,  0x15,  0xc9,  0x32,  0x28,
+  0xa8,  0xf7,  0x51,  0xba,  0x8b,  0x0e,  0xe4,  0x99,  0xa3,  0x35,  0x1e,  0xea,
+  0x37,  0x51,  0x60,  0xb9,  0x26,  0x68,  0xcd,  0x47,  0xba,  0x8c,  0xd3,  0xb0,
+  0x5c,  0xf9,  0x7b,  0xe3,  0xb6,  0xaf,  0x3e,  0xa5,  0xf1,  0x0e,  0xf2,  0xde,
+  0x47,  0x26,  0x1b,  0x24,  0x48,  0x62,  0x4e,  0xc0,  0x15,  0x0c,  0x4f,  0xe2,
+  0x58,  0xfe,  0x95,  0xe7,  0x95,  0xda,  0x7c,  0x64,  0xff,  0x00,  0x92,  0x97,
+  0xad,  0xff,  0x00,  0xbf,  0x1f,  0xfe,  0x8a,  0x4a,  0xe2,  0xeb,  0xf9,  0x47,
+  0x3a,  0x9c,  0xaa,  0x66,  0x78,  0x99,  0x49,  0xdd,  0xf3,  0xcb,  0xf0,  0x6d,
+  0x23,  0x92,  0x5b,  0x9e,  0xf7,  0xfb,  0x34,  0xeb,  0x13,  0xcd,  0x67,  0xac,
+  0xe9,  0xb2,  0x39,  0x6b,  0x78,  0x1a,  0x39,  0xa2,  0x04,  0xfd,  0xd2,  0xdb,
+  0x83,  0x0f,  0xc7,  0x68,  0xfd,  0x6b,  0xc1,  0x2b,  0xda,  0xff,  0x00,  0x66,
+  0x73,  0x8b,  0xed,  0x7f,  0xfe,  0xb9,  0xc3,  0xfc,  0xde,  0xbc,  0x52,  0xbd,
+  0x8c,  0xd2,  0x72,  0x9e,  0x4b,  0x97,  0x39,  0x3b,  0xdb,  0xda,  0xaf,  0x92,
+  0x92,  0xb1,  0x4f,  0xe1,  0x41,  0x45,  0x14,  0x57,  0xc6,  0x90,  0x14,  0x51,
+  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x15,  0xef,
+  0x7f,  0x13,  0xf5,  0x89,  0xf4,  0xef,  0x82,  0xbe,  0x19,  0xb6,  0x81,  0xca,
+  0x0b,  0xc8,  0x2d,  0x62,  0x94,  0x83,  0xd5,  0x04,  0x3b,  0x88,  0xfc,  0x48,
+  0x15,  0xe0,  0x95,  0xed,  0x7f,  0x17,  0x0f,  0xfc,  0x5a,  0x5f,  0x05,  0xff,
+  0x00,  0xd7,  0x38,  0x3f,  0xf4,  0x45,  0x7d,  0x96,  0x47,  0x39,  0x43,  0x03,
+  0x98,  0x4a,  0x2e,  0xcf,  0x91,  0x7e,  0x32,  0xb3,  0xfc,  0x0a,  0x8e,  0xcc,
+  0xf1,  0x4a,  0xe9,  0xbe,  0x1a,  0x6a,  0xf3,  0xe8,  0xbe,  0x3a,  0xd1,  0x67,
+  0x81,  0xca,  0x99,  0x2e,  0x52,  0x07,  0x00,  0xfd,  0xe4,  0x76,  0x0a,  0xc0,
+  0xfe,  0x07,  0xf4,  0xae,  0x66,  0xb6,  0x3c,  0x1b,  0xff,  0x00,  0x23,  0x7e,
+  0x87,  0xff,  0x00,  0x5f,  0xd0,  0x7f,  0xe8,  0xc5,  0xaf,  0x9b,  0xc0,  0xce,
+  0x54,  0xf1,  0x54,  0xa7,  0x07,  0x66,  0xa4,  0xbf,  0x31,  0x2d,  0xcf,  0xb4,
+  0x33,  0x46,  0x6a,  0x3d,  0xd4,  0x6e,  0xaf,  0xeb,  0x9b,  0x1d,  0x57,  0x24,
+  0xcd,  0x19,  0xa8,  0xf7,  0x51,  0xba,  0x8b,  0x0e,  0xe4,  0x99,  0xa3,  0x35,
+  0x1e,  0xea,  0x37,  0x51,  0x60,  0xb9,  0x26,  0x68,  0xcd,  0x47,  0xba,  0x8d,
+  0xd4,  0x58,  0x2e,  0x49,  0x9a,  0x33,  0x51,  0xee,  0xa3,  0x75,  0x16,  0x15,
+  0xc9,  0x33,  0x46,  0x6a,  0x3d,  0xd4,  0x6e,  0xa2,  0xc3,  0xb8,  0xdd,  0xd4,
+  0x9b,  0xa9,  0xbb,  0xa8,  0xdd,  0x5a,  0x19,  0xdc,  0x7e,  0xea,  0x4d,  0xd4,
+  0xdd,  0xd4,  0x6e,  0xa0,  0x57,  0x1f,  0xba,  0x8d,  0xd4,  0xcd,  0xd4,  0x6e,
+  0xa0,  0x77,  0x1f,  0xba,  0x8d,  0xd4,  0xcd,  0xd4,  0x6e,  0xa4,  0x2b,  0x8f,
+  0xdd,  0x49,  0xba,  0x9b,  0xba,  0x8d,  0xd4,  0xc2,  0xe3,  0xb7,  0x52,  0xee,
+  0xa6,  0x6e,  0xa3,  0x75,  0x20,  0xb9,  0xf2,  0x9f,  0xc6,  0x3f,  0xf9,  0x29,
+  0x5a,  0xdf,  0xfb,  0xf1,  0xff,  0x00,  0xe8,  0xb4,  0xae,  0x32,  0xbb,  0x2f,
+  0x8c,  0x5c,  0xfc,  0x49,  0xd6,  0xff,  0x00,  0xdf,  0x8f,  0xff,  0x00,  0x45,
+  0xa5,  0x71,  0xb5,  0xfc,  0x99,  0x9c,  0x7f,  0xc8,  0xcb,  0x13,  0xfe,  0x39,
+  0xff,  0x00,  0xe9,  0x4c,  0xc1,  0xee,  0x7b,  0x57,  0xec,  0xd2,  0x71,  0x7d,
+  0xaf,  0x7f,  0xd7,  0x38,  0x7f,  0x9b,  0xd7,  0x8a,  0xd7,  0xb4,  0x7e,  0xcd,
+  0x67,  0x17,  0xda,  0xf7,  0xfd,  0x73,  0x87,  0xf9,  0xbd,  0x78,  0xbd,  0x7b,
+  0x19,  0x97,  0xfc,  0x89,  0x32,  0xef,  0xfb,  0x8b,  0xff,  0x00,  0xa5,  0x21,
+  0xbd,  0x90,  0x51,  0x45,  0x15,  0xf2,  0x02,  0x0a,  0x28,  0xa2,  0x80,  0x0a,
+  0x28,  0xa2,  0x80,  0x0a,  0x28,  0xa2,  0x80,  0x0a,  0xf6,  0xaf,  0x8b,  0x47,
+  0x3f,  0x09,  0x7c,  0x17,  0xff,  0x00,  0x5c,  0xe0,  0xff,  0x00,  0xd1,  0x15,
+  0xe2,  0xb5,  0xed,  0x1f,  0x16,  0x4f,  0xfc,  0x5a,  0x6f,  0x06,  0x7f,  0xd7,
+  0x38,  0x3f,  0xf4,  0x45,  0x7d,  0x7e,  0x4d,  0xff,  0x00,  0x22,  0xfc,  0xc3,
+  0xfc,  0x11,  0xff,  0x00,  0xd2,  0x90,  0xd6,  0xcc,  0xf1,  0x7a,  0xd8,  0xf0,
+  0x67,  0xfc,  0x8e,  0x1a,  0x17,  0xfd,  0x7f,  0xc1,  0xff,  0x00,  0xa3,  0x16,
+  0xb1,  0xeb,  0x63,  0xc1,  0xdf,  0xf2,  0x37,  0x68,  0x7f,  0xf5,  0xfd,  0x07,
+  0xfe,  0x8c,  0x5a,  0xf9,  0xbc,  0x27,  0xfb,  0xcd,  0x3f,  0xf1,  0x2f,  0xcc,
+  0x48,  0xfb,  0x2b,  0x75,  0x1b,  0xa9,  0x9b,  0xa8,  0xdd,  0x5f,  0xd8,  0x16,
+  0x37,  0xb8,  0xfd,  0xd4,  0x6e,  0xa6,  0x6e,  0xa3,  0x75,  0x20,  0xb8,  0xed,
+  0xd4,  0xbb,  0xa9,  0x9b,  0xa8,  0xdd,  0x4c,  0x2e,  0x3f,  0x75,  0x26,  0xea,
+  0x6e,  0xea,  0x37,  0x52,  0x0b,  0x8f,  0xdd,  0x49,  0xba,  0x9b,  0xba,  0x8d,
+  0xd4,  0xec,  0x3b,  0x8f,  0xdd,  0x49,  0xba,  0x9b,  0xba,  0x8d,  0xd4,  0x0a,
+  0xe4,  0x74,  0x53,  0x33,  0x4b,  0x93,  0x57,  0x63,  0x3b,  0x8e,  0xa2,  0x9b,
+  0x9a,  0x4c,  0xd1,  0x60,  0xb8,  0xfa,  0x29,  0x99,  0xa3,  0x34,  0x58,  0x2e,
+  0x3f,  0x34,  0x53,  0x33,  0x4b,  0x93,  0x45,  0x82,  0xe3,  0xa8,  0xcd,  0x33,
+  0x34,  0x66,  0x8b,  0x05,  0xc7,  0xd1,  0x4d,  0xc9,  0xa3,  0x26,  0x8b,  0x05,
+  0xcf,  0x96,  0x3e,  0x30,  0x7f,  0xc9,  0x48,  0xd6,  0xbf,  0xdf,  0x8f,  0xff,
+  0x00,  0x45,  0xa5,  0x71,  0xb5,  0xdd,  0xfc,  0x6c,  0xd3,  0xa6,  0xb1,  0xf8,
+  0x85,  0x7f,  0x2c,  0x8a,  0x44,  0x77,  0x4b,  0x1c,  0xd1,  0xb7,  0x66,  0x1b,
+  0x02,  0x9f,  0xd5,  0x4d,  0x70,  0x95,  0xfc,  0x97,  0x9d,  0x42,  0x50,  0xcc,
+  0xf1,  0x31,  0x92,  0xb7,  0xbf,  0x2f,  0xfd,  0x29,  0x90,  0x7b,  0x3f,  0xec,
+  0xdb,  0xff,  0x00,  0x1f,  0xba,  0xef,  0xfd,  0x73,  0x87,  0xf9,  0xbd,  0x78,
+  0xc5,  0x7b,  0x87,  0xec,  0xe3,  0xa7,  0x4d,  0x1c,  0x3a,  0xd5,  0xf3,  0x29,
+  0x58,  0x24,  0x31,  0xc2,  0x8d,  0xfd,  0xe2,  0x37,  0x16,  0xfc,  0xb2,  0x3f,
+  0x3a,  0xf0,  0xfa,  0xf6,  0x73,  0x58,  0x4a,  0x19,  0x26,  0x5b,  0xcc,  0xad,
+  0x7f,  0x6a,  0xff,  0x00,  0xf2,  0x64,  0x01,  0x45,  0x14,  0x57,  0xc6,  0x00,
+  0x51,  0x45,  0x14,  0x00,  0x51,  0x45,  0x14,  0x00,  0x51,  0x45,  0x14,  0x00,
+  0x57,  0xb3,  0xfc,  0x57,  0xff,  0x00,  0x92,  0x51,  0xe0,  0xdf,  0xfa,  0xe7,
+  0x07,  0xfe,  0x88,  0xaf,  0x18,  0xaf,  0x70,  0xf8,  0x9b,  0xa7,  0x4d,  0x79,
+  0xf0,  0x77,  0xc3,  0x37,  0x11,  0x29,  0x74,  0xb5,  0x8a,  0xd9,  0xe4,  0xc7,
+  0x65,  0x30,  0xed,  0xcf,  0xe6,  0x40,  0xfc,  0x6b,  0xec,  0xf2,  0x38,  0x4a,
+  0x78,  0x0c,  0xc1,  0x45,  0x5f,  0xdc,  0x5f,  0x84,  0xae,  0xc0,  0xf0,  0xfa,
+  0xd8,  0xf0,  0x6f,  0xfc,  0x8d,  0xfa,  0x1f,  0xfd,  0x7f,  0x41,  0xff,  0x00,
+  0xa3,  0x16,  0xb1,  0xeb,  0xa2,  0xf8,  0x79,  0xa7,  0x4d,  0xaa,  0x78,  0xdf,
+  0x45,  0x86,  0x15,  0x2c,  0xcb,  0x75,  0x1c,  0xad,  0x8e,  0xca,  0x8c,  0x18,
+  0x9f,  0xc8,  0x57,  0xcd,  0x60,  0x61,  0x29,  0xe2,  0xe9,  0x46,  0x2a,  0xed,
+  0xca,  0x3f,  0x9a,  0x03,  0xeb,  0x9c,  0xd1,  0x4c,  0xcd,  0x2e,  0x4d,  0x7f,
+  0x60,  0x58,  0xbb,  0x8e,  0xa2,  0x99,  0x9a,  0x33,  0x45,  0x82,  0xe3,  0xe8,
+  0xa6,  0x66,  0x8c,  0xd1,  0x60,  0xb8,  0xfa,  0x29,  0x99,  0xa5,  0xc9,  0xa2,
+  0xc1,  0x71,  0xd9,  0xa2,  0x9b,  0x93,  0x49,  0x9a,  0x2c,  0x17,  0x1f,  0x45,
+  0x33,  0x34,  0x66,  0x8b,  0x05,  0xc6,  0x6e,  0xa3,  0x75,  0x30,  0x90,  0x3a,
+  0x9c,  0x51,  0x9a,  0xd2,  0xc6,  0x57,  0x1f,  0xba,  0x8d,  0xd4,  0xda,  0x4c,
+  0xd1,  0x60,  0xb8,  0xfd,  0xd4,  0x6e,  0xa6,  0x02,  0x0f,  0x43,  0x9a,  0x37,
+  0x01,  0xdf,  0x14,  0x58,  0x2e,  0x3f,  0x75,  0x1b,  0xa9,  0xb4,  0x94,  0x58,
+  0x2e,  0x3f,  0x75,  0x1b,  0xa9,  0xb4,  0x80,  0x83,  0xd0,  0xe6,  0x8b,  0x05,
+  0xc7,  0xee,  0xa3,  0x75,  0x30,  0x90,  0x3a,  0x9c,  0x51,  0x9a,  0x2c,  0x17,
+  0x31,  0x3c,  0x5d,  0xe0,  0xcd,  0x2f,  0xc6,  0xb6,  0x2b,  0x6f,  0xa8,  0xc4,
+  0x4b,  0x26,  0x4c,  0x53,  0xc6,  0x71,  0x24,  0x64,  0xf5,  0xc1,  0xfe,  0x87,
+  0x8a,  0xe0,  0x6d,  0x3f,  0x67,  0x7d,  0x32,  0x2b,  0xb0,  0xf7,  0x1a,  0xad,
+  0xcc,  0xf6,  0xe0,  0xe7,  0xca,  0x58,  0xd5,  0x09,  0x1e,  0x85,  0xb2,  0x7f,
+  0x95,  0x7a,  0xd5,  0x25,  0x78,  0x38,  0xcc,  0x87,  0x2c,  0xcc,  0x2b,  0x2a,
+  0xf8,  0x9a,  0x2a,  0x52,  0xef,  0xaa,  0xfb,  0xec,  0xd5,  0xfe,  0x77,  0x0b,
+  0x95,  0xf4,  0xad,  0x32,  0xd3,  0x44,  0xb0,  0x86,  0xca,  0xc6,  0x05,  0xb7,
+  0xb6,  0x88,  0x61,  0x23,  0x4e,  0x83,  0xfc,  0x4f,  0xbd,  0x7c,  0x6b,  0x5f,
+  0x69,  0x57,  0xc5,  0xb5,  0xf9,  0x8f,  0x88,  0xb0,  0x8d,  0x38,  0xe0,  0xe1,
+  0x05,  0x64,  0xb9,  0xec,  0x97,  0xfd,  0xb8,  0x34,  0x14,  0x51,  0x45,  0x7e,
+  0x32,  0x30,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,
+  0x28,  0x00,  0xaf,  0xad,  0xfc,  0x2b,  0x04,  0x57,  0x9e,  0x06,  0xd1,  0xad,
+  0xe7,  0x8d,  0x66,  0x86,  0x4d,  0x3a,  0x04,  0x78,  0xdc,  0x65,  0x58,  0x18,
+  0xd7,  0x20,  0x8a,  0xf9,  0x22,  0xbe,  0xba,  0xf0,  0x67,  0xfc,  0x89,  0xfa,
+  0x17,  0xfd,  0x78,  0x41,  0xff,  0x00,  0xa2,  0xd6,  0xbf,  0x5c,  0xf0,  0xee,
+  0x2a,  0x58,  0x9c,  0x42,  0x7b,  0x72,  0xaf,  0xcc,  0x47,  0x05,  0xab,  0x7e,
+  0xcf,  0x7a,  0x4d,  0xdd,  0xdb,  0x4b,  0x65,  0xa8,  0x4f,  0x63,  0x13,  0x1c,
+  0xf9,  0x25,  0x04,  0x80,  0x7b,  0x02,  0x48,  0x3f,  0x9e,  0x6b,  0xaf,  0xf0,
+  0x57,  0xc3,  0xcd,  0x27,  0xc0,  0xd1,  0xb9,  0xb3,  0x47,  0x9a,  0xee,  0x41,
+  0xb6,  0x4b,  0xa9,  0xb0,  0x5c,  0x8f,  0x41,  0xe8,  0x3d,  0x87,  0xe3,  0x5d,
+  0x36,  0x69,  0x6b,  0xf5,  0x7c,  0x37,  0x0f,  0xe5,  0x78,  0x3a,  0xff,  0x00,
+  0x59,  0xa1,  0x41,  0x46,  0x7d,  0xf5,  0xd3,  0xd1,  0x6c,  0xbe,  0x49,  0x0a,
+  0xe3,  0xb7,  0x51,  0xba,  0x99,  0x9a,  0x03,  0x03,  0xde,  0xbd,  0xfb,  0x05,
+  0xc7,  0xee,  0xa3,  0x75,  0x30,  0x90,  0x06,  0x4f,  0x14,  0x51,  0x60,  0xb8,
+  0xfd,  0xd4,  0x6e,  0xa6,  0xd1,  0x45,  0x82,  0xe3,  0xb7,  0x51,  0xba,  0x98,
+  0x08,  0x3d,  0x0e,  0x68,  0x24,  0x0e,  0xf4,  0x58,  0x2e,  0x3f,  0x75,  0x1b,
+  0xa9,  0x94,  0xb4,  0x58,  0x2e,  0x3b,  0x75,  0x1b,  0xa9,  0x99,  0xa0,  0x10,
+  0x7a,  0x1a,  0x2c,  0x17,  0x31,  0x62,  0xbd,  0x91,  0x46,  0xf7,  0x90,  0x3e,
+  0xd3,  0xf7,  0x1b,  0xa9,  0xad,  0x58,  0xa5,  0x13,  0x46,  0xae,  0xbd,  0x08,
+  0xac,  0x3f,  0x38,  0xff,  0x00,  0x71,  0x3f,  0xef,  0x91,  0x56,  0x52,  0xf1,
+  0xe3,  0x48,  0x55,  0x42,  0x80,  0x7a,  0x80,  0x3d,  0xeb,  0xb2,  0x70,  0xbe,
+  0xc7,  0x9d,  0x4e,  0xaf,  0x2e,  0xec,  0xd6,  0xcd,  0x36,  0x59,  0x44,  0x31,
+  0xb3,  0xb7,  0x41,  0x49,  0xba,  0xb3,  0x1e,  0xf2,  0x49,  0x12,  0x65,  0x60,
+  0x08,  0x1d,  0x01,  0x1e,  0xf5,  0x84,  0x61,  0xcc,  0x75,  0x4e,  0xa7,  0x22,
+  0x1b,  0x2d,  0xec,  0x8c,  0x0b,  0xa4,  0x81,  0x37,  0x1f,  0xb8,  0xbd,  0x7e,
+  0xb4,  0xb1,  0x5e,  0xc8,  0xa0,  0x3b,  0xb8,  0x7d,  0xa7,  0xee,  0x37,  0x5f,
+  0xad,  0x57,  0xf3,  0x8f,  0xf7,  0x13,  0xfe,  0xf9,  0x14,  0x79,  0xc7,  0xfb,
+  0x89,  0xff,  0x00,  0x7c,  0x8a,  0xeb,  0xe5,  0x56,  0xb5,  0x8e,  0x0e,  0x77,
+  0x7b,  0xdc,  0xdd,  0x8e,  0x41,  0x2a,  0x2b,  0xaf,  0x42,  0x33,  0x4e,  0xac,
+  0xa8,  0xef,  0x1d,  0x3c,  0x85,  0x00,  0x05,  0x3d,  0x40,  0x1e,  0xe6,  0xb4,
+  0x77,  0x57,  0x24,  0xa3,  0xca,  0x77,  0xc2,  0x7c,  0xe8,  0x74,  0x92,  0x08,
+  0xd1,  0x99,  0x8f,  0x00,  0x66,  0xb2,  0xa5,  0xbd,  0x91,  0x81,  0x74,  0x70,
+  0x99,  0x38,  0xd8,  0x3a,  0xfd,  0x69,  0xd2,  0x5e,  0x3b,  0xf9,  0xea,  0x40,
+  0x2a,  0x3a,  0x02,  0x3d,  0xc5,  0x55,  0xf3,  0x8f,  0xf7,  0x13,  0xfe,  0xf9,
+  0x15,  0xbc,  0x21,  0x6d,  0xce,  0x6a,  0x95,  0x6f,  0xa2,  0x64,  0xf1,  0x5e,
+  0x48,  0xa3,  0x7b,  0x48,  0x1f,  0x69,  0xfb,  0x8d,  0xd4,  0xd6,  0xac,  0x52,
+  0x89,  0xa3,  0x57,  0x5e,  0x86,  0xb0,  0xfc,  0xe3,  0xfd,  0xc4,  0xff,  0x00,
+  0xbe,  0x45,  0x59,  0x4b,  0xc7,  0x8d,  0x61,  0x0a,  0x14,  0x03,  0xd4,  0x01,
+  0xef,  0x44,  0xe1,  0x7d,  0x85,  0x4e,  0xaf,  0x2e,  0xec,  0xd6,  0xcd,  0x15,
+  0x1e,  0xea,  0x5d,  0xd5,  0xcd,  0x63,  0xba,  0xe3,  0xeb,  0xc0,  0xbc,  0x71,
+  0xf0,  0x57,  0x55,  0x83,  0x57,  0x9e,  0xe7,  0x44,  0x85,  0x6f,  0x6c,  0xa6,
+  0x72,  0xe2,  0x25,  0x70,  0xaf,  0x16,  0x4e,  0x76,  0xe0,  0x91,  0x91,  0xe9,
+  0x8a,  0xf7,  0xad,  0xd4,  0x66,  0xbe,  0x7f,  0x39,  0xc8,  0xf0,  0x99,  0xe5,
+  0x18,  0xd2,  0xc4,  0xdd,  0x72,  0xbb,  0xa6,  0xb7,  0x5d,  0xfb,  0xef,  0xe8,
+  0x17,  0xb1,  0xf2,  0xc5,  0xff,  0x00,  0xc3,  0x5f,  0x12,  0xe9,  0x96,  0x53,
+  0x5d,  0xdd,  0x69,  0x52,  0x43,  0x6f,  0x0a,  0x97,  0x92,  0x42,  0xe8,  0x42,
+  0x81,  0xd4,  0xf0,  0x6b,  0x99,  0xaf,  0xaa,  0xfe,  0x21,  0x9c,  0xf8,  0x1f,
+  0x5c,  0xff,  0x00,  0xaf,  0x47,  0xfe,  0x55,  0xf2,  0xa5,  0x7e,  0x01,  0xc5,
+  0x59,  0x1e,  0x1f,  0x22,  0xc4,  0x53,  0xa3,  0x87,  0x93,  0x92,  0x94,  0x6f,
+  0xef,  0x5b,  0xbd,  0xba,  0x24,  0x5a,  0x77,  0x0a,  0xe9,  0xec,  0xbe,  0x19,
+  0xf8,  0x9b,  0x51,  0xb3,  0x86,  0xea,  0xdb,  0x49,  0x92,  0x5b,  0x79,  0x90,
+  0x49,  0x1b,  0x87,  0x40,  0x19,  0x48,  0xc8,  0x3d,  0x6b,  0x98,  0xaf,  0xac,
+  0x3c,  0x08,  0x71,  0xe0,  0xad,  0x0b,  0xfe,  0xbc,  0xa1,  0xff,  0x00,  0xd0,
+  0x05,  0x57,  0x0a,  0xe4,  0x58,  0x7c,  0xf6,  0xbd,  0x5a,  0x58,  0x89,  0x4a,
+  0x2a,  0x2a,  0xfe,  0xed,  0xbb,  0xdb,  0xaa,  0x60,  0xdd,  0x8f,  0x9e,  0xdb,
+  0xe1,  0x4f,  0x8a,  0xd1,  0x4b,  0x1d,  0x1a,  0x50,  0x00,  0xc9,  0x3e,  0x62,
+  0x7f,  0xf1,  0x55,  0xc9,  0xd7,  0xd9,  0x17,  0x4d,  0xfe,  0x8d,  0x37,  0xfb,
+  0x87,  0xf9,  0x57,  0xc6,  0xf5,  0xd1,  0xc5,  0x9c,  0x3d,  0x86,  0xc8,  0x5d,
+  0x05,  0x87,  0x9c,  0xa5,  0xcf,  0xcd,  0x7e,  0x6b,  0x74,  0xb6,  0xd6,  0x4b,
+  0xb8,  0x27,  0x70,  0xae,  0x87,  0x47,  0xf0,  0x07,  0x88,  0x35,  0xfb,  0x04,
+  0xbd,  0xb0,  0xd3,  0x64,  0xb9,  0xb5,  0x72,  0x42,  0xc8,  0xae,  0xa0,  0x12,
+  0x0e,  0x0f,  0x53,  0xeb,  0x5c,  0xf5,  0x7d,  0x27,  0xf0,  0x54,  0xe3,  0xe1,
+  0xed,  0x8f,  0xfd,  0x74,  0x97,  0xff,  0x00,  0x43,  0x35,  0xe7,  0x70,  0xbe,
+  0x4f,  0x43,  0x3c,  0xc6,  0xcb,  0x0d,  0x5e,  0x4d,  0x25,  0x16,  0xf4,  0xb5,
+  0xee,  0x9a,  0x5d,  0x53,  0xee,  0x0d,  0xd8,  0xf3,  0x1f,  0x0d,  0x7c,  0x12,
+  0xd7,  0xb5,  0x3d,  0x42,  0x31,  0xa9,  0x40,  0x34,  0xdb,  0x20,  0xc0,  0xc8,
+  0xee,  0xea,  0xce,  0x47,  0x70,  0xa0,  0x13,  0xcf,  0xb9,  0xe2,  0xbe,  0x87,
+  0xb7,  0x82,  0x3b,  0x4b,  0x78,  0xa0,  0x89,  0x42,  0x45,  0x12,  0x84,  0x45,
+  0x1d,  0x80,  0x18,  0x02,  0x97,  0x34,  0x9b,  0xab,  0xfa,  0x07,  0x25,  0xe1,
+  0xfc,  0x1e,  0x45,  0x09,  0x47,  0x0d,  0x76,  0xe5,  0xbb,  0x7a,  0xbd,  0x36,
+  0x5a,  0x24,  0xad,  0xf2,  0x22,  0xf7,  0x24,  0xcd,  0x19,  0xa8,  0xf7,  0x51,
+  0xba,  0xbe,  0x96,  0xc1,  0x71,  0xd2,  0x48,  0x22,  0x46,  0x76,  0xe0,  0x0e,
+  0x6b,  0x2a,  0x5b,  0xd9,  0x18,  0x17,  0x47,  0x11,  0xe4,  0xe3,  0x60,  0xeb,
+  0xf5,  0xa7,  0x49,  0x78,  0xef,  0xe7,  0xa9,  0x00,  0xa8,  0xe8,  0x08,  0xf7,
+  0x02,  0xaa,  0xf9,  0xc7,  0xfb,  0x89,  0xff,  0x00,  0x7c,  0x8a,  0xe9,  0x84,
+  0x2d,  0xb9,  0xc5,  0x56,  0xaf,  0x36,  0x89,  0x93,  0xc5,  0x7b,  0x22,  0x8d,
+  0xef,  0x20,  0x7d,  0xa7,  0xee,  0x37,  0x53,  0x5a,  0xd1,  0x4a,  0x26,  0x8d,
+  0x5d,  0x7a,  0x1a,  0xc2,  0xf3,  0x8f,  0xf7,  0x13,  0xfe,  0xf9,  0x15,  0x65,
+  0x2f,  0x1e,  0x34,  0x84,  0x28,  0x50,  0x09,  0xe4,  0x01,  0xef,  0x44,  0xe1,
+  0x7d,  0x85,  0x4e,  0xaf,  0x2e,  0xec,  0xd6,  0xa6,  0xcb,  0x28,  0x86,  0x36,
+  0x76,  0xe8,  0x29,  0x37,  0x56,  0x63,  0xde,  0x3c,  0x89,  0x30,  0x60,  0xa4,
+  0x0e,  0x80,  0x8f,  0x7a,  0xc2,  0x30,  0xe6,  0x3a,  0xa7,  0x53,  0x91,  0x0d,
+  0x96,  0xf6,  0x46,  0x05,  0xd2,  0x40,  0x9b,  0x8f,  0xdc,  0x5e,  0xa3,  0xde,
+  0x96,  0x2b,  0xd9,  0x14,  0x07,  0x77,  0x0f,  0xb4,  0xfd,  0xc6,  0xeb,  0xf5,
+  0xaa,  0xfe,  0x71,  0xfe,  0xe2,  0x7f,  0xdf,  0x22,  0x8f,  0x38,  0xff,  0x00,
+  0x71,  0x3f,  0xef,  0x91,  0x5d,  0x7c,  0xaa,  0xd6,  0xb1,  0xc1,  0xce,  0xef,
+  0x7b,  0x9b,  0xb1,  0xc8,  0x25,  0x45,  0x75,  0xe8,  0x46,  0x69,  0xd5,  0x95,
+  0x1d,  0xe3,  0xa0,  0x81,  0x46,  0x02,  0x9e,  0xa0,  0x0f,  0x72,  0x2b,  0x4b,
+  0x35,  0xc9,  0x28,  0xf2,  0x9d,  0xf0,  0xa9,  0xce,  0x85,  0x92,  0x41,  0x1a,
+  0x33,  0xb7,  0x40,  0x32,  0x6b,  0x2a,  0x5b,  0xd9,  0x1c,  0x17,  0x47,  0x09,
+  0x93,  0x8d,  0x83,  0xaf,  0xd6,  0x9d,  0x25,  0xe3,  0xbf,  0x9e,  0xa4,  0x02,
+  0xa3,  0xa0,  0x23,  0xdc,  0x55,  0x5f,  0x38,  0xff,  0x00,  0x71,  0x3f,  0xef,
+  0x91,  0x5b,  0xc2,  0x16,  0xdc,  0xe6,  0xa9,  0x57,  0x9b,  0x44,  0xc8,  0xea,
+  0x70,  0xa4,  0x88,  0x30,  0x09,  0xff,  0x00,  0xf5,  0xd3,  0x4d,  0xbb,  0x09,
+  0x84,  0x59,  0x1b,  0xbd,  0x7b,  0x56,  0x95,  0xb4,  0x66,  0x18,  0x42,  0x13,
+  0x92,  0x3d,  0x2a,  0xe5,  0x2b,  0x23,  0x2a,  0x70,  0x72,  0x6d,  0x32,  0x7a,
+  0xc8,  0x2a,  0x40,  0x9f,  0x20,  0x8f,  0xff,  0x00,  0x5d,  0x6a,  0xe6,  0xa3,
+  0xb9,  0x8c,  0xcf,  0x09,  0x40,  0x40,  0x27,  0xd6,  0xb1,  0x83,  0xe5,  0x3a,
+  0x6a,  0x47,  0x99,  0x5c,  0xc7,  0xa2,  0xa5,  0x5b,  0x76,  0x69,  0x8c,  0x59,
+  0x1b,  0xbf,  0x4a,  0x3e,  0xce,  0xde,  0x7f,  0x95,  0x91,  0xbb,  0xd7,  0xb5,
+  0x74,  0xdd,  0x1c,  0x3c,  0xac,  0x7a,  0xa9,  0x2d,  0x6f,  0x80,  0x7f,  0xcb,
+  0x1a,  0xd6,  0xa8,  0x6d,  0xe3,  0x30,  0xc2,  0xa8,  0x48,  0x24,  0x77,  0x15,
+  0x26,  0x6b,  0x9a,  0x6f,  0x99,  0x9d,  0xf4,  0xe3,  0xca,  0x8c,  0xb6,  0x52,
+  0x1a,  0xe3,  0x20,  0xff,  0x00,  0x96,  0x15,  0x5e,  0xb6,  0x2e,  0x23,  0x33,
+  0x44,  0xc8,  0x08,  0x04,  0xd6,  0x67,  0xd9,  0xdb,  0xcf,  0xf2,  0xb2,  0x37,
+  0x7a,  0xf6,  0xad,  0xa1,  0x24,  0xd1,  0xcb,  0x52,  0x0e,  0x2d,  0x58,  0x8a,
+  0xa7,  0x0a,  0x48,  0x83,  0x00,  0x9f,  0xff,  0x00,  0x5d,  0x34,  0xdb,  0xb2,
+  0xcc,  0x22,  0xc8,  0xdd,  0xeb,  0xda,  0xb4,  0xad,  0xa3,  0x30,  0xc2,  0xaa,
+  0x4e,  0x48,  0xf4,  0xa2,  0x52,  0xb2,  0x0a,  0x70,  0x72,  0x6d,  0x32,  0x7a,
+  0x29,  0xa4,  0xd1,  0x9a,  0xe5,  0xb1,  0xde,  0x3a,  0x8a,  0x6e,  0x73,  0x41,
+  0x34,  0x58,  0x0e,  0x7f,  0xe2,  0x1f,  0xfc,  0x88,  0xfa,  0xe7,  0xfd,  0x7a,
+  0xbf,  0xf2,  0xaf,  0x95,  0xab,  0xeb,  0x2f,  0x18,  0x58,  0x4b,  0xaa,  0xf8,
+  0x57,  0x56,  0xb4,  0x80,  0x6e,  0x9a,  0x6b,  0x69,  0x15,  0x17,  0xd5,  0xb6,
+  0x9c,  0x0f,  0xce,  0xbe,  0x4e,  0x65,  0x2a,  0x48,  0x20,  0x82,  0x38,  0x20,
+  0xf6,  0xaf,  0xc1,  0x7c,  0x46,  0x84,  0x96,  0x32,  0x84,  0xed,  0xa3,  0x8b,
+  0x5f,  0x73,  0xff,  0x00,  0x82,  0x8d,  0x20,  0x25,  0x7d,  0x5d,  0xe0,  0x5f,
+  0xf9,  0x12,  0xf4,  0x2f,  0xfa,  0xf2,  0x87,  0xff,  0x00,  0x40,  0x15,  0xf2,
+  0x9a,  0x23,  0x48,  0xea,  0x88,  0xa5,  0x9d,  0x8e,  0x02,  0x81,  0x92,  0x4d,
+  0x7d,  0x69,  0xe1,  0x8b,  0x19,  0x34,  0xbf,  0x0d,  0xe9,  0x76,  0x73,  0x71,
+  0x2c,  0x16,  0xd1,  0xc6,  0xe3,  0xd0,  0x85,  0x00,  0xd5,  0x78,  0x73,  0x09,
+  0x3c,  0x56,  0x22,  0x76,  0xd1,  0x45,  0x2f,  0xc7,  0xfe,  0x00,  0x4c,  0xd0,
+  0xba,  0xff,  0x00,  0x8f,  0x69,  0xbf,  0xdc,  0x3f,  0xca,  0xbe,  0x39,  0xaf,
+  0xb1,  0xe5,  0x5f,  0x32,  0x27,  0x4c,  0xe3,  0x72,  0x91,  0x9a,  0xf9,  0x03,
+  0x50,  0xb1,  0x9b,  0x4c,  0xbe,  0xb8,  0xb4,  0x9d,  0x0a,  0x4d,  0x04,  0x86,
+  0x37,  0x53,  0xd8,  0x83,  0x8a,  0xed,  0xf1,  0x22,  0x12,  0xff,  0x00,  0x65,
+  0x9d,  0xb4,  0xf7,  0xd7,  0xfe,  0x92,  0x10,  0x2b,  0xd7,  0xd2,  0x5f,  0x05,
+  0xbf,  0xe4,  0x9f,  0x58,  0xff,  0x00,  0xd7,  0x49,  0x7f,  0xf4,  0x33,  0x5f,
+  0x36,  0xd7,  0xd3,  0x9f,  0x0a,  0x74,  0xe9,  0xb4,  0xbf,  0x01,  0xe9,  0x91,
+  0x4e,  0xa5,  0x24,  0x75,  0x69,  0x76,  0x9e,  0xa0,  0x33,  0x12,  0x3f,  0x42,
+  0x2b,  0xc3,  0xf0,  0xf6,  0x12,  0x96,  0x69,  0x52,  0x49,  0x68,  0xa0,  0xff,
+  0x00,  0x19,  0x44,  0x72,  0xd8,  0xeb,  0xe8,  0xa6,  0xe6,  0x8c,  0xd7,  0xf4,
+  0x3d,  0x8c,  0x87,  0x51,  0x4d,  0xcd,  0x19,  0xa2,  0xc0,  0x65,  0xb2,  0x90,
+  0xd7,  0x19,  0x04,  0x7f,  0xfb,  0x42,  0xab,  0xd6,  0xc5,  0xc4,  0x66,  0x68,
+  0x59,  0x07,  0x04,  0xfa,  0xd6,  0x67,  0xd9,  0xdb,  0xcf,  0xf2,  0xb2,  0x37,
+  0x7a,  0xf6,  0xae,  0xa8,  0x4a,  0xe8,  0xe0,  0xa9,  0x07,  0x16,  0xac,  0x45,
+  0x53,  0x85,  0x24,  0x41,  0x80,  0x4f,  0xff,  0x00,  0xae,  0x9a,  0x6d,  0xd9,
+  0x66,  0x11,  0x64,  0x6e,  0xf5,  0xed,  0x5a,  0x76,  0xd1,  0x98,  0x21,  0x0a,
+  0x48,  0x27,  0xda,  0x89,  0x4a,  0xc8,  0x29,  0xc1,  0xc9,  0xb4,  0xc9,  0xab,
+  0x20,  0xa9,  0x02,  0x7c,  0x82,  0x3f,  0xfd,  0x75,  0xab,  0x9a,  0x8a,  0xe6,
+  0x33,  0x34,  0x45,  0x41,  0xc1,  0xf7,  0xac,  0x60,  0xf9,  0x4e,  0x9a,  0x91,
+  0xe6,  0x46,  0x45,  0x15,  0x28,  0xb7,  0x66,  0x98,  0xc5,  0x91,  0xb8,  0x77,
+  0xed,  0x47,  0xd9,  0xdb,  0xcf,  0xf2,  0xb2,  0x37,  0x7a,  0xf6,  0xae,  0x9b,
+  0xa3,  0x87,  0x95,  0x8f,  0x55,  0x25,  0xad,  0xf0,  0x0f,  0xf9,  0x63,  0x5a,
+  0xd5,  0x0d,  0xba,  0x18,  0x61,  0x54,  0x24,  0x12,  0x3d,  0x2a,  0x4c,  0xd7,
+  0x34,  0xdf,  0x33,  0x3b,  0xe9,  0xc7,  0x95,  0x19,  0x6c,  0xa4,  0x35,  0xc6,
+  0x41,  0xff,  0x00,  0x2c,  0x2a,  0xbd,  0x6c,  0x5c,  0x46,  0x66,  0x85,  0x90,
+  0x1c,  0x13,  0xeb,  0x59,  0x9f,  0x67,  0x6f,  0x3f,  0xca,  0xc8,  0xdd,  0xfa,
+  0x56,  0xd0,  0x92,  0x68,  0xe5,  0xa9,  0x06,  0x9a,  0xb1,  0xa0,  0xd6,  0xc1,
+  0xae,  0x04,  0xb9,  0x39,  0x1d,  0xaa,  0x6a,  0x28,  0xae,  0x76,  0xdb,  0x3a,
+  0xd2,  0xb6,  0xc1,  0x45,  0x14,  0x52,  0x19,  0x0a,  0xdb,  0x05,  0xb8,  0x32,
+  0xe4,  0xe4,  0xf6,  0xa3,  0xec,  0xc3,  0xed,  0x1e,  0x6e,  0x4e,  0x7d,  0x2a,
+  0x6a,  0x2a,  0xb9,  0x99,  0x3c,  0xa8,  0x28,  0xa2,  0x8a,  0x92,  0x82,  0xa1,
+  0xfb,  0x30,  0xfb,  0x47,  0x9b,  0x93,  0x9f,  0x4a,  0x9a,  0x8a,  0x69,  0xd8,
+  0x4d,  0x5f,  0x72,  0x16,  0xb6,  0x0d,  0x70,  0x25,  0xc9,  0xc8,  0xed,  0x53,
+  0x51,  0x45,  0x0d,  0xb6,  0x09,  0x5b,  0x60,  0xa2,  0x8a,  0x29,  0x0c,  0x28,
+  0xa2,  0x8a,  0x00,  0x2b,  0x83,  0xf1,  0x57,  0xc1,  0xdd,  0x1b,  0xc4,  0xb7,
+  0xaf,  0x79,  0x1b,  0xcb,  0xa7,  0x5d,  0x48,  0x73,  0x21,  0x80,  0x02,  0x8e,
+  0x7d,  0x4a,  0x9e,  0xff,  0x00,  0x42,  0x2b,  0xbc,  0xa2,  0xbc,  0xfc,  0x76,
+  0x5f,  0x85,  0xcc,  0xa9,  0xfb,  0x1c,  0x5d,  0x35,  0x38,  0xf9,  0xfe,  0x8f,
+  0x75,  0xf2,  0x1a,  0x6d,  0x1c,  0x3f,  0x84,  0xbe,  0x11,  0xe8,  0xde,  0x16,
+  0xbb,  0x4b,  0xc2,  0xd2,  0x5f,  0xde,  0x27,  0x29,  0x24,  0xf8,  0xda,  0x87,
+  0xd5,  0x54,  0x77,  0xf7,  0x39,  0xae,  0xe2,  0x8a,  0x29,  0xe0,  0xb0,  0x18,
+  0x5c,  0xba,  0x97,  0xb1,  0xc2,  0x53,  0x50,  0x8f,  0x97,  0xeb,  0xd5,  0xfc,
+  0xc2,  0xed,  0x85,  0x71,  0xfe,  0x31,  0xf8,  0x5f,  0xa4,  0x78,  0xc6,  0x6f,
+  0xb4,  0xcd,  0xe6,  0x5a,  0x5e,  0xe3,  0x06,  0xe2,  0x0c,  0x65,  0xc7,  0x6d,
+  0xc0,  0xf5,  0xfe,  0x7e,  0xf5,  0xd8,  0x51,  0x55,  0x8c,  0xc1,  0x61,  0xf1,
+  0xf4,  0x9d,  0x0c,  0x54,  0x14,  0xe2,  0xfa,  0x3f,  0xeb,  0x46,  0x17,  0x68,
+  0xf3,  0xbf,  0x0f,  0x7c,  0x11,  0xd1,  0x74,  0x6b,  0xc4,  0xb9,  0xb9,  0x96,
+  0x5d,  0x49,  0xd0,  0xe5,  0x63,  0x94,  0x05,  0x8f,  0x3e,  0xa5,  0x47,  0x5f,
+  0xc4,  0xe3,  0xda,  0xbd,  0x13,  0xa5,  0x14,  0x56,  0x38,  0x1c,  0xb7,  0x07,
+  0x96,  0x41,  0xd3,  0xc1,  0xd3,  0x50,  0x4f,  0x7b,  0x75,  0xf5,  0x7b,  0xb0,
+  0x6d,  0xb0,  0xa2,  0x8a,  0x2b,  0xd3,  0x10,  0x51,  0x45,  0x14,  0x00,  0x54,
+  0x3f,  0x66,  0x1f,  0x68,  0xf3,  0x72,  0x73,  0xe9,  0x53,  0x51,  0x4d,  0x3b,
+  0x09,  0xab,  0xee,  0x42,  0xd6,  0xc1,  0xae,  0x04,  0xb9,  0x39,  0x1d,  0xaa,
+  0x6a,  0x28,  0xa1,  0xb6,  0xc1,  0x2b,  0x6c,  0x14,  0x51,  0x45,  0x21,  0x90,
+  0xad,  0xb0,  0x5b,  0x83,  0x2e,  0x4e,  0x4f,  0x6a,  0x3e,  0xcc,  0x3e,  0xd1,
+  0xe6,  0xe4,  0xe7,  0xd2,  0xa6,  0xa2,  0xab,  0x99,  0x93,  0xca,  0x82,  0x8a,
+  0x28,  0xa9,  0x28,  0x2a,  0x1f,  0xb3,  0x0f,  0xb4,  0x79,  0xb9,  0x39,  0xf4,
+  0xa9,  0xa8,  0xa6,  0x9d,  0x84,  0xd5,  0xf7,  0x3e,  0x20,  0xff,  0x00,  0x87,
+  0xa6,  0xf8,  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xa3,
+  0xfe,  0x1e,  0x9b,  0xe1,  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,
+  0xbe,  0x17,  0xfe,  0xc6,  0xb2,  0xff,  0x00,  0x9f,  0x64,  0xa7,  0x47,  0xa2,
+  0x59,  0x31,  0xe6,  0xd9,  0x31,  0x45,  0x8e,  0x9e,  0x44,  0x7d,  0xcd,  0xff,
+  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,  0xc7,  0xfe,  0x05,  0x45,
+  0x47,  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,  0x1f,  0xf8,  0x15,
+  0x15,  0x7c,  0x3b,  0xfd,  0x87,  0x61,  0xff,  0x00,  0x3e,  0xb1,  0xfe,  0x54,
+  0xd9,  0x34,  0x6b,  0x05,  0x1c,  0x5b,  0x47,  0x9f,  0xa5,  0x16,  0x0e,  0x44,
+  0x7d,  0xc9,  0xff,  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,  0xc7,
+  0xfe,  0x05,  0x45,  0x47,  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,
+  0x1f,  0xf8,  0x15,  0x15,  0x7c,  0x2f,  0xfd,  0x8d,  0x65,  0xff,  0x00,  0x3e,
+  0xc9,  0xf9,  0x53,  0xe3,  0xd1,  0x2c,  0x4f,  0x26,  0xd9,  0x31,  0xf4,  0xa2,
+  0xc1,  0xc8,  0x8f,  0xb9,  0x7f,  0xe1,  0xe9,  0xbe,  0x16,  0xff,  0x00,  0xa1,
+  0x1f,  0x58,  0xff,  0x00,  0xc0,  0xa8,  0xa8,  0xff,  0x00,  0x87,  0xa6,  0xf8,
+  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xaf,  0x87,  0x7f,
+  0xb0,  0xec,  0x3f,  0xe7,  0xd6,  0x3f,  0xca,  0x99,  0x26,  0x8d,  0x62,  0x38,
+  0x16,  0xc9,  0x9a,  0x2c,  0x1c,  0x88,  0xfb,  0x97,  0xfe,  0x1e,  0x9b,  0xe1,
+  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,  0x8f,  0xf8,  0x7a,  0x6f,
+  0x85,  0xbf,  0xe8,  0x47,  0xd6,  0x3f,  0xf0,  0x2a,  0x2a,  0xf8,  0x5f,  0xfb,
+  0x1a,  0xcb,  0xfe,  0x7d,  0x93,  0xf2,  0xa9,  0x23,  0xd1,  0x2c,  0x48,  0xc9,
+  0xb6,  0x4f,  0xca,  0x8b,  0x07,  0x22,  0x3e,  0xe4,  0xff,  0x00,  0x87,  0xa6,
+  0xf8,  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xa3,  0xfe,
+  0x1e,  0x9b,  0xe1,  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,  0xbe,
+  0x1d,  0xfe,  0xc3,  0xb0,  0xff,  0x00,  0x9f,  0x58,  0xff,  0x00,  0x2a,  0x64,
+  0x9a,  0x35,  0x88,  0x38,  0x16,  0xc9,  0xf9,  0x51,  0x60,  0xe4,  0x47,  0xdc,
+  0xbf,  0xf0,  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,  0x7f,  0xe0,  0x54,
+  0x54,  0x7f,  0xc3,  0xd3,  0x7c,  0x2d,  0xff,  0x00,  0x42,  0x3e,  0xb1,  0xff,
+  0x00,  0x81,  0x51,  0x57,  0xc2,  0xff,  0x00,  0xd8,  0xd6,  0x5f,  0xf3,  0xec,
+  0x9f,  0x95,  0x48,  0x9a,  0x1d,  0x89,  0x19,  0x36,  0xc9,  0xf9,  0x51,  0x60,
+  0xe4,  0x47,  0xdc,  0x9f,  0xf0,  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,
+  0x7f,  0xe0,  0x54,  0x54,  0x7f,  0xc3,  0xd3,  0x7c,  0x2d,  0xff,  0x00,  0x42,
+  0x3e,  0xb1,  0xff,  0x00,  0x81,  0x51,  0x57,  0xc3,  0xbf,  0xd8,  0x76,  0x1f,
+  0xf3,  0xeb,  0x1f,  0xe5,  0x51,  0xbe,  0x8d,  0x63,  0x9c,  0x0b,  0x64,  0xfc,
+  0xa8,  0xb0,  0x72,  0x23,  0xee,  0x6f,  0xf8,  0x7a,  0x6f,  0x85,  0xbf,  0xe8,
+  0x47,  0xd6,  0x3f,  0xf0,  0x2a,  0x2a,  0x3f,  0xe1,  0xe9,  0xbe,  0x16,  0xff,
+  0x00,  0xa1,  0x1f,  0x58,  0xff,  0x00,  0xc0,  0xa8,  0xab,  0xe1,  0x7f,  0xec,
+  0x7b,  0x2f,  0xf9,  0xf6,  0x4f,  0xca,  0x9b,  0x2e,  0x9d,  0xa7,  0xdb,  0xed,
+  0x53,  0x67,  0xe6,  0xc8,  0xc0,  0x90,  0xb1,  0xae,  0x4e,  0x3d,  0x68,  0xb0,
+  0x72,  0x23,  0xee,  0xaf,  0xf8,  0x7a,  0x6f,  0x85,  0xbf,  0xe8,  0x47,  0xd6,
+  0x3f,  0xf0,  0x2a,  0x2a,  0x3f,  0xe1,  0xe9,  0xbe,  0x16,  0xff,  0x00,  0xa1,
+  0x1f,  0x58,  0xff,  0x00,  0xc0,  0xa8,  0xab,  0xe1,  0x1f,  0x23,  0x4b,  0xd8,
+  0x1b,  0xec,  0x44,  0x8d,  0xbb,  0x9b,  0x09,  0xf7,  0x06,  0x48,  0xc9,  0xe7,
+  0xd8,  0xfe,  0x54,  0x3d,  0x9e,  0x9e,  0x2e,  0x04,  0x66,  0xcb,  0x60,  0x27,
+  0x68,  0x72,  0xbf,  0x29,  0x3f,  0x5c,  0xd1,  0x60,  0xe4,  0x47,  0xdd,  0xdf,
+  0xf0,  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,  0x7f,  0xe0,  0x54,  0x54,
+  0x7f,  0xc3,  0xd3,  0x7c,  0x2d,  0xff,  0x00,  0x42,  0x3e,  0xb1,  0xff,  0x00,
+  0x81,  0x51,  0x57,  0xc1,  0x82,  0xdf,  0x4e,  0x1b,  0xb7,  0xd9,  0x98,  0x88,
+  0x19,  0xda,  0xeb,  0xc9,  0xe7,  0x1c,  0x73,  0xea,  0x45,  0x4d,  0x1d,  0x9e,
+  0x9a,  0x46,  0x0d,  0x91,  0x12,  0x02,  0x41,  0x8c,  0xaf,  0xcd,  0x9c,  0x67,
+  0xd7,  0xd2,  0x8b,  0x07,  0x22,  0x3e,  0xed,  0xff,  0x00,  0x87,  0xa6,  0xf8,
+  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xa3,  0xfe,  0x1e,
+  0x9b,  0xe1,  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,  0xbe,  0x16,
+  0xb7,  0xd3,  0xf4,  0xeb,  0x86,  0x65,  0xfb,  0x1f,  0x96,  0xea,  0x01,  0x2b,
+  0x22,  0xe0,  0xe0,  0xf7,  0xa7,  0x36,  0x8f,  0x62,  0x49,  0xc5,  0xb2,  0x62,
+  0x8b,  0x07,  0x22,  0x3e,  0xe7,  0xff,  0x00,  0x87,  0xa6,  0xf8,  0x5b,  0xfe,
+  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xa3,  0xfe,  0x1e,  0x9b,  0xe1,
+  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,  0xbe,  0x17,  0xfe,  0xc6,
+  0xb2,  0x3f,  0xf2,  0xec,  0x95,  0x30,  0xd0,  0xec,  0x40,  0xff,  0x00,  0x8f,
+  0x64,  0xa2,  0xc1,  0xc8,  0x8f,  0xb8,  0xbf,  0xe1,  0xe9,  0xbe,  0x16,  0xff,
+  0x00,  0xa1,  0x1f,  0x58,  0xff,  0x00,  0xc0,  0xa8,  0xa8,  0xff,  0x00,  0x87,
+  0xa6,  0xf8,  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xaf,
+  0x87,  0x7f,  0xb1,  0x2c,  0x07,  0xfc,  0xba,  0xc7,  0xf9,  0x54,  0x27,  0x47,
+  0xb2,  0x27,  0xfe,  0x3d,  0x92,  0x8b,  0x07,  0x22,  0x3e,  0xe8,  0xff,  0x00,
+  0x87,  0xa6,  0xf8,  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,
+  0xa3,  0xfe,  0x1e,  0x9b,  0xe1,  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,
+  0x8a,  0xbe,  0x17,  0x1a,  0x2d,  0x91,  0x38,  0xfb,  0x32,  0x54,  0xdf,  0xd8,
+  0x76,  0x1f,  0xf3,  0xea,  0x9f,  0x95,  0x16,  0x0e,  0x44,  0x7d,  0xc5,  0xff,
+  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,  0xc7,  0xfe,  0x05,  0x45,
+  0x47,  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,  0x1f,  0xf8,  0x15,
+  0x15,  0x7c,  0x3a,  0x74,  0x4b,  0x00,  0x33,  0xf6,  0x58,  0xff,  0x00,  0x2a,
+  0x84,  0xe8,  0xd6,  0x5f,  0xf3,  0xec,  0x94,  0x58,  0x39,  0x11,  0xf7,  0x47,
+  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,  0x1f,  0xf8,  0x15,  0x15,
+  0x1f,  0xf0,  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,  0x7f,  0xe0,  0x54,
+  0x55,  0xf0,  0xc2,  0xe8,  0xb6,  0x4c,  0x40,  0xfb,  0x32,  0x54,  0xbf,  0xd8,
+  0x76,  0x1f,  0xf3,  0xea,  0x94,  0x58,  0x39,  0x11,  0xf7,  0x17,  0xfc,  0x3d,
+  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,  0x1f,  0xf8,  0x15,  0x15,  0x1f,  0xf0,
+  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,  0x7f,  0xe0,  0x54,  0x55,  0xf0,
+  0xe3,  0x68,  0xb6,  0x0a,  0x09,  0xfb,  0x2c,  0x7f,  0x95,  0x45,  0xfd,  0x8d,
+  0x65,  0xff,  0x00,  0x3e,  0xc9,  0x45,  0x83,  0x91,  0x1f,  0x74,  0x7f,  0xc3,
+  0xd3,  0x7c,  0x2d,  0xff,  0x00,  0x42,  0x3e,  0xb1,  0xff,  0x00,  0x81,  0x51,
+  0x51,  0xff,  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,  0xc7,  0xfe,
+  0x05,  0x45,  0x5f,  0x0c,  0x26,  0x89,  0x64,  0xcd,  0xff,  0x00,  0x1e,  0xc9,
+  0x52,  0xff,  0x00,  0x61,  0xd8,  0x7f,  0xcf,  0xac,  0x7f,  0x95,  0x16,  0x0e,
+  0x44,  0x7d,  0xc5,  0xff,  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,
+  0xc7,  0xfe,  0x05,  0x45,  0x47,  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,
+  0xeb,  0x1f,  0xf8,  0x15,  0x15,  0x7c,  0x38,  0xfa,  0x2d,  0x82,  0xaf,  0xfc,
+  0x7a,  0xc7,  0xf9,  0x54,  0x5f,  0xd8,  0xd6,  0x5f,  0xf3,  0xec,  0x94,  0x58,
+  0x39,  0x11,  0x72,  0xa7,  0x45,  0xda,  0xb8,  0xa8,  0xe3,  0x5c,  0xb6,  0x7d,
+  0x2a,  0x5a,  0xa2,  0xc2,  0xa1,  0x66,  0xdc,  0xd9,  0xa7,  0xc8,  0xd8,  0x18,
+  0xf5,  0xa8,  0xa8,  0x01,  0x40,  0xc9,  0xa9,  0xd4,  0x6d,  0x18,  0xa8,  0xe2,
+  0x5e,  0x73,  0x52,  0x50,  0x00,  0x4e,  0x05,  0x40,  0xc7,  0x71,  0xcd,  0x49,
+  0x2b,  0x71,  0x8a,  0x8a,  0x80,  0x14,  0x0c,  0x9c,  0x54,  0xe0,  0x60,  0x62,
+  0xa3,  0x89,  0x7b,  0xd4,  0x94,  0x00,  0x13,  0x80,  0x4d,  0x40,  0x4e,  0x4e,
+  0x69,  0xf2,  0xb7,  0x6a,  0x8e,  0x80,  0x15,  0x46,  0xe3,  0x8a,  0x9e,  0x99,
+  0x1a,  0xe0,  0x67,  0xd6,  0x9f,  0x40,  0x08,  0xc7,  0x68,  0xcd,  0x41,  0x4f,
+  0x91,  0xb2,  0x71,  0xe9,  0x4c,  0xa0,  0x07,  0x22,  0xee,  0x6f,  0x6a,  0x27,
+  0xb5,  0x59,  0xa4,  0x49,  0x37,  0xbc,  0x6e,  0xbc,  0x06,  0x43,  0x8c,  0x8f,
+  0x43,  0xed,  0x52,  0x46,  0xb8,  0x5f,  0x73,  0x4e,  0xa0,  0x0a,  0xa6,  0xca,
+  0x38,  0xa2,  0x95,  0x41,  0x6f,  0xde,  0x2e,  0xc3,  0xcf,  0x6c,  0x93,  0xff,
+  0x00,  0xb3,  0x1a,  0x87,  0xec,  0x60,  0xca,  0xae,  0xd2,  0x48,  0xe1,  0x4e,
+  0x42,  0x12,  0x36,  0x83,  0xf9,  0x55,  0xa9,  0x1b,  0x73,  0x7b,  0x0a,  0x6d,
+  0x00,  0x57,  0x8b,  0x49,  0xb7,  0x0c,  0xfb,  0x53,  0xcb,  0x0c,  0x00,  0x21,
+  0x38,  0xe8,  0x72,  0x0f,  0xd6,  0xa6,  0x5d,  0x39,  0x17,  0x90,  0xf2,  0x79,
+  0x99,  0x2c,  0x64,  0x27,  0x2c,  0x4e,  0xdc,  0x7e,  0x82,  0xac,  0xa2,  0xed,
+  0x5a,  0x5a,  0x00,  0xad,  0x1d,  0xaa,  0xdb,  0x16,  0x6f,  0x31,  0xe5,  0x91,
+  0xc0,  0x05,  0xe4,  0x39,  0x38,  0x1d,  0xbf,  0x5a,  0x5a,  0x73,  0xb6,  0xe6,
+  0xa6,  0xf5,  0xa0,  0x07,  0xc4,  0xb9,  0x39,  0xf4,  0xa9,  0x69,  0x14,  0x6d,
+  0x18,  0xa5,  0xe9,  0x40,  0x0c,  0x95,  0xb0,  0x31,  0x51,  0x52,  0xb1,  0xdc,
+  0x49,  0xa0,  0x0c,  0x9c,  0x50,  0x03,  0xe2,  0x5e,  0xf5,  0x25,  0x00,  0x60,
+  0x62,  0x82,  0x70,  0x33,  0x40,  0x11,  0xca,  0xdd,  0xaa,  0x3a,  0x52,  0x72,
+  0x73,  0x42,  0x8d,  0xc4,  0x0a,  0x00,  0x92,  0x25,  0xc0,  0xcd,  0x3e,  0x8e,
+  0x94,  0x8c,  0x76,  0x82,  0x68,  0x02,  0x39,  0x5b,  0x27,  0x1e,  0x94,  0xca,
+  0x3a,  0xd3,  0x91,  0x77,  0x35,  0x00,  0x49,  0x1a,  0xe1,  0x7d,  0xcd,  0x3a,
+  0x8a,  0x47,  0x6d,  0xab,  0x40,  0x11,  0xc8,  0xd9,  0x6f,  0x61,  0x4c,  0xa2,
+  0x9d,  0x1a,  0xee,  0x6f,  0x61,  0x40,  0x1f,  0xff,  0xd9
+};
diff --git a/services/camera/libcameraservice/FakeCamera.cpp b/services/camera/libcameraservice/FakeCamera.cpp
new file mode 100644
index 0000000..f3a6a67
--- /dev/null
+++ b/services/camera/libcameraservice/FakeCamera.cpp
@@ -0,0 +1,433 @@
+/*
+**
+** Copyright 2008, 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_TAG "FakeCamera"
+#include <utils/Log.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <utils/String8.h>
+
+#include "FakeCamera.h"
+
+
+namespace android {
+
+// TODO: All this rgb to yuv should probably be in a util class.
+
+// TODO: I think something is wrong in this class because the shadow is kBlue
+// and the square color should alternate between kRed and kGreen. However on the
+// emulator screen these are all shades of gray. Y seems ok but the U and V are
+// probably not.
+
+static int tables_initialized = 0;
+uint8_t *gYTable, *gCbTable, *gCrTable;
+
+static int
+clamp(int  x)
+{
+    if (x > 255) return 255;
+    if (x < 0)   return 0;
+    return x;
+}
+
+/* the equation used by the video code to translate YUV to RGB looks like this
+ *
+ *    Y  = (Y0 - 16)*k0
+ *    Cb = Cb0 - 128
+ *    Cr = Cr0 - 128
+ *
+ *    G = ( Y - k1*Cr - k2*Cb )
+ *    R = ( Y + k3*Cr )
+ *    B = ( Y + k4*Cb )
+ *
+ */
+
+static const double  k0 = 1.164;
+static const double  k1 = 0.813;
+static const double  k2 = 0.391;
+static const double  k3 = 1.596;
+static const double  k4 = 2.018;
+
+/* let's try to extract the value of Y
+ *
+ *   G + k1/k3*R + k2/k4*B = Y*( 1 + k1/k3 + k2/k4 )
+ *
+ *   Y  = ( G + k1/k3*R + k2/k4*B ) / (1 + k1/k3 + k2/k4)
+ *   Y0 = ( G0 + k1/k3*R0 + k2/k4*B0 ) / ((1 + k1/k3 + k2/k4)*k0) + 16
+ *
+ * let define:
+ *   kYr = k1/k3
+ *   kYb = k2/k4
+ *   kYy = k0 * ( 1 + kYr + kYb )
+ *
+ * we have:
+ *    Y  = ( G + kYr*R + kYb*B )
+ *    Y0 = clamp[ Y/kYy + 16 ]
+ */
+
+static const double kYr = k1/k3;
+static const double kYb = k2/k4;
+static const double kYy = k0*( 1. + kYr + kYb );
+
+static void
+initYtab( void )
+{
+    const  int imax = (int)( (kYr + kYb)*(31 << 2) + (61 << 3) + 0.1 );
+    int    i;
+
+    gYTable = (uint8_t *)malloc(imax);
+
+    for(i=0; i<imax; i++) {
+        int  x = (int)(i/kYy + 16.5);
+        if (x < 16) x = 16;
+        else if (x > 235) x = 235;
+        gYTable[i] = (uint8_t) x;
+    }
+}
+
+/*
+ *   the source is RGB565, so adjust for 8-bit range of input values:
+ *
+ *   G = (pixels >> 3) & 0xFC;
+ *   R = (pixels >> 8) & 0xF8;
+ *   B = (pixels & 0x1f) << 3;
+ *
+ *   R2 = (pixels >> 11)      R = R2*8
+ *   B2 = (pixels & 0x1f)     B = B2*8
+ *
+ *   kYr*R = kYr2*R2 =>  kYr2 = kYr*8
+ *   kYb*B = kYb2*B2 =>  kYb2 = kYb*8
+ *
+ *   we want to use integer multiplications:
+ *
+ *   SHIFT1 = 9
+ *
+ *   (ALPHA*R2) >> SHIFT1 == R*kYr  =>  ALPHA = kYr*8*(1 << SHIFT1)
+ *
+ *   ALPHA = kYr*(1 << (SHIFT1+3))
+ *   BETA  = kYb*(1 << (SHIFT1+3))
+ */
+
+static const int  SHIFT1  = 9;
+static const int  ALPHA   = (int)( kYr*(1 << (SHIFT1+3)) + 0.5 );
+static const int  BETA    = (int)( kYb*(1 << (SHIFT1+3)) + 0.5 );
+
+/*
+ *  now let's try to get the values of Cb and Cr
+ *
+ *  R-B = (k3*Cr - k4*Cb)
+ *
+ *    k3*Cr = k4*Cb + (R-B)
+ *    k4*Cb = k3*Cr - (R-B)
+ *
+ *  R-G = (k1+k3)*Cr + k2*Cb
+ *      = (k1+k3)*Cr + k2/k4*(k3*Cr - (R-B)/k0)
+ *      = (k1 + k3 + k2*k3/k4)*Cr - k2/k4*(R-B)
+ *
+ *  kRr*Cr = (R-G) + kYb*(R-B)
+ *
+ *  Cr  = ((R-G) + kYb*(R-B))/kRr
+ *  Cr0 = clamp(Cr + 128)
+ */
+
+static const double  kRr = (k1 + k3 + k2*k3/k4);
+
+static void
+initCrtab( void )
+{
+    uint8_t *pTable;
+    int i;
+
+    gCrTable = (uint8_t *)malloc(768*2);
+
+    pTable = gCrTable + 384;
+    for(i=-384; i<384; i++)
+        pTable[i] = (uint8_t) clamp( i/kRr + 128.5 );
+}
+
+/*
+ *  B-G = (k2 + k4)*Cb + k1*Cr
+ *      = (k2 + k4)*Cb + k1/k3*(k4*Cb + (R-B))
+ *      = (k2 + k4 + k1*k4/k3)*Cb + k1/k3*(R-B)
+ *
+ *  kBb*Cb = (B-G) - kYr*(R-B)
+ *
+ *  Cb   = ((B-G) - kYr*(R-B))/kBb
+ *  Cb0  = clamp(Cb + 128)
+ *
+ */
+
+static const double  kBb = (k2 + k4 + k1*k4/k3);
+
+static void
+initCbtab( void )
+{
+    uint8_t *pTable;
+    int i;
+
+    gCbTable = (uint8_t *)malloc(768*2);
+
+    pTable = gCbTable + 384;
+    for(i=-384; i<384; i++)
+        pTable[i] = (uint8_t) clamp( i/kBb + 128.5 );
+}
+
+/*
+ *   SHIFT2 = 16
+ *
+ *   DELTA = kYb*(1 << SHIFT2)
+ *   GAMMA = kYr*(1 << SHIFT2)
+ */
+
+static const int  SHIFT2 = 16;
+static const int  DELTA  = kYb*(1 << SHIFT2);
+static const int  GAMMA  = kYr*(1 << SHIFT2);
+
+int32_t ccrgb16toyuv_wo_colorkey(uint8_t *rgb16, uint8_t *yuv420,
+        uint32_t *param, uint8_t *table[])
+{
+    uint16_t *inputRGB = (uint16_t*)rgb16;
+    uint8_t *outYUV = yuv420;
+    int32_t width_dst = param[0];
+    int32_t height_dst = param[1];
+    int32_t pitch_dst = param[2];
+    int32_t mheight_dst = param[3];
+    int32_t pitch_src = param[4];
+    uint8_t *y_tab = table[0];
+    uint8_t *cb_tab = table[1];
+    uint8_t *cr_tab = table[2];
+
+    int32_t size16 = pitch_dst*mheight_dst;
+    int32_t i,j,count;
+    int32_t ilimit,jlimit;
+    uint8_t *tempY,*tempU,*tempV;
+    uint16_t pixels;
+    int   tmp;
+uint32_t temp;
+
+    tempY = outYUV;
+    tempU = outYUV + (height_dst * pitch_dst);
+    tempV = tempU + 1;
+
+    jlimit = height_dst;
+    ilimit = width_dst;
+
+    for(j=0; j<jlimit; j+=1)
+    {
+        for (i=0; i<ilimit; i+=2)
+        {
+            int32_t   G_ds = 0, B_ds = 0, R_ds = 0;
+            uint8_t   y0, y1, u, v;
+
+            pixels =  inputRGB[i];
+            temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
+            y0   = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
+
+            G_ds    += (pixels>>1) & 0x03E0;
+            B_ds    += (pixels<<5) & 0x03E0;
+            R_ds    += (pixels>>6) & 0x03E0;
+
+            pixels =  inputRGB[i+1];
+            temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
+            y1   = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
+
+            G_ds    += (pixels>>1) & 0x03E0;
+            B_ds    += (pixels<<5) & 0x03E0;
+            R_ds    += (pixels>>6) & 0x03E0;
+
+            R_ds >>= 1;
+            B_ds >>= 1;
+            G_ds >>= 1;
+
+            tmp = R_ds - B_ds;
+
+            u = cb_tab[(((B_ds-G_ds)<<SHIFT2) - GAMMA*tmp)>>(SHIFT2+2)];
+            v = cr_tab[(((R_ds-G_ds)<<SHIFT2) + DELTA*tmp)>>(SHIFT2+2)];
+
+            tempY[0] = y0;
+            tempY[1] = y1;
+            tempY += 2;
+
+            if ((j&1) == 0) {
+                tempU[0] = u;
+                tempV[0] = v;
+                tempU += 2;
+                tempV += 2;
+            }
+        }
+
+        inputRGB += pitch_src;
+    }
+
+    return 1;
+}
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+
+static void convert_rgb16_to_yuv420(uint8_t *rgb, uint8_t *yuv, int width, int height)
+{
+    if (!tables_initialized) {
+        initYtab();
+        initCrtab();
+        initCbtab();
+        tables_initialized = 1;
+    }
+
+    uint32_t param[6];
+    param[0] = (uint32_t) width;
+    param[1] = (uint32_t) height;
+    param[2] = (uint32_t) width;
+    param[3] = (uint32_t) height;
+    param[4] = (uint32_t) width;
+    param[5] = (uint32_t) 0;
+
+    uint8_t *table[3];
+    table[0] = gYTable;
+    table[1] = gCbTable + 384;
+    table[2] = gCrTable + 384;
+
+    ccrgb16toyuv_wo_colorkey(rgb, yuv, param, table);
+}
+
+const int FakeCamera::kRed;
+const int FakeCamera::kGreen;
+const int FakeCamera::kBlue;
+
+FakeCamera::FakeCamera(int width, int height)
+          : mTmpRgb16Buffer(0)
+{
+    setSize(width, height);
+}
+
+FakeCamera::~FakeCamera()
+{
+    delete[] mTmpRgb16Buffer;
+}
+
+void FakeCamera::setSize(int width, int height)
+{
+    mWidth = width;
+    mHeight = height;
+    mCounter = 0;
+    mCheckX = 0;
+    mCheckY = 0;
+
+    // This will cause it to be reallocated on the next call
+    // to getNextFrameAsYuv420().
+    delete[] mTmpRgb16Buffer;
+    mTmpRgb16Buffer = 0;
+}
+
+void FakeCamera::getNextFrameAsRgb565(uint16_t *buffer)
+{
+    int size = mWidth / 10;
+
+    drawCheckerboard(buffer, size);
+
+    int x = ((mCounter*3)&255);
+    if(x>128) x = 255 - x;
+    int y = ((mCounter*5)&255);
+    if(y>128) y = 255 - y;
+
+    drawSquare(buffer, x*size/32, y*size/32, (size*5)>>1, (mCounter&0x100)?kRed:kGreen, kBlue);
+
+    mCounter++;
+}
+
+void FakeCamera::getNextFrameAsYuv420(uint8_t *buffer)
+{
+    if (mTmpRgb16Buffer == 0)
+        mTmpRgb16Buffer = new uint16_t[mWidth * mHeight];
+
+    getNextFrameAsRgb565(mTmpRgb16Buffer);
+    convert_rgb16_to_yuv420((uint8_t*)mTmpRgb16Buffer, buffer, mWidth, mHeight);
+}
+
+void FakeCamera::drawSquare(uint16_t *dst, int x, int y, int size, int color, int shadow)
+{
+    int square_xstop, square_ystop, shadow_xstop, shadow_ystop;
+
+    square_xstop = min(mWidth, x+size);
+    square_ystop = min(mHeight, y+size);
+    shadow_xstop = min(mWidth, x+size+(size/4));
+    shadow_ystop = min(mHeight, y+size+(size/4));
+
+    // Do the shadow.
+    uint16_t *sh = &dst[(y+(size/4))*mWidth];
+    for (int j = y + (size/4); j < shadow_ystop; j++) {
+        for (int i = x + (size/4); i < shadow_xstop; i++) {
+            sh[i] &= shadow;
+        }
+        sh += mWidth;
+    }
+
+    // Draw the square.
+    uint16_t *sq = &dst[y*mWidth];
+    for (int j = y; j < square_ystop; j++) {
+        for (int i = x; i < square_xstop; i++) {
+            sq[i] = color;
+        }
+        sq += mWidth;
+    }
+}
+
+void FakeCamera::drawCheckerboard(uint16_t *dst, int size)
+{
+    bool black = true;
+
+    if((mCheckX/size)&1)
+        black = false;
+    if((mCheckY/size)&1)
+        black = !black;
+
+    int county = mCheckY%size;
+    int checkxremainder = mCheckX%size;
+
+    for(int y=0;y<mHeight;y++) {
+        int countx = checkxremainder;
+        bool current = black;
+        for(int x=0;x<mWidth;x++) {
+            dst[y*mWidth+x] = current?0:0xffff;
+            if(countx++ >= size) {
+                countx=0;
+                current = !current;
+            }
+        }
+        if(county++ >= size) {
+            county=0;
+            black = !black;
+        }
+    }
+    mCheckX += 3;
+    mCheckY++;
+}
+
+
+void FakeCamera::dump(int fd) const
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+    snprintf(buffer, 255, " width x height (%d x %d), counter (%d), check x-y coordinate(%d, %d)\n", mWidth, mHeight, mCounter, mCheckX, mCheckY);
+    result.append(buffer);
+    ::write(fd, result.string(), result.size());
+}
+
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/FakeCamera.h b/services/camera/libcameraservice/FakeCamera.h
new file mode 100644
index 0000000..724de20
--- /dev/null
+++ b/services/camera/libcameraservice/FakeCamera.h
@@ -0,0 +1,67 @@
+/*
+**
+** Copyright 2008, 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 ANDROID_HARDWARE_FAKECAMERA_H
+#define ANDROID_HARDWARE_FAKECAMERA_H
+
+#include <sys/types.h>
+#include <stdint.h>
+
+namespace android {
+
+/*
+ * FakeCamera is used in the CameraHardwareStub to provide a fake video feed
+ * when the system does not have a camera in hardware.
+ * The fake video is a moving black and white checkerboard background with a
+ * bouncing gray square in the foreground.
+ * This class is not thread-safe.
+ *
+ * TODO: Since the major methods provides a raw/uncompressed video feed, rename
+ * this class to RawVideoSource.
+ */
+
+class FakeCamera {
+public:
+    FakeCamera(int width, int height);
+    ~FakeCamera();
+
+    void setSize(int width, int height);
+    void getNextFrameAsYuv420(uint8_t *buffer);
+    // Write to the fd a string representing the current state.
+    void dump(int fd) const;
+
+private:
+    // TODO: remove the uint16_t buffer param everywhere since it is a field of
+    // this class.
+    void getNextFrameAsRgb565(uint16_t *buffer);
+
+    void drawSquare(uint16_t *buffer, int x, int y, int size, int color, int shadow);
+    void drawCheckerboard(uint16_t *buffer, int size);
+
+    static const int kRed = 0xf800;
+    static const int kGreen = 0x07c0;
+    static const int kBlue = 0x003e;
+
+    int         mWidth, mHeight;
+    int         mCounter;
+    int         mCheckX, mCheckY;
+    uint16_t    *mTmpRgb16Buffer;
+};
+
+}; // namespace android
+
+#endif // ANDROID_HARDWARE_FAKECAMERA_H
diff --git a/services/camera/tests/CameraServiceTest/Android.mk b/services/camera/tests/CameraServiceTest/Android.mk
new file mode 100644
index 0000000..cf4e42f
--- /dev/null
+++ b/services/camera/tests/CameraServiceTest/Android.mk
@@ -0,0 +1,26 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= CameraServiceTest.cpp
+
+LOCAL_MODULE:= CameraServiceTest
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_C_INCLUDES += \
+                frameworks/base/libs
+
+LOCAL_CFLAGS :=
+
+LOCAL_SHARED_LIBRARIES += \
+		libbinder \
+                libcutils \
+                libutils \
+                libui \
+                libcamera_client \
+                libsurfaceflinger_client
+
+# Disable it because the ISurface interface may change, and before we have a
+# chance to fix this test, we don't want to break normal builds.
+#include $(BUILD_EXECUTABLE)
diff --git a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
new file mode 100644
index 0000000..3c8d553
--- /dev/null
+++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -0,0 +1,919 @@
+#define LOG_TAG "CameraServiceTest"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <surfaceflinger/ISurface.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
+#include <ui/GraphicBuffer.h>
+#include <camera/ICamera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraService.h>
+#include <ui/Overlay.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+using namespace android;
+
+//
+//  Assertion and Logging utilities
+//
+#define INFO(...) \
+    do { \
+        printf(__VA_ARGS__); \
+        printf("\n"); \
+        LOGD(__VA_ARGS__); \
+    } while(0)
+
+void assert_fail(const char *file, int line, const char *func, const char *expr) {
+    INFO("assertion failed at file %s, line %d, function %s:",
+            file, line, func);
+    INFO("%s", expr);
+    abort();
+}
+
+void assert_eq_fail(const char *file, int line, const char *func,
+        const char *expr, int actual) {
+    INFO("assertion failed at file %s, line %d, function %s:",
+            file, line, func);
+    INFO("(expected) %s != (actual) %d", expr, actual);
+    abort();
+}
+
+#define ASSERT(e) \
+    do { \
+        if (!(e)) \
+            assert_fail(__FILE__, __LINE__, __func__, #e); \
+    } while(0)
+
+#define ASSERT_EQ(expected, actual) \
+    do { \
+        int _x = (actual); \
+        if (_x != (expected)) \
+            assert_eq_fail(__FILE__, __LINE__, __func__, #expected, _x); \
+    } while(0)
+
+//
+//  Holder service for pass objects between processes.
+//
+class IHolder : public IInterface {
+protected:
+    enum {
+        HOLDER_PUT = IBinder::FIRST_CALL_TRANSACTION,
+        HOLDER_GET,
+        HOLDER_CLEAR
+    };
+public:
+    DECLARE_META_INTERFACE(Holder);
+
+    virtual void put(sp<IBinder> obj) = 0;
+    virtual sp<IBinder> get() = 0;
+    virtual void clear() = 0;
+};
+
+class BnHolder : public BnInterface<IHolder> {
+    virtual status_t onTransact(uint32_t code,
+                                const Parcel& data,
+                                Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+class BpHolder : public BpInterface<IHolder> {
+public:
+    BpHolder(const sp<IBinder>& impl)
+        : BpInterface<IHolder>(impl) {
+    }
+
+    virtual void put(sp<IBinder> obj) {
+        Parcel data, reply;
+        data.writeStrongBinder(obj);
+        remote()->transact(HOLDER_PUT, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    virtual sp<IBinder> get() {
+        Parcel data, reply;
+        remote()->transact(HOLDER_GET, data, &reply);
+        return reply.readStrongBinder();
+    }
+
+    virtual void clear() {
+        Parcel data, reply;
+        remote()->transact(HOLDER_CLEAR, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(Holder, "CameraServiceTest.Holder");
+
+status_t BnHolder::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch(code) {
+        case HOLDER_PUT: {
+            put(data.readStrongBinder());
+            return NO_ERROR;
+        } break;
+        case HOLDER_GET: {
+            reply->writeStrongBinder(get());
+            return NO_ERROR;
+        } break;
+        case HOLDER_CLEAR: {
+            clear();
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+class HolderService : public BnHolder {
+    virtual void put(sp<IBinder> obj) {
+        mObj = obj;
+    }
+    virtual sp<IBinder> get() {
+        return mObj;
+    }
+    virtual void clear() {
+        mObj.clear();
+    }
+private:
+    sp<IBinder> mObj;
+};
+
+//
+//  A mock CameraClient
+//
+class MCameraClient : public BnCameraClient {
+public:
+    virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2);
+    virtual void dataCallback(int32_t msgType, const sp<IMemory>& data);
+    virtual void dataCallbackTimestamp(nsecs_t timestamp,
+            int32_t msgType, const sp<IMemory>& data);
+
+    // new functions
+    void clearStat();
+    enum OP { EQ, GE, LE, GT, LT };
+    void assertNotify(int32_t msgType, OP op, int count);
+    void assertData(int32_t msgType, OP op, int count);
+    void waitNotify(int32_t msgType, OP op, int count);
+    void waitData(int32_t msgType, OP op, int count);
+    void assertDataSize(int32_t msgType, OP op, int dataSize);
+
+    void setReleaser(ICamera *releaser) {
+        mReleaser = releaser;
+    }
+private:
+    Mutex mLock;
+    Condition mCond;
+    DefaultKeyedVector<int32_t, int> mNotifyCount;
+    DefaultKeyedVector<int32_t, int> mDataCount;
+    DefaultKeyedVector<int32_t, int> mDataSize;
+    bool test(OP op, int v1, int v2);
+    void assertTest(OP op, int v1, int v2);
+
+    ICamera *mReleaser;
+};
+
+void MCameraClient::clearStat() {
+    Mutex::Autolock _l(mLock);
+    mNotifyCount.clear();
+    mDataCount.clear();
+    mDataSize.clear();
+}
+
+bool MCameraClient::test(OP op, int v1, int v2) {
+    switch (op) {
+        case EQ: return v1 == v2;
+        case GT: return v1 > v2;
+        case LT: return v1 < v2;
+        case GE: return v1 >= v2;
+        case LE: return v1 <= v2;
+        default: ASSERT(0); break;
+    }
+    return false;
+}
+
+void MCameraClient::assertTest(OP op, int v1, int v2) {
+    if (!test(op, v1, v2)) {
+        LOGE("assertTest failed: op=%d, v1=%d, v2=%d", op, v1, v2);
+        ASSERT(0);
+    }
+}
+
+void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
+    Mutex::Autolock _l(mLock);
+    int v = mNotifyCount.valueFor(msgType);
+    assertTest(op, v, count);
+}
+
+void MCameraClient::assertData(int32_t msgType, OP op, int count) {
+    Mutex::Autolock _l(mLock);
+    int v = mDataCount.valueFor(msgType);
+    assertTest(op, v, count);
+}
+
+void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
+    Mutex::Autolock _l(mLock);
+    int v = mDataSize.valueFor(msgType);
+    assertTest(op, v, dataSize);
+}
+
+void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
+    INFO("%s", __func__);
+    Mutex::Autolock _l(mLock);
+    ssize_t i = mNotifyCount.indexOfKey(msgType);
+    if (i < 0) {
+        mNotifyCount.add(msgType, 1);
+    } else {
+        ++mNotifyCount.editValueAt(i);
+    }
+    mCond.signal();
+}
+
+void MCameraClient::dataCallback(int32_t msgType, const sp<IMemory>& data) {
+    INFO("%s", __func__);
+    int dataSize = data->size();
+    INFO("data type = %d, size = %d", msgType, dataSize);
+    Mutex::Autolock _l(mLock);
+    ssize_t i = mDataCount.indexOfKey(msgType);
+    if (i < 0) {
+        mDataCount.add(msgType, 1);
+        mDataSize.add(msgType, dataSize);
+    } else {
+        ++mDataCount.editValueAt(i);
+        mDataSize.editValueAt(i) = dataSize;
+    }
+    mCond.signal();
+
+    if (msgType == CAMERA_MSG_VIDEO_FRAME) {
+        ASSERT(mReleaser != NULL);
+        mReleaser->releaseRecordingFrame(data);
+    }
+}
+
+void MCameraClient::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+        const sp<IMemory>& data) {
+    dataCallback(msgType, data);
+}
+
+void MCameraClient::waitNotify(int32_t msgType, OP op, int count) {
+    INFO("waitNotify: %d, %d, %d", msgType, op, count);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        int v = mNotifyCount.valueFor(msgType);
+        if (test(op, v, count)) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+void MCameraClient::waitData(int32_t msgType, OP op, int count) {
+    INFO("waitData: %d, %d, %d", msgType, op, count);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        int v = mDataCount.valueFor(msgType);
+        if (test(op, v, count)) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+//
+//  A mock Surface
+//
+class MSurface : public BnSurface {
+public:
+    virtual status_t registerBuffers(const BufferHeap& buffers);
+    virtual void postBuffer(ssize_t offset);
+    virtual void unregisterBuffers();
+    virtual sp<OverlayRef> createOverlay(
+            uint32_t w, uint32_t h, int32_t format, int32_t orientation);
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
+    virtual status_t setBufferCount(int bufferCount);
+
+    // new functions
+    void clearStat();
+    void waitUntil(int c0, int c1, int c2);
+
+private:
+    // check callback count
+    Condition mCond;
+    Mutex mLock;
+    int registerBuffersCount;
+    int postBufferCount;
+    int unregisterBuffersCount;
+};
+
+status_t MSurface::registerBuffers(const BufferHeap& buffers) {
+    INFO("%s", __func__);
+    Mutex::Autolock _l(mLock);
+    ++registerBuffersCount;
+    mCond.signal();
+    return NO_ERROR;
+}
+
+void MSurface::postBuffer(ssize_t offset) {
+    // INFO("%s", __func__);
+    Mutex::Autolock _l(mLock);
+    ++postBufferCount;
+    mCond.signal();
+}
+
+void MSurface::unregisterBuffers() {
+    INFO("%s", __func__);
+    Mutex::Autolock _l(mLock);
+    ++unregisterBuffersCount;
+    mCond.signal();
+}
+
+sp<GraphicBuffer> MSurface::requestBuffer(int bufferIdx, int usage) {
+    INFO("%s", __func__);
+    return NULL;
+}
+
+status_t MSurface::setBufferCount(int bufferCount) {
+    INFO("%s", __func__);
+    return NULL;
+}
+
+void MSurface::clearStat() {
+    Mutex::Autolock _l(mLock);
+    registerBuffersCount = 0;
+    postBufferCount = 0;
+    unregisterBuffersCount = 0;
+}
+
+void MSurface::waitUntil(int c0, int c1, int c2) {
+    INFO("waitUntil: %d %d %d", c0, c1, c2);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        if (registerBuffersCount >= c0 &&
+            postBufferCount >= c1 &&
+            unregisterBuffersCount >= c2) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format,
+        int32_t orientation) {
+    // Not implemented.
+    ASSERT(0);
+    return NULL;
+}
+
+//
+//  Utilities to use the Holder service
+//
+sp<IHolder> getHolder() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    ASSERT(sm != 0);
+    sp<IBinder> binder = sm->getService(String16("CameraServiceTest.Holder"));
+    ASSERT(binder != 0);
+    sp<IHolder> holder = interface_cast<IHolder>(binder);
+    ASSERT(holder != 0);
+    return holder;
+}
+
+void putTempObject(sp<IBinder> obj) {
+    INFO("%s", __func__);
+    getHolder()->put(obj);
+}
+
+sp<IBinder> getTempObject() {
+    INFO("%s", __func__);
+    return getHolder()->get();
+}
+
+void clearTempObject() {
+    INFO("%s", __func__);
+    getHolder()->clear();
+}
+
+//
+//  Get a Camera Service
+//
+sp<ICameraService> getCameraService() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    ASSERT(sm != 0);
+    sp<IBinder> binder = sm->getService(String16("media.camera"));
+    ASSERT(binder != 0);
+    sp<ICameraService> cs = interface_cast<ICameraService>(binder);
+    ASSERT(cs != 0);
+    return cs;
+}
+
+int getNumberOfCameras() {
+    sp<ICameraService> cs = getCameraService();
+    return cs->getNumberOfCameras();
+}
+
+//
+// Various Connect Tests
+//
+void testConnect(int cameraId) {
+    INFO("%s", __func__);
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc, cameraId);
+    ASSERT(c != 0);
+    c->disconnect();
+}
+
+void testAllowConnectOnceOnly(int cameraId) {
+    INFO("%s", __func__);
+    sp<ICameraService> cs = getCameraService();
+    // Connect the first client.
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc, cameraId);
+    ASSERT(c != 0);
+    // Same client -- ok.
+    ASSERT(cs->connect(cc, cameraId) != 0);
+    // Different client -- not ok.
+    sp<MCameraClient> cc2 = new MCameraClient();
+    ASSERT(cs->connect(cc2, cameraId) == 0);
+    c->disconnect();
+}
+
+void testReconnectFailed() {
+    INFO("%s", __func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    sp<MCameraClient> cc = new MCameraClient();
+    ASSERT(c->connect(cc) != NO_ERROR);
+}
+
+void testReconnectSuccess() {
+    INFO("%s", __func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    sp<MCameraClient> cc = new MCameraClient();
+    ASSERT(c->connect(cc) == NO_ERROR);
+    c->disconnect();
+}
+
+void testLockFailed() {
+    INFO("%s", __func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() != NO_ERROR);
+}
+
+void testLockUnlockSuccess() {
+    INFO("%s", __func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() == NO_ERROR);
+    ASSERT(c->unlock() == NO_ERROR);
+}
+
+void testLockSuccess() {
+    INFO("%s", __func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() == NO_ERROR);
+    c->disconnect();
+}
+
+//
+// Run the connect tests in another process.
+//
+const char *gExecutable;
+
+struct FunctionTableEntry {
+    const char *name;
+    void (*func)();
+};
+
+FunctionTableEntry function_table[] = {
+#define ENTRY(x) {#x, &x}
+    ENTRY(testReconnectFailed),
+    ENTRY(testReconnectSuccess),
+    ENTRY(testLockUnlockSuccess),
+    ENTRY(testLockFailed),
+    ENTRY(testLockSuccess),
+#undef ENTRY
+};
+
+void runFunction(const char *tag) {
+    INFO("runFunction: %s", tag);
+    int entries = sizeof(function_table) / sizeof(function_table[0]);
+    for (int i = 0; i < entries; i++) {
+        if (strcmp(function_table[i].name, tag) == 0) {
+            (*function_table[i].func)();
+            return;
+        }
+    }
+    ASSERT(0);
+}
+
+void runInAnotherProcess(const char *tag) {
+    pid_t pid = fork();
+    if (pid == 0) {
+        execlp(gExecutable, gExecutable, tag, NULL);
+        ASSERT(0);
+    } else {
+        int status;
+        ASSERT_EQ(pid, wait(&status));
+        ASSERT_EQ(0, status);
+    }
+}
+
+void testReconnect(int cameraId) {
+    INFO("%s", __func__);
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc, cameraId);
+    ASSERT(c != 0);
+    // Reconnect to the same client -- ok.
+    ASSERT(c->connect(cc) == NO_ERROR);
+    // Reconnect to a different client (but the same pid) -- ok.
+    sp<MCameraClient> cc2 = new MCameraClient();
+    ASSERT(c->connect(cc2) == NO_ERROR);
+    c->disconnect();
+    cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+}
+
+void testLockUnlock(int cameraId) {
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc, cameraId);
+    ASSERT(c != 0);
+    // We can lock as many times as we want.
+    ASSERT(c->lock() == NO_ERROR);
+    ASSERT(c->lock() == NO_ERROR);
+    // Lock from a different process -- not ok.
+    putTempObject(c->asBinder());
+    runInAnotherProcess("testLockFailed");
+    // Unlock then lock from a different process -- ok.
+    ASSERT(c->unlock() == NO_ERROR);
+    runInAnotherProcess("testLockUnlockSuccess");
+    // Unlock then lock from a different process -- ok.
+    runInAnotherProcess("testLockSuccess");
+    clearTempObject();
+}
+
+void testReconnectFromAnotherProcess(int cameraId) {
+    INFO("%s", __func__);
+
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc, cameraId);
+    ASSERT(c != 0);
+    // Reconnect from a different process -- not ok.
+    putTempObject(c->asBinder());
+    runInAnotherProcess("testReconnectFailed");
+    // Unlock then reconnect from a different process -- ok.
+    ASSERT(c->unlock() == NO_ERROR);
+    runInAnotherProcess("testReconnectSuccess");
+    clearTempObject();
+}
+
+// We need to flush the command buffer after the reference
+// to ICamera is gone. The sleep is for the server to run
+// the destructor for it.
+static void flushCommands() {
+    IPCThreadState::self()->flushCommands();
+    usleep(200000);  // 200ms
+}
+
+// Run a test case
+#define RUN(class_name, cameraId) do { \
+    { \
+        INFO(#class_name); \
+        class_name instance; \
+        instance.init(cameraId); \
+        instance.run(); \
+    } \
+    flushCommands(); \
+} while(0)
+
+// Base test case after the the camera is connected.
+class AfterConnect {
+public:
+    void init(int cameraId) {
+        cs = getCameraService();
+        cc = new MCameraClient();
+        c = cs->connect(cc, cameraId);
+        ASSERT(c != 0);
+    }
+
+protected:
+    sp<ICameraService> cs;
+    sp<MCameraClient> cc;
+    sp<ICamera> c;
+
+    ~AfterConnect() {
+        c->disconnect();
+        c.clear();
+        cc.clear();
+        cs.clear();
+    }
+};
+
+class TestSetPreviewDisplay : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStartPreview : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+
+        ASSERT(c->startPreview() == NO_ERROR);
+        ASSERT(c->previewEnabled() == true);
+
+        surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer
+        surface->clearStat();
+
+        sp<MSurface> another_surface = new MSurface();
+        c->setPreviewDisplay(another_surface);  // just to make sure unregisterBuffers
+                                                // is called.
+        surface->waitUntil(0, 0, 1);  // needs unregisterBuffers
+
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStartPreviewWithoutDisplay : public AfterConnect {
+public:
+    void run() {
+        ASSERT(c->startPreview() == NO_ERROR);
+        ASSERT(c->previewEnabled() == true);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+// Base test case after the the camera is connected and the preview is started.
+class AfterStartPreview : public AfterConnect {
+public:
+    void init(int cameraId) {
+        AfterConnect::init(cameraId);
+        surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        ASSERT(c->startPreview() == NO_ERROR);
+    }
+
+protected:
+    sp<MSurface> surface;
+
+    ~AfterStartPreview() {
+        surface.clear();
+    }
+};
+
+class TestAutoFocus : public AfterStartPreview {
+public:
+    void run() {
+        cc->assertNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 0);
+        c->autoFocus();
+        cc->waitNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 1);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStopPreview : public AfterStartPreview {
+public:
+    void run() {
+        ASSERT(c->previewEnabled() == true);
+        c->stopPreview();
+        ASSERT(c->previewEnabled() == false);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestTakePicture: public AfterStartPreview {
+public:
+    void run() {
+        ASSERT(c->takePicture() == NO_ERROR);
+        cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
+        cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+        cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+        c->stopPreview();
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestTakeMultiplePictures: public AfterStartPreview {
+public:
+    void run() {
+        for (int i = 0; i < 10; i++) {
+            cc->clearStat();
+            ASSERT(c->takePicture() == NO_ERROR);
+            cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
+            cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+            cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+        }
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestGetParameters: public AfterStartPreview {
+public:
+    void run() {
+        String8 param_str = c->getParameters();
+        INFO("%s", static_cast<const char*>(param_str));
+    }
+};
+
+static bool getNextSize(const char **ptrS, int *w, int *h) {
+    const char *s = *ptrS;
+
+    // skip over ','
+    if (*s == ',') s++;
+
+    // remember start position in p
+    const char *p = s;
+    while (*s != '\0' && *s != 'x') {
+        s++;
+    }
+    if (*s == '\0') return false;
+
+    // get the width
+    *w = atoi(p);
+
+    // skip over 'x'
+    ASSERT(*s == 'x');
+    p = s + 1;
+    while (*s != '\0' && *s != ',') {
+        s++;
+    }
+
+    // get the height
+    *h = atoi(p);
+    *ptrS = s;
+    return true;
+}
+
+class TestPictureSize : public AfterStartPreview {
+public:
+    void checkOnePicture(int w, int h) {
+        const float rate = 0.9;  // byte per pixel limit
+        int pixels = w * h;
+
+        CameraParameters param(c->getParameters());
+        param.setPictureSize(w, h);
+        // disable thumbnail to get more accurate size.
+        param.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, 0);
+        param.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, 0);
+        c->setParameters(param.flatten());
+
+        cc->clearStat();
+        ASSERT(c->takePicture() == NO_ERROR);
+        cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+        //cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
+        cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+        cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT,
+                int(pixels * rate));
+        cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0);
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+
+    void run() {
+        CameraParameters param(c->getParameters());
+        int w, h;
+        const char *s = param.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES);
+        while (getNextSize(&s, &w, &h)) {
+            LOGD("checking picture size %dx%d", w, h);
+            checkOnePicture(w, h);
+        }
+    }
+};
+
+class TestPreviewCallbackFlag : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+
+        // Try all flag combinations.
+        for (int v = 0; v < 8; v++) {
+            LOGD("TestPreviewCallbackFlag: flag=%d", v);
+            usleep(100000); // sleep a while to clear the in-flight callbacks.
+            cc->clearStat();
+            c->setPreviewCallbackFlag(v);
+            ASSERT(c->previewEnabled() == false);
+            ASSERT(c->startPreview() == NO_ERROR);
+            ASSERT(c->previewEnabled() == true);
+            sleep(2);
+            c->stopPreview();
+            if ((v & FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
+                cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
+            } else {
+                if ((v & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
+                    cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 10);
+                } else {
+                    cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 1);
+                }
+            }
+        }
+    }
+};
+
+class TestRecording : public AfterConnect {
+public:
+    void run() {
+        ASSERT(c->recordingEnabled() == false);
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        cc->setReleaser(c.get());
+        c->startRecording();
+        ASSERT(c->recordingEnabled() == true);
+        sleep(2);
+        c->stopRecording();
+        usleep(100000); // sleep a while to clear the in-flight callbacks.
+        cc->setReleaser(NULL);
+        cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10);
+    }
+};
+
+class TestPreviewSize : public AfterStartPreview {
+public:
+    void checkOnePicture(int w, int h) {
+        int size = w*h*3/2;  // should read from parameters
+
+        c->stopPreview();
+
+        CameraParameters param(c->getParameters());
+        param.setPreviewSize(w, h);
+        c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        c->setParameters(param.flatten());
+
+        c->startPreview();
+
+        cc->clearStat();
+        cc->waitData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 1);
+        cc->assertDataSize(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, size);
+    }
+
+    void run() {
+        CameraParameters param(c->getParameters());
+        int w, h;
+        const char *s = param.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES);
+        while (getNextSize(&s, &w, &h)) {
+            LOGD("checking preview size %dx%d", w, h);
+            checkOnePicture(w, h);
+        }
+    }
+};
+
+void runHolderService() {
+    defaultServiceManager()->addService(
+            String16("CameraServiceTest.Holder"), new HolderService());
+    ProcessState::self()->startThreadPool();
+}
+
+int main(int argc, char **argv)
+{
+    if (argc != 1) {
+        runFunction(argv[1]);
+        return 0;
+    }
+    INFO("CameraServiceTest start");
+    gExecutable = argv[0];
+    runHolderService();
+    int n = getNumberOfCameras();
+    INFO("%d Cameras available", n);
+
+    for (int id = 0; id < n; id++) {
+        INFO("Testing camera %d", id);
+        testConnect(id);                              flushCommands();
+        testAllowConnectOnceOnly(id);                 flushCommands();
+        testReconnect(id);                            flushCommands();
+        testLockUnlock(id);                           flushCommands();
+        testReconnectFromAnotherProcess(id);          flushCommands();
+
+        RUN(TestSetPreviewDisplay, id);
+        RUN(TestStartPreview, id);
+        RUN(TestStartPreviewWithoutDisplay, id);
+        RUN(TestAutoFocus, id);
+        RUN(TestStopPreview, id);
+        RUN(TestTakePicture, id);
+        RUN(TestTakeMultiplePictures, id);
+        RUN(TestGetParameters, id);
+        RUN(TestPictureSize, id);
+        RUN(TestPreviewCallbackFlag, id);
+        RUN(TestRecording, id);
+        RUN(TestPreviewSize, id);
+    }
+
+    INFO("CameraServiceTest finished");
+}